10个Redis高阶面试题
大家好,我是V哥,过年跟2个大佬小聚,聊到他们招人的标准,偷偷的记下来,以下是为Java高级程序员整理的Redis深度面试题及答案,涵盖高并发、分布式、性能优化等核心场景,结合企业级解决方案和代码示例:
一、Redis高可用与持久化
1. 如何设计一个千万级QPS的Redis高可用架构?
// 架构方案:
1. 多层级缓存:本地缓存(Caffeine)+ Redis Cluster(分片)
2. 部署模式:Redis Cluster 6节点(3主3从)+ Sentinel集群
3. 读写分离:主节点写,从节点读(通过JedisCluster配置readFrom=REPLICA)
4. Proxy层:使用Redis Cluster Proxy统一接入
5. 监控体系:Prometheus + Grafana监控节点状态、慢查询
// 容灾方案:
- 故障转移:Sentinel自动切换主从
- 数据持久化:AOF每秒刷盘 + RDB每小时备份
- 跨机房同步:通过Redis-Shake工具进行异地双活
2. AOF重写期间内存暴涨如何解决?
// 问题场景:
当Redis实例内存使用率超过80%时触发AOF重写,导致fork子进程时内存翻倍
// 解决方案:
1. 配置优化:
- aof-rewrite-incremental-fsync yes(增量同步)
- auto-aof-rewrite-percentage 80(降低重写阈值)
2. 内存控制:
- 使用Hash分桶存储大Key(如用户画像数据)
- 开启activedefrag yes自动内存碎片整理
3. 运维方案:
- 在业务低谷期通过BGREWRITEAOF手动触发
- 使用Redis内存分析工具(rdb-tools)定位大Key
二、数据结构与高级特性
3. 如何用Redis实现延迟队列?
// 场景:订单30分钟未支付自动关闭
public class DelayQueueService {
private static final String DELAY_QUEUE = "order:delay:queue";
// 生产消息
public void produceDelayMessage(String orderId, long delaySeconds) {
Jedis jedis = jedisPool.getResource();
long score = System.currentTimeMillis() + delaySeconds * 1000;
jedis.zadd(DELAY_QUEUE, score, orderId);
}
// 消费消息
public void consumeDelayMessages() {
while (!Thread.interrupted()) {
Set<String> orders = jedis.zrangeByScore(DELAY_QUEUE, 0,
System.currentTimeMillis(), 0, 1);
if (!orders.isEmpty()) {
String orderId = orders.iterator().next();
if (jedis.zrem(DELAY_QUEUE, orderId) > 0) {
handleExpiredOrder(orderId); // 处理过期订单
}
} else {
Thread.sleep(500); // 避免CPU空转
}
}
}
}
4. Redis Stream如何保证消息可靠性?
// 消息丢失防护方案:
1. 生产者确认:
- 使用XADD命令返回消息ID确认写入成功
- 集群模式下确保消息写入主节点
2. 消费者组设计:
- 创建消费者组时设置$符号表示只接收新消息
- 使用XREADGROUP BLOCK 2000 GROUP group1 consumer1 STREAMS orders >
3. 消息确认机制:
- 处理完成后执行XACK orders group1 messageId
- 设置合理的PEL(Pending Entries List)超时时间
4. 死信处理:
- 监控XPENDING输出
- 对超过重试次数的消息转存死信Stream
三、分布式与性能优化
5. RedLock算法真的安全吗?如何改进?
// 争议点分析:
1. 时钟跳跃问题:NTP同步导致锁过期时间计算错误
2. GC停顿问题:Java应用STW导致锁失效
3. 网络延迟问题:主节点写入未同步到从节点时故障转移
// 改进方案(Redisson实现):
RLock lock = redisson.getLock("orderLock");
lock.lock(30, TimeUnit.SECONDS);
// 底层优化:
1. 看门狗机制:每10秒续期锁(默认30秒过期)
2. 故障转移时通过发布订阅同步锁状态
3. 组合使用:
- 锁标记(UUID)+ Lua脚本保证原子性
- 业务逻辑增加幂等校验
6. 大Value导致集群节点内存不均怎么处理?
// 场景:某节点存储10GB的缓存报表数据
// 解决方案:
1. 数据分片:
- 对Key进行hash取模:report:{id} -> report:{id%1024}
- 使用Hash Tag强制分片:{report}.part1, {report}.part2
2. 存储优化:
- 使用ZSTD压缩算法(Redis 6.2+)
- 拆分JSON为多个Hash字段
3. 架构升级:
- 单独部署大容量节点作为数据节点
- 使用RedisTimeSeries处理时序型大数据
四、缓存疑难问题
7. 缓存与数据库双写不一致如何解决?
// 经典场景:先更新数据库再删除缓存失败
// 解决方案对比:
方案 | 一致性 | 复杂度 | 适用场景
---|---|---|---
Cache Aside | 最终 | 低 | 读多写少
Read/Write Through | 强 | 高 | 配置中心
Delay Double Delete | 最终 | 中 | 写频繁场景
// 最佳实践(Delay Double Delete伪代码):
public void updateProduct(Product product) {
// 第一次删除
redis.del(product.getId());
// 更新数据库
db.update(product);
// 延时二次删除
executor.schedule(() -> {
redis.del(product.getId());
}, 1, TimeUnit.SECONDS);
}
8. 如何设计百万级并发秒杀系统?
// 分层防护体系:
1. 流量削峰:
- Redis INCR预扣库存(原子性保证)
- 令牌桶限流(RateLimiter)
2. 库存扣减Lua脚本:
String script =
"local stock = tonumber(redis.call('GET', KEYS[1])) " +
"if stock > 0 then " +
" redis.call('DECR', KEYS[1]) " +
" return 1 " +
"end " +
"return 0 ";
3. 热点Key优化:
- 本地缓存+Redis多副本(读写分离)
- Key拆分:stock_1, stock_2...(随机路由)
4. 异步处理:
- 下单成功发送MQ到Kafka
- 独立服务消费MQ完成订单创建
五、高级运维与监控
9. Redis内存碎片率超过1.5如何处理?
// 诊断命令:
redis-cli info memory | grep ratio
> mem_fragmentation_ratio:1.72
// 处理步骤:
1. 重启节点(低峰期主从切换)
2. 配置优化:
- activedefrag yes
- hz 10(提高后台任务频率)
3. 存储优化:
- 避免使用大量TTL相近的Key
- 使用jemalloc内存分配器
4. 监控报警:
- 设置碎片率>1.5触发告警
- 使用Redis-benchmark压力测试验证
10. Redis集群如何实现平滑扩缩容?
// 扩容流程:
1. 准备新节点:redis-server --cluster-enabled yes
2. 加入集群:redis-cli --cluster add-node new_ip:port existing_ip:port
3. 数据迁移:
redis-cli --cluster reshard --from all --to <new_node_id> --slots 4096 --yes
4. 流量切换:更新客户端集群配置
// 缩容注意事项:
- 迁移前检查节点是否为从节点
- 使用redis-cli --cluster rebalance移除节点
- 保留空节点24小时防止数据丢失
考察重点总结:
- 原理深度:持久化机制、集群原理、分布式算法
- 实战经验:大厂真实场景的问题解决思路
- 架构思维:高并发设计、容灾方案、性能优化
- 新技术跟踪:Redis 7新特性(Function、Multi-part AOF)
建议候选人结合自身项目经验准备案例,高手的简历项目经验应该是这样的:
- “在我们的电商系统中,使用Redis Pipeline将抢购接口的TPS从1500提升到8500”
- “通过优化Hash结构,将用户画像查询响应时间从45ms降低到7ms”
最后
以上是我们聊天中说到的10个问题,回来整理成这篇文章,分享给大家,当然关于Redis 的面试题还有很多知识点,需要的朋友可以一搜一大把,或者私信 V 哥分享给你,如果你正在准备往上跳一跳,希望可以帮助到你,关注威哥爱编程,一起为技术成长。