Redis持久化机制

Redis把数据存储在内存中,当进程退出后数据就会丢失。Redis持久化机制可以将内存中的数据存储到磁盘上,当重新启动时可以从磁盘文件中读取数据加载到内存中。

Redis支持两种持久化机制:全量镜像RDB和增量式持久化AOF。

RDB

RDB是Redis的快照,存储了Redis中所有未过期的键值对。

redis.conf中配置RDB:

# 配置rdb文件的路径
# 若使用相对路径,工作目录由 dir 配置指定
dbfilename dump.rdb
dir /var/lib/redis

# save 项配置保存策略, 格式为`save <seconds> <changes>`
# save 条件可以配置多个, 若其中任一个条件被满足则会更新快照
save 900 1 # 900 秒内至少有 1 个 key 被改变 
save 300 10 # 300 秒内至少有 300 个 key 被改变 
save 60 10000 # 60 秒内至少有 10000 个 key 被改变
save "" # 注释所有 save 配置,或在最后添加一个空的save配置可以禁用自动保存

stop-writes-on-bgsave-error yes # 当保存快照文件失败后,redis不再执行任何写请求,以避免无法持久化造成错误
rdbcompression yes # 在保存快照时对文件进行压缩
rdbchecksum yes # 在快照文件结尾添加一个CRC64校验和;若该配置项为no则会写入0作为校验和,表示redis重新启动时无需进行校验

每次redis进程启动时会先检查rdb文件是否存在,若存在则将文件中的内容加载到内存中。

redis自动更新RDB文件时会fork一个子进程执行快照保存工作,在保存期间主进程可以正常的提供服务。

我们同样可以通过指令保存快照:

  • save: 以阻塞的方式保存快照,保存期间redis不能处理其它请求
  • bgsave: fork一个子进程完成保存工作,保存期间不会影响redis的正常服务。

lastsave命令可以得到最新的RDB文件创建时间戳,可以用来检查保存是否成功。

AOF

RDB作为数据库快照,每次创建都需要将整个数据库写入到文件。这是一个非常耗时的操作,因此也难以频繁进行,在出现异常时可能丢失大量数据。

Redis提供了增量式持久化工具AOF(Append Only ile), AOF通过记录Redis数据库中所有写指令进行持久化。AOF文件中以Redis通信协议的格式存储指令。

当Redis进程启动时会检查AOF文件是否存在,若存在则依次执行AOF中的指令恢复数据。

Redis每次执行写指令时都会向AOF文件中添加一条日志,但新的记录不会立即写入磁盘(fsync)而是缓存在写入缓冲区中。

我们可以配置将缓冲区中的数据写入磁盘的策略,避免数据丢失。

将缓冲区中数据写入磁盘是一个耗时操作,频繁写磁盘会对性能造成影响但是Redis崩溃丢失数据也较少,因此我们需要根据应用场景进行权衡。

日志重写

AOF中可能会记录多余的指令,若我们对同一个key执行了100次set指令, AOF文件中就会有100条记录但只仅保留最后一条set指令即可恢复数据。AOF重写会整理AOF文件清理不必要的指令日志(如删除被覆盖的set指令),减少AOF文件大小。

redis 采用后台重写的策略,即 fork 一个子进程把整理后的 AOF 写入到临时文件中。使用BGREWRITEAOF可以手动触发后台重写操作。

实际上AOF重写不会读取原来的AOF文件,子进程会带有一份当前数据的副本,并根据该副本直接生成新的AOF文件。

主进程在重写期间将新增的写操作写入原来的 AOF文件 和 AOF重写缓存 中,即使重写失败原来的AOF文件仍保存了完整的数据。当子进程完成AOF重写后会向主进程发送信号,主进程收到该信号后会将AOF重写缓存中的内容写入新的AOF文件,然后用新的AOF文件覆盖原有文件。

redis.conf中配置AOF:

# 是否开启AOF,默认关闭(no)  
appendonly yes  
  
#  AOF 文件名  
appendfilename appendonly.aof  
  
# AOF 文件写入策略
# appendfsync always # 每次收到写命令就立即强制写入磁盘, 一致性最好但性能最差
appendfsync everysec # 每秒钟写入磁盘一次, 平衡一致性和性能,推荐配置
# appendfsync no     # 依赖操作系统的写入策略,一般为30秒左右一次,性能最好但是一致性最没有保证
    
# 在 AOF 重写期间将 appendfsync 配置为 no, 
# 默认配置为 no 避免因为磁盘IO性能不足,导致重写时间过长。若重写期间 redis 崩溃则可能丢失数据。
# 配置为 yes 则可以保证一致性,但会延长重写耗时
no-appendfsync-on-rewrite no   
  
# AOF文件新增大小达到上次重写后文件大小的 100%,则自动进行AOF重写。
# 配置为 0 会禁用自动重写  
auto-aof-rewrite-percentage 100  
  
# 当前AOF文件超过64mb才会自动进行AOF重写
auto-aof-rewrite-min-size 64mb  

Redis会记录启动时或上次重写后AOF文件的大小,若新增数据的大小达到原大小的100%(auto-aof-rewrite-percentage配置)则触发重写。

只有当前AOF文件体积大于auto-aof-rewrite-min-size时才会执行重写操作,否则即使新增数据量超过指定百分比也不会执行重写。这样避免了原文件过小导致初期频繁重写的问题。

posted @ 2018-06-08 23:00  -Finley-  阅读(1058)  评论(1编辑  收藏  举报