毕竟Redis通常仅作为缓存使用,缓存内容丢了也就丢了,不过咱们得在生产环境下模拟演练下才行。假设一开始只有1个不支持持久化的Redis实例, 最大内存只有4G, 显然这里有这么几个问题。从可用性角度, 单节点挂了系统完犊子; 从存储容量角度, 4G容量不足, 得加内存, 停机维护系统完犊子; 从读写性能角度, 带宽/CPU能力不够, 得升级网卡/CPU, 停机维护系统完犊子; 转来转去貌似都可以算是可用性问题, 也就意味着Redis运行依赖的硬件环境(CPU,内存,网卡)或者软件环境(如操作系统), 依赖Redis的系统都只能是完犊子的命运。
于是你肯定想整个小集群, 至少是2个节点, A节点挂了B节点对外服务(这是主备), 注意此时依然没有开启持久化。然后由觉得备节点闲着也是浪费, 咋地可以利用下, 于是就写主读备(这是主从)。但是引入新的问题, 就是主从(备)的数据如何保持一致, 这个业界有成熟的经验。每次写入主时, 同时也写入从一份, 每次操作等待两个都写成功后再返回, 不过又产生的问题是如果写入失败了咋整。这玩意发展的足够严谨就变成了分布式事务。此时, 你又想了我就是想保持俩节点数据一致, 没必要每一次操作返回都一致吧, 是不是可以稍微晚点? 这问题又稍微简化了些, 主从正常对外服务与主从之间的数据同步解耦。
到这里, 俩节点密切配合丝滑流畅, 但看看之前的3个问题, 一个实例挂了另外一个顶上, 性能和容量问题(升级软硬件还可以对外服务)。但这里有2个BUG, 一是任何一个实例退出期间, 集群又重回单点(此时你慌不慌)。二是升级完成后, 你还是得做数据同步, 但是新加入的节点, 它内存里是空的, 复制的指令只有增量, 没有存量。
对于问题1, 我弄个1主2从。对于问题2, 只能先把所有的操作命令全部复制下来, 然后在新节点上回放。这就是持久化1.0, 全量日志(对应AOF方式)。随着时间的推移, 日志文件肉眼可见地增大, 而且头也不回地在增长。于是你想数据加加删删, 只保留目前存量数据的日志不就好了, 这就是快照, 算是持久化2.0(对应RDB方式)。本来吧, 升级到2.0之后1.0可以扔掉了, 但2.0有个问题就是数据不全, 要全还得是1.0, 要是把这俩结合就完美了这就是快照+增量日志, 算是持久化3.0(基于RDB重写的AOF方式)。再看问题1, 其实咱们无法一开始就预见所有, 集群得支持节点动态加入吧, 没有持久化就没有复制, 没有复制就没有恢复, 于是加入了也是个废柴, 又绕道问题2了。
总之, 持久化是必要的, 可以解决两个问题实例数据恢复和实例间的数据复制。接下来, 咱们细说Redis持久化。
持久化方式 | 说明 |
---|---|
RDB | 保存某个时刻的全量数据 |
AOF | 保存server收到的所有写操作命令, 命令在server重启后用于回放, 重建原始数据 |
RDB+AOF | 在同一个实例上可同时启用两种持久化方式 |
RDB是某个时刻的数据快照, 触发条件有时间触发, key更新触发和命令触发如save/bgsave。
AppendOnlyFile, 记录所有的写入日志。
将原本需要写入磁盘的文件, 直接通过网络连接发送给目标节点。目前能想到的点是磁盘由于运维不及时,剩余空间不足以完成持久化,而此时又需要备份的情况。
如前面所言, 持久化与恢复和复制密切相关, 这里聊聊恢复。当开启AOF时候, 默认会以AOF为恢复数据源, 毕竟AOF中的文件完整度相比RDB更高, 否则默认以RDB文件作为恢复数据源。
此外, 由于恢复时通常意味着进程重启, 如果是系统宕机重启, AOF文件的最后一条日志可能是不完整的, 可以通过redis-check-aof命令来尝试恢复。也可以配置允许加载不完整的AOF文件来解决, 毕竟在注定有损失的情况下, 当然是越少越好。
本文结合Redis使用场景引入Redis持久化的必要性(恢复和复制问题), 持久化的实现方式RDB和AOF, 以及两种方式的优缺点, 特别是AOF相关的运维策略, 希望对你有所帮助, 感谢你的阅读。