Redis持久化


文章目录

  • 一、 前言
  • 二、持久化方式
  • 三、RDB方式
    • 优点
    • 缺点
  • 四、AOF方式
    • 优点
    • 缺点
  • 五、No Persist方式
  • 六、恢复策略
  • 七、运维策略
  • 八、总结


一、 前言

毕竟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方式

RDB是某个时刻的数据快照, 触发条件有时间触发, key更新触发和命令触发如save/bgsave。

优点

  1. RDB是一种紧凑的二进制格式文件, 可以对Redis进行多次快照以获得不同版本的数据;
  2. 创建快照时, 基于fork函数创建子进程, 后续的数据读写在子进程中完成, 最小化对主进程的影响;
  3. 恢复数据时, 速度比AOF快, 并且便于网络传输(比如集群环境下的全量复制);

缺点

  1. 由于不是每次写入都触发快照, 因此存在数据丢失风险, 丢失数据为上次快照到崩溃之前;
  2. 如果数据非常大, 基于fork函数创建子进程占用过多CPU, 从而影响主进程对外服务效率。个人见过的生产实例最大16G(待定)。

四、AOF方式

AppendOnlyFile, 记录所有的写入日志。

优点

  1. 相比RDB, 数据丢失的更少, 丢失范围与fsync刷盘机制有关, 在默认策略fsync per second下至多丢失1s数据。在开启AOF情况下, AOF会被作为默认的恢复数据源;
  2. AOF文件仅做简单追加, 不做seek, 一般不存在文件中间被破坏的情况, 即便最后的命令被破坏也可以去修正;
  3. AOF文件内容非常容易理解和解析, 假设你不小心flushall删除了所有的数据, 在AOF文件没有rewrite的情况下, 你依然可以通过删除AOF文件中的flushall指令而后恢复出原始的数据;

缺点

  1. 在表示相同数据的情况下,AOF文件比RDB文件大;
  2. AOF模式下由于需要频繁做fsync, 性能要比RDB差。相比AOF, RDB更能保证大批量写入下的最大延迟;

五、No Persist方式

将原本需要写入磁盘的文件, 直接通过网络连接发送给目标节点。目前能想到的点是磁盘由于运维不及时,剩余空间不足以完成持久化,而此时又需要备份的情况。

六、恢复策略

如前面所言, 持久化与恢复和复制密切相关, 这里聊聊恢复。当开启AOF时候, 默认会以AOF为恢复数据源, 毕竟AOF中的文件完整度相比RDB更高, 否则默认以RDB文件作为恢复数据源。

此外, 由于恢复时通常意味着进程重启, 如果是系统宕机重启, AOF文件的最后一条日志可能是不完整的, 可以通过redis-check-aof命令来尝试恢复。也可以配置允许加载不完整的AOF文件来解决, 毕竟在注定有损失的情况下, 当然是越少越好。

七、运维策略

  1. 由于默认记录所有的命令, 日志文件随时间增长会变得越来越大, Redis通过log rewrite机制来解决。相关配置包括auto-aof-rewrite-min-size和auto-aof-rewrite-percentage。前者为日志文件首次到达该size时启动重写, 后者为基于首次的size增长该percentage时重写, 从而保证AOF文件在一个相对可控的范围内;
  2. 由于rewrite期间会占用CPU做必要的计算, 选项no-appendfsync-on-rewrite可以配置在rewrite期间是否不做AOF的fsync操作, 如果在乎延迟可以设置为yes, 如果在乎数据完整性可以设置为no;
  3. rewrite的具体实现有两种, 一种是基于CPU计算出抵消的命令, 最后仅保留剩余结果。另外一种则是基于RDB的快照+增量的AOF日志。总之, 配置项aof-use-rdb-preamble控制。

八、总结

本文结合Redis使用场景引入Redis持久化的必要性(恢复和复制问题), 持久化的实现方式RDB和AOF, 以及两种方式的优缺点, 特别是AOF相关的运维策略, 希望对你有所帮助, 感谢你的阅读。

你可能感兴趣的:(Redis,redis,数据库,缓存)