Redis(七)持久化(Persistence)
前言
前文中介绍到Redis时内存的K-V数据结构存储服务器。Redis的高性能原因之一在于其读写数据都是在内存中进行。它的架构实现方式决定了Redis的数据存储具有不可靠性,易丢失,因为RAM内存在硬件问题或者断电情况下都会被擦除。
基于以上问题,为了防止数据在特殊情况下丢失,Redis支持内存数据持久化至磁盘的功能——Redis Persistence。
Redis持久化方式
Redis提供了两种持久化方式:
- RDB持久化方式:在特定的时间间隔存储Redis键空间的某一时刻的快照。
- AOF持久化方式:当有数据写入Redis时,将以日志的形式记录写入的命令。以追加的方式写入AOF文件尾部,写入的内容遵循Redis协议的命令格式。
两种持久化方式完全不同。第一种是以完整的数据角度进行持久化,第二种是以日志的形式记录完整的写入操作。Redis用户可以在这两种方式之间进行trade off,也可以综合使用这两种方式。
Redis持久化比较
RDB的优点:
- RDB是某一时刻的Redis键空间的快照文件,是经过高度压缩的单个文件,所以RDB文件对于备份非常合适。根据不同的时刻,有不同版本的文件。
- 因为其实高度压缩的单个文件,所以对于数据采集,容灾都是非常不错的选择,可以将其转移至数据中心。
- Redis是单进程的方式work,所以在进行持久化时正在work的父进程会fork子进程进行很持久化操作,父进程仍然可以正常的服务用户client的请求,对性能影响微乎其微。
- 因为RDB持久化方式存储的是键空间的数据,所以对于Redis重启,恢复数据相对于AOF要更迅速。
AOF优点:
- AOF方式对于Redis的持久化更耐用,因为AOF提供了多种持久化策略可供选择:无同步持久化, 每秒同步持久化, 每次操作时同步持久化。默认策略是每秒持久化,这种方式写性能很好且只会丢失一秒间隔的数据(可容忍)。
- AOF方式只仅仅是追加的log形式,所以持久化时无需查找键空间数据且不会出现因为断电问题出现AOF文件损坏的问题。因为是追加的方式,只会局部影响最后的文件内容,Redis提供了redis-check-aof工具用于修复AOF文件。
- 当出现AOF文件过大时,Redis会自动后台重写AOF文件。
- 因为AOF是追加命令+数据的格式log,所以AOF文件具有易读性。
RDB的缺点:
- RDB方式是一段时间间隔后持久化数据快照,所以存在数据丢失风险。即使你将间隔控制在每5分钟,仍然存在最近几分钟内数据丢失的可能。
- RDB持久化方式是工作的父进程fork持久化的子进程。如果键空间数据很大,fork可能需要耗费很长时间,在fork过程中,父进程停止对client请求服务。如果数据集很大且cpu性能不是很好,可能造成Redis秒级停止服务。
AOF缺点:
- 相同键空间的数据,AOF文件的体积比RDB文件更大。
- 根据不同的fsycn策略,AOF方式可能比RDB更慢。虽然每秒的fsycn性能非常好,但是在巨大的写入是RDB的性能比AOF更好。
Redis持久化工作流
上述比较了两种持久化方式的各自优缺点,两者的选择需要trade off。但是通常,综合使用两种持久化方式是不粗的选择。
单独使用RDB存在数据丢失风险,单独使用AOF对于重启和数据备份来说不是好的idea。基于以上两种原因,综合使用RDB和AOF,能满足数据备份和快速重启,也能将数据丢失的风险降到最低。
默认情况,Redis是将快照保存在一个二进制的dump.rdb文件中。可以配置Redis在最近间隔多少秒内发生多少变化时进行RDB持久化。或者可以使用SAVE或者BGSAVE命令。
例如:save 60 1000,如果每60秒发生1000次变化,则进行RDB持久化。
RDB的工作流程:
- Redis fork用于持久化的子进程。
- 子进程将键空间数据写入到临时的rdb文件中。
- 当子进程完成写入,将替换旧的RDB文件。
对于AOF方式,需要在配置文件中开启AOF,配置:appendonly yes。当有写入命令时,Redis会将其追加到AOF文件末尾。
可以配置AOF的fsycn策略:
- 每当一个新命令执行时,即追加。很慢但是很安全
- 每秒追加一次,足够快且只丢失一秒的数据
- 从不fsync,依赖操作系统,非常快但是缺少安全性
建议的策略是每秒追加一次。
使用AOF方式有时可能出现文件损坏的问题,比如正在写入AOF文件时出现断电情况。这时可以使用redis-check-aof工具修复AOF文件
redis-check-aof --fix "filename",然后使用修复后的AOF文件启动Redis即可恢复数据。
AOF重写方式的工作流程:
- Redis的工作父进程fork子进程。
- 子进程开始写一个新的临时AOF文件
- 父进程将新发生的操作全部写入内存缓冲区
- 当子进程重写完毕,父进程会受到信号,并将内存缓冲区的内容追加到子进程重写后的AOF文件中
- Redis再重命名旧的AOF文件名至新的文件,Redis并将新的操作追加到文件中。
Redis持久化配置
触发RDB持久化配置需要在redis.conf中配置:
dir /usr/local/var/redis/
dbfilename dump.rdb
save 60 5
触发AOF持久化配置需要在redis.cong中配置:
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec