3. Redis持久化与高可用选型

会话状态平台与普通缓存最大的区别在于:会话数据一旦丢失,用户会被强制登出,购物车、登录态、权限上下文全部失效。因此持久化策略与高可用拓扑不是“可选项”,而是决定平台可用性的基础设计。本节先拆解三种持久化方式对会话状态的实际影响,再对比主从、哨兵、集群三种高可用模式在状态平台中的适用边界。

一、三种持久化方式对会话状态的影响

RDB 是在指定时间点把内存中的数据集快照写入磁盘。它的核心特征是“周期性、全量、二进制紧凑”。对会话平台而言,RDB 的恢复速度最快,适合做冷备和灾难恢复;但两次快照之间的写入会丢失。例如配置 save 900 1、save 300 10、save 60 10000,意味着最多可能丢失 60 秒内、且不足 10000 次写入的会话变更。对于登录态这类“丢失即登出”的数据,60 秒的窗口往往不可接受。

AOF 以追加方式记录每条写命令,通过 appendfsync 控制落盘时机。everysec 是会话平台的常用折中:每秒 fsync 一次,最坏丢失约 1 秒数据,性能损耗可控;always 每条命令都 fsync,几乎不丢数据,但吞吐会明显下降;no 交给操作系统决定,丢失窗口不可控,不建议用于会话状态。AOF 的代价是文件体积大、恢复时需要重放命令,重启恢复时间随写入量线性增长。

混合持久化(Redis 4.0 起,aof-use-rdb-preamble yes)把 AOF 重写后的内容以 RDB 格式作为前半段,后续增量命令以 AOF 格式追加。它同时获得 RDB 的快速加载和 AOF 的低丢失窗口,是当前会话平台最推荐的组合。需要注意:混合持久化仍属于 AOF 机制,恢复时先加载 RDB 前导,再重放尾部 AOF 命令。

三种持久化方式对会话状态的影响对比 RDB 快照 写入方式:周期性全量快照 丢失窗口:两次快照之间 恢复速度:最快 文件体积:最小 会话影响:可能批量登出 适用:冷备 / 灾备恢复 示例:save 60 10000 最坏丢失 60s 内变更 登录态场景风险高 AOF 追加日志 写入方式:逐条记录写命令 丢失窗口:由 fsync 决定 恢复速度:随写入量线性增长 文件体积:较大 everysec:最坏丢约 1s always:几乎不丢,吞吐降 示例:appendfsync everysec 恢复需重放全部命令 重启恢复时间偏长 混合持久化 写入方式:RDB 前导 + AOF 增量 丢失窗口:约 1s(everysec) 恢复速度:接近 RDB 文件体积:介于两者之间 兼顾低丢失与快恢复 会话平台推荐方案 aof-use-rdb-preamble yes 重写后前导为 RDB 格式 登录态场景首选

二、主从、哨兵、集群的适用场景

主从复制解决的是“读扩展与数据冗余”。一个主节点接收写入,多个从节点异步复制。会话平台中,读多写少的场景(如校验登录态、读取权限)可以把读流量分摊到从节点。但主从本身不具备自动故障转移:主节点宕机后需要人工介入,且异步复制存在数据丢失窗口。它适合作为哨兵或集群的底层复制机制,而不是独立的高可用方案。

哨兵模式在主从基础上增加了监控、通知和自动故障转移。多个哨兵节点对主节点进行心跳探测,当多数哨兵判定主节点客观下线后,选举出新的主节点并通知客户端。对会话平台而言,哨兵的价值在于“主节点故障后能在秒级到十秒级恢复写入”,配合混合持久化可以把会话丢失控制在很小范围。但哨兵不解决单节点容量上限,所有写入仍落在单个主节点上,适合会话总量在单机内存可承载范围内的场景。

集群模式通过分片把数据分散到多个主节点,每个主节点再带从节点。它解决的是容量与吞吐的横向扩展问题。会话平台使用集群时,必须面对一个关键约束:跨 slot 的多键操作受限,涉及同一用户的多个会话键需要用 hash tag 保证落在同一分片,例如 session:{user:1001}:token 与 session:{user:1001}:profile。集群的故障转移粒度是分片级,单个分片故障只影响该分片上的会话,但客户端需要支持 MOVED/ASK 重定向。它适合会话量超过单机内存、或写入吞吐需要多主分担的大型平台。

模式 故障转移 容量扩展 会话平台适用场景
主从 无,需人工 读扩展 读多写少、可接受人工恢复
哨兵 自动,秒级~十秒级 单主容量上限 会话总量单机可承载、要求自动恢复
集群 自动,分片级 多主横向扩展 超单机内存、高写入吞吐的大型平台

三、选型决策与配置示例

选型可以按三个问题推进:会话总量是否超过单机内存?能否接受人工故障恢复?丢失窗口能容忍多大?若总量在单机内、要求自动恢复,选哨兵 + 混合持久化;若总量超单机或写入吞吐需要多主,选集群 + 混合持久化;若只是读扩展且可接受人工恢复,主从即可。

以下是一份哨兵 + 混合持久化的关键配置示例,参数为教学示例值,实际需按内存与写入量调整:

# redis.conf(主节点)
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
save 900 1
save 300 10

# sentinel.conf
sentinel monitor session-master 10.0.0.11 6379 2
sentinel down-after-milliseconds session-master 5000
sentinel failover-timeout session-master 60000
sentinel parallel-syncs session-master 1

验证时不要只看进程是否存活。可以在主节点写入一个带 TTL 的会话键,手动触发故障转移,观察新主节点上该键是否存在、TTL 是否合理。例如写入 SET session:{user:1001}:token abc EX 1800,执行 DEBUG SLEEP 10 模拟阻塞或直接 kill 主进程,等待哨兵完成切换后在新主节点执行 TTL session:{user:1001}:token。若返回接近 1800 的剩余秒数,说明复制与持久化链路基本正常;若键不存在,需要检查复制偏移量与 min-replicas-to-write 等参数。

会话平台不建议单独使用 RDB 作为唯一持久化方式。RDB 的丢失窗口对登录态过于激进,应至少启用 AOF everysec,或直接使用混合持久化。集群模式下务必用 hash tag 保证同一用户的会话键落在同一分片,否则跨分片操作会失败。
判断持久化是否达标,可以关注三个指标:rdb_last_bgsave_status、aof_last_bgrewrite_status、master_link_status。前两者为 ok 表示后台保存/重写成功,后者为 up 表示主从复制链路正常。故障转移后应复查这三个指标。