
简介Redis核心技术与实战.zip 是一份面向后端开发与运维工程师的Redis系统学习资料包围绕核心原理与实战场景展开。内容按课程篇章组织开篇词1讲、基础篇10讲、实践篇28讲覆盖键值数据库基本架构、五种数据结构的适用场景、单线程高性能IO模型、AOF日志与RDB内存快照、主从复制与哨兵高可用机制、切片集群扩容方案以及String误用、海量key统计、GEO新数据类型、时间序列数据保存、消息队列方案、单线程阻塞规避、CPU结构影响、响应延迟变慢排查等实践主题能帮助读者从原理到调优建立完整Redis知识体系。压缩包大小约856MB页面未显示文件总数与类型明细暂以学习热度为参考已有47人学习。整体适合希望深入理解Redis内部运行机制、解决线上性能与数据一致性问题的开发者按需学习。1. 从键值数据库到生产主力这套 Redis 实战资源能帮你打通什么Redis 最常被误解的一句话是「就是个缓存」。真上了生产你会发现String 的内存膨胀、主从切换时的全量复制、bigkey 阻塞单线程、缓存穿透打垮后端随便一个都能让响应从毫秒级跳到秒级。这套「Redis核心技术与实战」把 10 讲基础加 28 讲实践串成了一条完整链路从键值数据库的基本架构、五种数据结构的底层编码、AOF 与 RDB 持久化到主从同步、哨兵切换、切片集群再到亿级 keys 统计、消息队列选型、延迟波动排查。适合两类人被 Redis 面试题问住的应用开发以及已经在用 Redis 但说不清「为什么变慢」的运维工程师。它不是命令大全而是把原理和场景对应起来的实战笔记照着走一遍能省下不少自己踩坑的时间。2. 先看清黑匣子内部数据结构、IO 模型与持久化该信什么2.1 五种基础数据结构选型前先看清复杂度与编码课程 01 讲先把一个键值数据库的骨架拆开存储引擎、操作接口、内存分配、持久化、网络框架每一块各自承担什么职责。02 讲紧接着抛出一个反直觉的结论——以快著称的 Redis 也有慢操作而这些慢操作绝大多数不是命令本身慢而是数据结构用错了位置。先记住一个排查命令任何场景都适用# 查看某个 key 的实际底层编码 redis-cli OBJECT ENCODING mykey # 查看 key 的类型 redis-cli TYPE mykey输出可能是ziplist、hashtable、skiplist、intset这类结果。OBJECT ENCODING的价值在于它告诉你 Redis 在内部到底用了什么结构存储这个 key而不是看你在代码里写的是Set还是List。常见做法是元素少时用压缩结构超过阈值自动转为标准结构比如 hash 默认元素少于 512 个且值小于 64 字节时用 ziplist超过后转 hashtable。参数说明这两个命令都不会触发阻塞可以放心用在线上。TYPE返回的是对外暴露的五种类型OBJECT ENCODING返回的是内部编码两者结合能判断一个 key 是否已经被转换到了预期结构。课程里反复强调的一点是选型不是凭感觉而是看操作复杂度。列表型数据频繁做头尾弹出就用 List需要按 score 排序就用 ZSet需要快速判断存在性就用 Set需要为每个用户维护独立计数就用 Hash——但 Hash 也不是无脑用字段过多时底层从 ziplist 转成 hashtable 后单字段更新的内存开销会明显上升。02 讲还专门讨论了那些「看着快、实际慢」的操作比如SORT的复杂度、KEYS *的全库扫描、LRANGE的大范围取值。这些命令在数据量小的时候无感数据量过万后延迟会从微秒级跳到几十毫秒级。把这些命令列进自己的禁用清单比事后排查快得多。2.2 AOF 与 RDB持久化参数不是默认就能用的课程 04 讲和 05 讲分别讲 AOF 日志和 RDB 内存快照。很多人在本地开发时只用了默认配置觉得「能跑就行」但上了生产后宕机恢复的速度和数据丢失的窗口直接由这两个参数决定。先看一组最小可用的持久化配置# redis.conf 关键持久化参数 appendonly yes # 开启 AOF appendfsync everysec # 每秒刷盘系统默认值 no-appendfsync-on-rewrite no # AOF 重写期间是否暂停 fsync save 900 1 # 900 秒内至少 1 次写操作触发 RDB save 300 10 # 300 秒内至少 10 次写操作触发 RDB save 60 10000 # 60 秒内至少 10000 次写操作触发 RDB逻辑说明appendonly yes开启后每个写命令都会追加到 AOF 文件appendfsync有三个取值——always每条命令都刷盘、everysec每秒刷一次、no交给操作系统决定。save配置则是 RDB 的触发条件满足任意一条就执行快照。参数说明绝大多数生产环境用everysec它最多丢 1 秒的数据换来的是单条写入不用等磁盘 fsync 完成。always最安全但吞吐量下降明显适合对数据完整性极度敏感的财务类业务。save 900 1这类配置意味着你在 10 分钟内有 1 次写入就会生成快照如果写入量极大快照会非常频繁需要考虑延长间隔或者只在业务低峰期手动执行BGSAVE。AOF 和 RDB 的取舍可以整理成一张表维度RDBAOF恢复速度快直接加载二进制快照慢需要重放所有写命令数据丢失窗口取决于 save 配置可能丢较多everysec 最多丢 1 秒文件大小紧凑较大需要定期 rewrite对性能影响fork 时可能造成内存翻倍刷盘策略影响写入延迟课程里特别提到一个容易被忽略的点RDB 生成时使用 fork 子进程依赖操作系统的写时复制COW如果父进程在这期间有大量写入内存会被复制一份物理内存不足时可能触发 swap这会让 Redis 整体变慢。这个坑基本只有线上环境才能踩到本地小数据量完全无感。2.3 单线程 IO 模型快在哪又会在哪卡住03 讲的核心结论是Redis 单线程快不是因为它把 CPU 用到了极限而是因为所有操作都在内存中完成加上 IO 多路复用把网络读写和命令处理解耦。瓶颈不在 CPU而在网络带宽、磁盘 fsync 频率和 fork 子进程的开销。单线程模型最大的软肋是一个耗时的命令会堵住后面所有请求。课程里给了一个很实在的排查手段# 扫描全库的大 key找出潜在的阻塞源 redis-cli --bigkeys # 查看当前是否有慢查询 redis-cli SLOWLOG GET 10--bigkeys会遍历所有 key按类型统计最大的几个输出每个 key 的类型、大小和元素个数。它本质上是执行SCAN而不是KEYS *所以不会一次性阻塞整个实例太久但在超大实例上依然建议在低峰期跑。SLOWLOG GET 10返回最近 10 条耗时超过阈值的命令阈值由slowlog-log-slower-than控制单位是微秒默认 10000 微秒即 10 毫秒。关键认知是慢查询日志里出现的不一定是「操作 N 个元素的大命令」更多时候是「恰好那一刻网络抖动导致命令处理时间变长」。所以课程的做法是把这两条命令组合起来看——先看是否有持续的大 key 操作再看慢查询的时间分布是否和流量高峰吻合。3. 高可用三件套主从同步、哨兵与切片集群怎么配才不出事3.1 主从复制全量复制与增量复制的切换条件06 讲的主从同步是这个系列里含金量最高的一讲之一。很多人只知道replicaof配一下就能挂主从但主库挂了再起来、网络断了再恢复这几个场景下的行为才是真正的分水岭。先看基本配置# 从库 redis.conf replicaof 10.0.0.1 6379 # 主观判断主从是否同步 redis-cli INFO replicationINFO replication会输出每个从库的master_repl_offset和slave_repl_offset两个偏移量。主库的写入位置和从库的复制位置一致时才是真正的同步完成只看连接状态connected不能代表数据一致。排查主从延迟时课程给的建议是优先看偏移量差值而不是看网络延迟。增量复制依赖一个关键配置repl-backlog-size默认是 1MB。这个值决定了从库断线重连后能走增量复制还是必须全量复制。如果网络抖动导致主从断开超过 backlog 能覆盖的写入量Redis 会直接退化为全量复制——全量复制要把整个 RDB 快照发给从库大实例上这个过程可能持续几十秒甚至数分钟期间主库的 CPU 和带宽都会被打满。常见做法是把repl-backlog-size调整为mem_size * 0.1或更大比如 16GB 内存的实例配 2GB 的 backlog。血泪经验是全量复制本身不可怕可怕的是它在业务高峰期被触发导致延迟雪崩。所以关键不是「消除全量复制」而是「控制全量复制的触发频率」。手段包括调大 backlog、避免频繁重启从库、主库避免执行FLUSHALL之类的危险命令。3.2 哨兵机制主观下线与客观下线的完整判定07 讲和 08 讲讲哨兵这是理解 Redis 高可用最绕的一段。关键要先分清两个概念——主观下线sdown和客观下线odown。主观下线是单个哨兵实例自己觉得主库没反应了客观下线是多个哨兵都确认主库不可用达到 quorum 后才会触发故障转移。这中间有一个最常见的问题网络分区导致主库其实活着但哨兵之间无法互通可能误判。课程给的解释是quorum 只决定是否触发切换真正执行切换还需要过半数哨兵同意也就是majority这两个数字经常被混淆。一份最小可用的哨兵配置# sentinel.conf sentinel monitor mymaster 10.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 15000参数说明monitor后面的数字 2 是 quorum表示至少 2 个哨兵节点认为主库下线才会触发切换down-after-milliseconds5000 表示 5 秒内主库没有响应就判定为主观下线failover-timeout15000 表示故障转移的超时窗口超过这个时间没完成会再次重试。排障时看哨兵的日志比看 Redis 日志更直接。哨兵日志里会出现sdown、odown、failover-start这些状态标记顺着这个序列就能判断一次故障切换从触发到完成的完整链路。如果发现odown之后迟迟没有failover-start大概率是 quorum 和 majority 的数字关系没配好或者哨兵节点数本身就是偶数导致投票无法过半。3.3 切片集群加内存还是加实例取决于数据访问模式09 讲的主题是切片集群核心决策是数据增多了该加内存还是加实例。课程的观点很明确——这个决策不由数据总量决定而是由访问分布决定。Redis Cluster 把整个 keyspace 分成 16384 个 slot每个节点负责一段。写入时 key 经过 CRC16 哈希后映射到某个 slot再由 slot 落到对应节点。查看当前 slot 分布# 查看每个节点负责的 slot 范围 redis-cli -p 6379 CLUSTER SLOTS # 查看 key 实际落在哪个 slot redis-cli -p 6379 CLUSTER KEYSLOT mykeyCLUSTER SLOTS 输出格式是起始slot 结束slot 主节点IP 端口 从节点IP 端口一眼能看出 slot 是否均匀。如果每个节点负责的 slot 数量差不多但某几个节点的流量明显偏高那就是热点 key 问题——比如某个商品的维表被高频访问所有请求都打在同一个 slot 上。这时候加内存没用因为热点是访问集中而不是容量不够正确做法是给热点 key 加随机后缀拆成多个 key 分散到不同 slot或者引入本地缓存扛掉一部分读流量。反过来如果节点内存使用率普遍接近上限但 CPU 正常那才是真正需要加内存或加实例的信号。课程里给了一个很朴素的判断标准先看CLUSTER INFO里的cluster_state是否 ok再看每个节点的used_memory是否接近maxmemory如果都没问题最后才考虑 slot 迁移。4. 实践篇的硬核场景亿级统计、String 陷阱与消息队列4.1 String 不是万金油内存翻倍与序列化开销11 讲标题是「万金油的 String为什么不好用了」。常见场景是把一个对象整个序列化成 JSON 塞进 String读的时候再反序列化。这在数据量小的时候没有问题但课程提到了一个很容易被忽略的代价每次修改一个字段都要取出整个字符串、反序列化、改字段、再序列化、写回反复多次后 CPU 和内存都被浪费。更隐蔽的问题是内存的膨胀系数。String 类型的 SDS 结构本身有头部开销存小对象时这部分占比不小。课程给的改法是换成 Hash# 不推荐对象整体存 String SET user:1001 {name: alice, age: 25, level: 3} # 推荐字段级存 Hash HSET user:1001 name alice age 25 level 3 HINCRBY user:1001 level 1逻辑说明HSET把对象拆成字段存储修改 level 时只需要HINCRBY一个字段不需要把整个对象读出来再写回去。这在频繁更新单字段的热点场景下能明显降低 CPU 和内存带宽开销。参数说明如果 Hash 字段数膨胀到超过 512 或字段总长度超过 64 字节底层会从 ziplist 转为 hashtable内存开销会变大但换来的是 O(1) 的字段访问。如果字段数预期会大量增长建议一开始就预估好或在业务层约定一个合理的字段数量上限。课程里的建议是字段数在百级以内用 Hash 收益最大如果字段数会涨到千级以上回到 String 可能更合适——选型没有银弹只有场景匹配。4.2 亿级 keys 统计Hash、Set、HyperLogLog 与 Bloom12 讲面对的是「一亿个 keys 要统计」的场景。课程把统计需求拆成三类精确统计唯一值、近似统计唯一值、判断某个值是否存在。这三类需求的选型完全不同。精确唯一值统计用 SetSADD加元素SCARD取基数。一亿个 key 全部塞进 Set内存会非常可观这是它最大的限制。近似统计用 HyperLogLog做去重统计时内存固定为 12KB 左右但误差在 0.81% 左右。判断存在性则适合用布隆过滤器每天几亿条去重逻辑用几十 MB 内存就能搞定。# HyperLogLog 基本用法 PFADD uv:2024-06-01 user123 user456 user789 PFCOUNT uv:2024-06-01 # 合并多天的数据再统计 PFMERGE uv:2024-06 uv:2024-06-01 uv:2024-06-02 PFCOUNT uv:2024-06逻辑说明PFADD添加元素PFCOUNT返回基数估计值PFMERGE可以把多天的 HyperLogLog 合并成一个再统计总量。这三个命令覆盖了日常 UV 统计的主要诉求。参数说明HyperLogLog 的误差是不可配置的标准误差约 0.81%但内存恒定在 12KB这是它相比 Set 的核心优势。需要注意的是PFADD对同一个元素重复添加不会增加计数这是「去重」语义的基础。如果业务对 0.81% 的误差不能接受——比如金额相关的对账场景——那只能用 Set没有折中方案。课程还提到面试高频考点如何判断一个 key 是否存在于亿级集合中。Set 的SISMEMBER是精确的但内存大布隆过滤器的BF.EXISTS是近似的但有假阳性率。Redis 的布隆过滤器不是原生数据结构需要加载 RedisBloom 模块。这是个很典型的选择题内存换精度还是精度换内存。4.3 消息队列与时间序列Stream 与自定义数据类型15 讲讲消息队列14 讲讲时间序列13 讲讲 GEO。这三个场景在生产中都很常见而且课程给了一个清晰的选型框架。消息队列方面Redis 有两条技术路线一是 Pub/Sub发布订阅模式实时性强但消息不落盘消费者挂了就丢二是 StreamRedis 5.0 引入的原生消息队列支持消费者组、消息确认、Pending 列表消息持久化在 Redis 内。# Stream 生产者 XADD orders * user_id 1001 amount 99.9 # Stream 消费者组 XGROUP CREATE orders order-group 0 XREADGROUP GROUP order-group consumer-1 COUNT 10 STREAMS orders 逻辑说明XADD往 Stream 里追加消息*让 Redis 自动生成消息 ID返回的 ID 是时间戳加序号天然有序XGROUP CREATE创建消费者组XREADGROUP从组里读取消息表示只读尚未投递给任何消费者的新消息。参数说明COUNT 10控制每次拉取条数避免一次拉太多导致处理不过来消息 ID 中的时间戳部分可以用来做时间范围查询这是 Stream 相比 List 做队列的核心优势。课程里对比了 List 做队列的局限没有消费者组概念多个消费者同时LPOP可能产生竞争且消息确认机制需要自己实现。如果业务需要消息可靠投递、失败重试、多消费者分流Stream 是更稳的选择。时间序列数据方面课程介绍了 RedisTimeSeries 模块它针对按时间戳写入、按时间范围聚合查询的场景做了专门优化。如果只是少量时间序列数据用 Sorted Set 也能模拟score 存时间戳member 存数值。但数据量上来后Sorted Set 的查询和聚合效率都不如专门的数据结构。GEO 也类似本质是 ZSet 的封装用GEOADD存经纬度GEOSEARCH查附近的人适合小众的地理位置场景数据量大了依然要考虑分片。5. 性能排查与避坑延迟波动、CPU 结构与常见翻车现场5.1 延迟变慢先查什么慢查询日志、latency monitor 与网络18 和 19 讲的主题是「波动的响应延迟」。课程的核心观点是Redis 变慢不要先怀疑 Redis 本身先分清楚是命令慢、网络慢还是环境慢。排查的第一步是打开慢查询日志和延迟监控# 设置慢查询阈值为 5 毫秒 redis-cli CONFIG SET slowlog-log-slower-than 5000 redis-cli SLOWLOG GET 20 # 开启延迟监控并查看 redis-cli CONFIG SET latency-monitor-threshold 100 redis-cli LATENCY LATEST逻辑说明slowlog-log-slower-than设成 5000 微秒即 5 毫秒超过这个时间的所有命令都会被记录latency-monitor-threshold是 Redis 内置的延迟事件采样器可以捕获 fork、过期 key 回收、AOF 刷盘这类事件。这两个工具的区别是SLOWLOG 记录的是命令维度的耗时LATENCY 记录的是事件维度的耗时前者帮你找「哪个命令慢」后者帮你找「哪个操作导致命令慢」。参数说明latency-monitor-threshold的单位也是微秒默认关闭设成 0需要手动开启。LATENCY LATEST输出最近一次超过阈值的事件类型和耗时如果显示fork事件耗时高基本可以断定子进程生成 RDB 时 COW 造成内存复制拖慢了主进程。课程里强调的一个反直觉结论是很多情况下延迟峰值根本不是 Redis 内部问题而是网络。redis-cli --latency可以用来测试客户端到服务端的网络往返耗时连续跑 10 秒以上观察最小值、平均值和最大值。如果最大值和平均值差距巨大说明网络存在抖动这时候调 Redis 参数没有意义问题在链路中间的交换机或云厂商的网络设施上。5.2 CPU 架构影响NUMA、CPU 绑定与网卡中断17 讲讲的是 CPU 结构对 Redis 性能的影响这是全课程里最容易被忽视的部分。单线程模型意味着 Redis 只用一个 CPU 核心所以 CPU 的调度、内存访问距离都会直接影响性能。物理机部署场景下最常见的坑是 NUMA 架构。CPU 和内存之间不是均匀访问的每个 CPU 有自己的本地内存跨节点访问内存的延迟比本地访问高一个量级。如果 Redis 进程被调度到了某个 CPU 核心而它的内存分配在另一个 NUMA 节点的内存上延迟就会莫名升高。课程给的判断方法很简单用numactl --hardware查看节点拓扑再用taskset -pc pid查看 Redis 进程当前绑定的核心如果进程可以在多个核心间漂移就意味着它可能在跨节点访问内存。处理方式常见做法是 CPU 绑定# 查看 Redis 进程 ID pgrep redis-server # 把 Redis 绑定到指定 CPU 核心 taskset -pc 2 redis_pid逻辑说明taskset -pc 2把进程绑定到 CPU 核心 2 上避免操作系统频繁把进程调度到不同核心也就避免了因为换核导致的缓存失效和跨 NUMA 内存访问。绑核的前提是确认该核心上没有其他高负载进程争抢否则反而可能加剧问题。另一个容易被忽略的点是网卡中断绑核。当网卡收到大量网络包时中断处理会占用 CPU。如果网卡中断和 Redis 进程挤在同一个核心上Redis 的命令处理会被中断处理抢占延迟抖动就会周期性出现。处理方式是查看/proc/interrupts确认中断分布然后通过smp_affinity把网卡中断绑到和 Redis 不同的核心上。这类问题在虚拟机环境里不容易遇到但在物理机大流量场景下非常典型。5.3 避坑清单5 条血泪经验坑一缓存穿透打垮数据库现象压测时数据库连接数瞬间飙满Redis 命中了大量不存在的 key。原因请求查的 key 在缓存和数据库里都不存在每次都直接打到数据库。解决对空结果也做缓存TTL 设短一些比如 30 秒或者在缓存前面加布隆过滤器直接拦截掉不存在的 key。课程推荐先做空值缓存因为它实现简单布隆过滤器更适合 key 空间巨大的场景。坑二bigkey 删除卡住整个实例现象删除一个 List 或 Hash 时Redis 延迟从毫秒级跳到数秒期间所有请求超时。原因单线程模型下删除一个大集合需要遍历所有元素耗时和元素数量成正比。解决删除大集合用UNLINK替代DELUNLINK是异步删除主线程只把 key 从键空间中移除实际内存释放交给后台线程。同时用OBJECT ENCODING和DEBUG OBJECT key检查大 key 的规模提前拆分。坑三主从全量复制打满带宽现象从库重启后主库出网带宽瞬间跑满读延迟剧烈波动。原因从库落后主库的偏移量超过repl-backlog-size触发了全量复制RDB 文件传输占满带宽。解决把repl-backlog-size从默认的 1MB 调大到内存的 5%~10%同时避免在业务高峰期重启从库。如果全量复制无法避免考虑在低峰期操作。坑四AOF everysec 丢秒级数据现象Redis 宕机后恢复发现丢了最近一两秒的写入。原因appendfsync everysec是每秒刷盘宕机瞬间未刷盘的数据确实会丢这是配置本身的语义。解决先确认业务对数据丢失的容忍度。不能接受任何丢失就用always并接受吞吐量下降能容忍就用everysec。不要在出事后才意识到配置的语义。坑五分布式锁在 GC 暂停时失效现象两个进程同时拿到了锁业务逻辑出现了并发冲突。原因Java 进程发生长时间 GC 暂停锁的过期时间到了锁被自动释放另一个进程趁机拿到锁。解决一般用 Redisson 的看门狗自动续期或者自己实现续期逻辑——把锁的过期时间设成业务执行时间的三倍以上并在执行过程中定期刷新过期时间。课程里提醒分布式锁的可靠性最终还是取决于业务对「极端情况容忍度」的评估没有绝对安全的分布式锁。6. 把排查思路固化成脚本一个可复用的性能体检清单课程内容看完后最容易出现的情况是「都懂了遇到问题还是慌」。我的习惯是把所有排障步骤固化成一条检查命令集合每次接手新环境先跑一遍把结果保存下来当作基线。#!/bin/bash # redis_health_check.sh - 简易 Redis 体检脚本 redis-cli INFO memory | grep used_memory_human redis-cli INFO stats | grep -E total_commands|expired_keys|evicted_keys redis-cli CONFIG GET slowlog-log-slower-than redis-cli SLOWLOG GET 5 redis-cli --latency -c 100 redis-cli --bigkeys | tail -20这段脚本覆盖了五个核心维度内存占用是否接近maxmemory、淘汰和过期是否异常、慢查询阈值配置是否合理、最近慢查询命令是哪些、全库是否存在大 key。跑完花不到 10 秒但能在一开始就暴露大部分隐患。--latency -c 100连续测试 100 次网络往返如果最大值超过 10 毫秒就开始怀疑网络链路问题。还有一个更轻量的日常习惯定期用INFO persistence看最近一次 RDB 生成耗时和 AOF 重写耗时这两个数值一旦出现持续上升说明写入量在逼近 fork 的临界点要提前规划容量。每次大促前我也都会强制走一遍这个体检流程再配合INFO replication确认主从偏移量一致基本能避免绝大多数线上事故。这套课程笔记我在不同阶段翻过三遍每遍的理解深度都不一样——第一遍学命令第二遍学原理第三遍才是真正在故障复盘时找到了对应章节。希望帮到你。本文还有配套的精品资源点击获取