VOL.001 · 创刊号Token 天团 API

Token 天团

—— 一份关于代码与生活的个人刊物 ——

技术Java教程

Redis 持久化与高可用:照片丢中间,日记丢尾巴——Java 工兵连第 15 篇

「Java 工兵连」第 15 篇,Redis 双子篇下篇。第 14 篇讲完「内存里怎么放」,这篇讲两个更上层的问题:机器挂了,数据丢多少(持久化)?机器挂了,服务停不停(高可用)?两个问题正交,别混着答。网上资料最爱罗列配置项,这篇只给你选型判断力——每个方案的能力边界在哪一刀。

一、持久化:照片与日记

左:RDB 与 AOF 对比与混合持久化;右:高可用三级台阶

RDB(快照)= 全家福照片:BGSAVE fork 一个子进程,把某瞬间的全量内存定格成紧凑的二进制文件。恢复飞快(直接加载),文件小适合备份。丢的是两次拍照之间的一切——默认触发条件(save 900 1 那组)意味着最坏丢十几分钟。另外注意:fork 本身在大内存实例上有瞬时停顿(复制页表),几十 GB 的实例要心里有数。

AOF(追加日志)= 流水账日记:每条写命令追加到文件——思路和 MySQL 的 binlog 完全同源(第 12 篇:追加写逻辑日志)。丢多少取决于「多久誊一次进保险柜」(appendfsync):

档位 含义 最多丢
always 每条命令都 fsync 0(一条不丢)
everysec(默认) 每秒 fsync 一次 1 秒
no 交给操作系统 听天由命

日记会越记越厚,所以有 AOF 重写:fork 子进程按当前内存反推出一本最薄的账(比如一百次 INCR 合并成一个 SET)。而 混合持久化(4.0+,默认开)是两者的合体:重写时用 RDB 格式打底,之后的增量用命令追加——恢复速度≈RDB,丢失窗口≈AOF。口诀:照片打底,日记续命。重启加载规则:有 AOF 优先 AOF(更完整),没有才用 RDB。

持久化选型一句话:缓存可重建 → 不开或只 RDB 做备份;秒级不丢 → AOF everysec + 混合;一条都不能丢 → 别硬扛 Redis——写穿数据库、Redis 只做缓存(第 17 篇会接着讲怎么一致)。

二、高可用:抄本、保安队、连锁分店

① 主从复制 = 师徒抄本。 一主多从,师父(主库)写字,徒弟(从库)实时抄——准确说是异步抄:师父写完立刻回复客户端,不等徒弟确认。好处:读扩展(读走徒弟)+ 数据热备。死穴两个:主挂了不会自动切(要人爬起来执行 REPLICAOF NO ONE);异步意味着主挂的瞬间,徒弟手里可能缺最后一行——「丢尾巴」。

② 哨兵 Sentinel = 保安队。 至少 3 个哨兵(奇数)独立于 Redis 部署,干三件事:监控(持续 ping)、自动故障转移、通知客户端新主地址。判定流程很像法庭:单个保安 ping 不通 = 主观下线(怀疑);达到 quorum(多数)同意 = 客观下线(定罪);哨兵们先自己选出 leader(多数派投票,Raft 思想),由 leader 挑一个数据最新的徒弟扶正。哨兵解决了「自动切」,但没解决扩展:写能力和内存上限还是一台机器的。

③ Cluster 集群 = 连锁分店。 全库 16384 个货位(slot)按范围分给多个主店,每个 key 按 CRC16(key) % 16384 落进某家店;每家主店再带徒弟(从店)防单店倒下。客户端问路(smart client 缓存槽位表),走错店会被 MOVED 重定向。它同时解决了容量(内存水平扩展)和写吞吐(多主分摊),代价清单:跨槽的多 key 操作受限(MGET/事务/多 key Lua 要求同槽——用 hash tag user:{1000} 让相关 key 落同一家店)、运维复杂度陡增、不支持跨槽事务。

三级台阶一句话:能抄不能切,能切不能扩,能扩但费心。

三、选型阶梯(抄作业版)

纯缓存、可全量重建 ......... 单实例(甚至关持久化),RDB 兼做备份
读多写少、要热备 ........... 主从(接受人肉切换或半自动)
单机内存够、要求自动切 ...... 哨兵(3 节点起步;单主内存经验值 <10~25GB)
超单机内存 / 写 QPS 超单机 ... Cluster(收下多 key 限制和运维成本)
不想养这些 .................. 云托管(Tair/ElastiCache),把哨兵和集群外包

最后单独划重点的坑:异步复制的丢尾巴是架构属性,不是配置能修的。WAIT numslave timeout 可以让主库等从库确认再返回(拿性能换安全),但真要跨机房强一致,正确答案从来不是给 Redis 上刑,而是换存储模型:写穿 DB、Redis 做缓存,或用共识协议的存储承担真相源。

老兵点评

  1. 选型的第一问不是「用什么」,是「丢了多少能接受」。把丢失容忍量化(0 条 / 1 秒 / 1 分钟 / 全丢都行),持久化和高可用的方案组合直接唯一化。面试里能先反问出这一句的人,已经在架构段位了。
  2. 别用运维复杂度换用不上的能力。见过太多小系统上来就 Cluster,结果 90% 精力花在槽迁移和多 key 排查上,数据量其实一台 16GB 实例绰绰有余。哨兵 + 单主撑到很大规模都是体面的选择——能力边界内的最简方案就是好方案(线程池篇「池按业务分」同款思想:约束换来的简单性是资产)。
  3. 面试段位差:初级背 RDB/AOF 区别;中级讲刷盘三档、混合持久化和哨兵选主观/客观下线;高级讲异步复制的丢失语义、Cluster 的槽与 gossip、以及「强一致需求不该由 Redis 扛」的边界判断——最后一层是存储选型的品味。

带走三句话

  1. 持久化口诀:照片丢中间(RDB 快照),日记丢尾巴(AOF everysec ≤1s),混合打底又续命;一条不丢的需求请写穿 DB。
  2. 高可用阶梯:主从能抄不能切,哨兵能切不能扩,集群能扩但费心(跨槽多 key 受限,hash tag 同槽)。
  3. 异步复制丢尾巴是架构属性:要更强只能 WAIT 交性能税,或把真相源交给 DB / 共识存储——选型第一问永远是「丢多少能接受」。

本篇是「Java 工兵连」第 15 篇 · Redis 双子篇完结。→ 上一篇:第 14 篇 · Redis 数据结构与 bigkey | 继续阅读:第 16 篇 · 缓存三件套:穿透 / 击穿 / 雪崩 | 浏览整个专栏 →。

❦ 终 ❦

← 回到首页全部归档 →