当前位置: 首页 > article >正文

10个Redis高阶面试题

大家好,我是V哥,过年跟2个大佬小聚,聊到他们招人的标准,偷偷的记下来,以下是为Java高级程序员整理的Redis深度面试题及答案,涵盖高并发、分布式、性能优化等核心场景,结合企业级解决方案和代码示例:


一、Redis高可用与持久化

1. 如何设计一个千万级QPS的Redis高可用架构?

// 架构方案:
1. 多层级缓存:本地缓存(Caffeine+ Redis Cluster(分片)
2. 部署模式:Redis Cluster 6节点(33从)+ Sentinel集群
3. 读写分离:主节点写,从节点读(通过JedisCluster配置readFrom=REPLICA4. 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
   - 设置合理的PELPending 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预扣库存(原子性保证)
   - 令牌桶限流(RateLimiter2. 库存扣减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. 异步处理:
   - 下单成功发送MQKafka
   - 独立服务消费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小时防止数据丢失

考察重点总结:

  1. 原理深度:持久化机制、集群原理、分布式算法
  2. 实战经验:大厂真实场景的问题解决思路
  3. 架构思维:高并发设计、容灾方案、性能优化
  4. 新技术跟踪:Redis 7新特性(Function、Multi-part AOF)

建议候选人结合自身项目经验准备案例,高手的简历项目经验应该是这样的:

  • “在我们的电商系统中,使用Redis Pipeline将抢购接口的TPS从1500提升到8500”
  • “通过优化Hash结构,将用户画像查询响应时间从45ms降低到7ms”

最后

以上是我们聊天中说到的10个问题,回来整理成这篇文章,分享给大家,当然关于Redis 的面试题还有很多知识点,需要的朋友可以一搜一大把,或者私信 V 哥分享给你,如果你正在准备往上跳一跳,希望可以帮助到你,关注威哥爱编程,一起为技术成长。


http://www.kler.cn/a/535310.html

相关文章:

  • 哈希(Hashing)在 C++ STL 中的应用
  • S4 HANA (递延所得税传输)Deferred Tax Transfer - S_AC0_52000644
  • 【PyTorch】解决Boolean value of Tensor with more than one value is ambiguous报错
  • [NKU]C++安装环境 VScode
  • bat脚本实现自动化漏洞挖掘
  • 【重生之学习C语言----杨辉三角篇】
  • 尚硅谷课程【笔记】——大数据之Shell【二】
  • SQL LEFT JOIN 详解
  • 【Elasticsearch】post_filter
  • 嵌入式经典面试题之操作系统(三)
  • 洛谷P2367 语文成绩(一维差分模板)
  • Hive自定义函数简介及实践案例
  • C# MAUI 注册服务
  • 如何在本机或服务器上部署运行DeepSeek R1模型
  • 高级java每日一道面试题-2025年01月29日-框架篇[SpringBoot篇]-SpringBoot 实现热部署有哪几种方式?
  • tcp/ip网络协议,tcp/ip网络协议栈
  • RabbitMQ 从入门到精通:从工作模式到集群部署实战(二)
  • Day52:type()函数
  • RocketMQ实战—5.消息重复+乱序+延迟的处理
  • 记录 | WPF基础学习自定义按钮
  • 【matlab代码】平方根扩展卡尔曼滤波(SR EKF)例程,三维非线性系统的滤波
  • 【Rust自学】20.2. 最后的项目:多线程Web服务器
  • 在远程 Linux 服务器上运行 Jupyter Notebook(.ipynb 文件)
  • idea 启动 thingsboard
  • iOS--SDWebImage源码解析
  • 《Node.js Express 框架》