【Redis 高级实战】分布式缓存、 多级缓存与最佳实践一篇打通
description: 从持久化、主从哨兵、分片集群到多级缓存落地再到 BigKey、Pipeline、慢查询与安全加固系统梳理 Redis 高级能力。在掌握 Redis 基础命令之后一到线上就会遇到单机瓶颈、高可用、数据一致性、缓存击穿、BigKey、慢查询、安全风险……本文把讲义里的“高级必修课”整理成一篇可直接发布的系统教程覆盖架构、原理和落地代码思路。⚡ 快速参考先给答案你何时需要高级篇单机 Redis 扛不住、数据太多、需要自动故障转移、需要更高吞吐/更低延迟、多层缓存治理、缓存一致性核心结论Redis 作为缓存时不必强求复杂持久化但必须做好高可用与治理慢查询/BigKey/安全主从 哨兵优先满足大部分业务万不得已再上大规模分片集群多级缓存能把压力从 Tomcat/数据库“分流”但引入 OpenResty/Lua 后要做好工程化与一致性最短路径高可用主从 - 哨兵自动故障转移海量数据写扩展分片集群hash slot性能体系浏览器缓存 - Nginx/OpenResty 本地缓存 - Redis - JVM 本地缓存 - DB避坑提醒生产禁用/限制KEYS、FLUSHALL、CONFIG SET重点治理 BigKey、慢查询阈值、序列化与 key 设计 学习目标理解 Redis 的两种持久化、主从同步、哨兵故障转移、分片集群 hash slot 原理。搭建“多级缓存”体系知道每一层缓存解决什么问题、带来什么风险。掌握线上最佳实践key 设计、BigKey 治理、批处理优化、慢查询与安全加固。一、基础概念是什么1.1 单机 Redis 的四大问题为什么要上集群单机 Redis 常见瓶颈集中在数据丢失风险进程宕机、机器故障需要持久化/复制并发能力上限单实例吞吐有限需要读写分离/水平扩展海量数据存储内存受限需要分片高可用主节点宕机后要自动切换需要哨兵/集群能力1.2 多级缓存是什么为什么要多级传统“Tomcat - Redis - DB”会有两个典型问题请求都要进 TomcatTomcat 成为系统瓶颈Redis 缓存失效时对 DB 形成瞬时冲击多级缓存把缓存前移和下沉浏览器缓存静态资源Nginx/OpenResty 本地缓存shared dictRedis 分布式缓存Tomcat JVM 本地缓存CaffeineDB二、原理详解为什么这样做2.1 Redis 持久化RDB vs AOFRedis 常见持久化两种RDB快照定期把内存数据生成快照文件dump.rdbAOF追加日志把每次写命令追加记录到 aof 文件2.1.1 RDB 执行时机与原理RDB 触发方式save阻塞少用bgsave子进程异步Redis 停机时redis.conf中配置触发条件例如save 900 1 save 300 10 save 60 10000RDB 的关键点bgsave会fork子进程利用copy-on-write子进程写 RDB主进程继续响应请求。RDB 缺点两次快照间隔期可能丢数据fork/压缩/写盘耗时。2.1.2 AOF 策略与重写AOF 开关redis.confappendonly yes appendfilename appendonly.aof刷盘策略appendfsync always最安全性能差appendfsync everysec默认性能与安全平衡常用appendfsync no交给 OS风险高AOF 重写bgrewriteaof会把“多次覆盖写”压缩成最少命令减少 AOF 体积。2.1.3 选型建议作为“缓存”的 Redis优先保证可用性与性能持久化不一定必须看业务容忍度需要更高数据安全RDB AOF 组合更稳2.2 主从复制全量同步 vs 增量同步主从核心价值读写分离 数据备份。2.2.1 全量同步第一次建立主从关系时slave 发送自己的replid与offsetmaster 发现replid不一致触发全量同步master 生成 RDB 发给 slaveslave 清空旧数据并加载master 把同步期间的写命令记录到repl_backlog并补发给 slave2.2.2 增量同步与 repl_backlogslave 恢复连接时带上 offsetmaster 从repl_backlog里找 offset 之后的命令增量补齐。注意repl_backlog是固定大小环形数组如果 slave 断开太久导致 offset 被覆盖只能再做全量同步。2.2.3 主从优化建议开启无磁盘复制repl-diskless-sync yes降低全量同步磁盘 I/O合理增大repl_backlog减少被覆盖导致的全量同步slave 太多时用“主-从-从”链式结构降低 master 压力2.3 哨兵 Sentinel自动故障转移哨兵三大作用监控持续ping检测 master/slave故障转移master 宕机自动提升 slave 为 master通知/服务发现把新 master 信息通知给客户端2.3.1 主观下线与客观下线主观下线单个 sentinel 判断实例超时未响应客观下线达到 quorum 的 sentinel 都认为下线2.3.2 选主规则面试常问大致顺序slave 与 master 断开时间太久超过阈值直接淘汰slave-priority越小优先级越高0 永不参与offset 越大数据越新优先级越高运行 id 越小优先级越高2.3.3 Spring/Lettuce 客户端如何适配哨兵Spring Data Redis Lettuce 能感知 sentinel 的主从变化并自动切换。配置示例spring:redis:sentinel:master:mymasternodes:-192.168.150.101:27001-192.168.150.101:27002-192.168.150.101:27003并配置读策略读写分离BeanpublicLettuceClientConfigurationBuilderCustomizerclientConfigurationBuilderCustomizer(){returnbuilder-builder.readFrom(ReadFrom.REPLICA_PREFERRED);}2.4 分片集群海量数据与写扩展主从/哨兵解决了高可用与读扩展但海量数据与写扩展需要分片集群。2.4.1 hash slot16384 插槽原理Redis Cluster 把 key 映射到 0~16383 插槽插槽再分配到不同 masterkey 含{}{}内是“有效部分”key 不含{}整个 key 是有效部分有效部分做 CRC16 哈希对 16384 取余得到 slot - 路由到对应节点。2.4.2 hash tag 的用法如果希望同一类 key 落同一个 slot方便事务/lua/批处理{user:1001}:profile {user:1001}:orders有效部分相同 - slot 相同 - 节点相同。三、完整实战代码怎么做3.1 多级缓存的落地架构目标形态请求路径示例商品详情接口浏览器 - Nginx 反向代理 - OpenResty本地缓存 Redis- Tomcat 集群JVM 缓存- DB关键点OpenResty 需要 Lua 编程shared dict、本地缓存读 Redis回源 TomcatTomcat 内用 Caffeine 做 JVM 本地缓存3.2 JVM 进程缓存CaffeineTomcat 层缓存适用访问频繁、数据量较小、追求极致性能的查询无网络开销。Caffeine 核心用法思路定义CacheK, Vbeancache.get(key, k - 查询DB)未命中回源 DB设置容量上限/过期策略避免内存撑爆常用策略基于容量maximumSize基于时间expireAfterWrite3.3 OpenRestyNginx 编程本地缓存 Redis 回源OpenResty 通过lua_shared_dict提供 worker 共享本地缓存lua_shared_dict item_cache 150m;Lua 层读写item_cache:get(key)item_cache:set(key, val, expireSeconds)最终查询函数思路伪代码read_data(key): 1) 查本地缓存 2) 未命中 - 查Redis 3) 仍未命中 - 回源Tomcat(http) 4) 写回本地缓存不同数据不同TTL 5) 返回3.4 Redis 缓存预热避免冷启动打爆 DB冷启动服务刚启动 Redis 没缓存大量请求回源 DB。预热思路项目启动后批量查询热点或全量数据写入 Redis建议按 key 前缀分类如item:id:{id}Spring 里常见做法实现InitializingBean在依赖注入完成后执行预热逻辑。3.5 缓存同步一致性三策略常见三种设置 TTL简单但时效差同步双写强一致但侵入代码、耦合高异步通知低耦合允许短暂不一致MQ / Canal基于 Canal 的优势业务代码零侵入通过订阅 MySQL binlog 触发缓存更新。四、场景应用用在哪里场景 1高并发商品详情多级缓存需求页面高并发访问Tomcat/DB 扛不住方案OpenResty 本地缓存短TTL Redis Tomcat JVM 缓存Caffeine收益把大量读请求挡在更前面减少 Tomcat 压力DB 峰值更稳场景 2数据更新频繁Canal 异步同步需求商品价格/库存更新后缓存尽快一致方案Canal 监听 binlog - 通知缓存服务更新 Redis/JVM 缓存收益业务代码更干净多个缓存服务可统一同步五、开发避坑总结高频错误5.1 BigKey一定要治理推荐阈值经验值单个 key 的 value 10KB集合类型元素数量 1000危害网络阻塞少量 QPS 占满带宽数据倾斜某节点内存爆主线程阻塞集合运算耗时CPU 压力序列化/反序列化发现方式redis-cli -a 密码 --bigkeysSCANstrlen/hlen/llen/scard/zcard自行统计分析 RDB第三方工具/ 网络监控删除建议Redis 4.0 优先UNLINK异步删除避免阻塞5.2 Key 设计最佳实践格式业务名:数据名:id简短尽量不超过 44 字节利于 embstr 编码与内存友好不要特殊字符5.3 批处理优化MSET vs Pipeline瓶颈往往在网络往返不在 Redis 执行本身MSET/HMSET适合部分类型Pipeline适合多命令批处理集群下批处理多 key 不同 slot 会失败需要按 slot 分组并行 slot 推荐或用 hash tag 强制落同 slot但可能数据倾斜5.4 慢查询治理Redis 单线程要警惕建议配置slowlog-log-slower-than建议 1000 微秒按业务调整slowlog-max-len建议 1000常用命令SLOWLOG LENSLOWLOG GET [n]SLOWLOG RESET5.5 安全加固线上必做高危条件Redis 未设密码暴露公网bind 0.0.0.0允许CONFIG SET使用 root 启动 Redis建议必设密码bind限制网卡 防火墙禁用危险命令rename-commandkeys/flushall/flushdb/config set等不要 root 运行避免默认端口暴露六、面试考点能说出来6.1 高频问题Q1RDB 与 AOF 区别ARDB 是快照恢复快但可能丢窗口期数据AOF 是追加日志数据更完整但体积大需要重写压缩。Q2主从全量/增量同步如何判断A看replid是否一致、offset 是否能在repl_backlog中找到offset 被覆盖只能全量。Q3Sentinel 如何判断下线A单个 sentinel 超时未响应为主观下线达到 quorum 多数认为下线为客观下线。Q4Redis Cluster 为啥是 16384 slot怎么路由 keyA对 key 有效部分做 CRC16取余 16384 得 slotslot 映射到节点。6.2 进阶追问集群下为什么 lua/事务麻烦 - 原子性要求 key 在同一节点跨节点无法保证。为什么不建议大规模集群 - 节点互 ping 带宽开销、兼容性问题、数据倾斜与客户端复杂度上升。七、总结复盘与下一步本文解决了Redis 从“会用”到“能上生产”的关键能力拼图高可用、扩展、性能体系、治理与安全。你现在可以为业务选择主从/哨兵/集群方案落地多级缓存并具备线上排查与优化抓手。本文为MY_TEUCK原创实战学习笔记持续更新Java后端与AI应用领域干货问题欢迎评论区交流。