Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库.Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用,今天就来了解一下Redis的持久化机制.
RDB快照
RDB持久化机制是Redis默认的持久化策略;Redis将内存数据库快照保存再名字为dump.rdb的二进制文件中;
你可以对Redis进行设置;让它再"N秒内数据集至少有M个改动"这一条件被满足时,自动保存一次数据集;redis.conf中RDB的默认保存策略如下:
关闭RDB只需要将所有的保存策略注释掉即可
Redis不仅可以有默认的自动保存策略,还可以手动执行命令生成dump.rdb二进制文件;进入redis客户端执行save或者bgsave可以生成dump.rdb文件,每次执行命令都会把redis内存快照存到一个新的rdb文件中,并且覆盖原有的rdb文件;自动保存数据集时,默认使用的是bgsave方式;
命令 | bgsave | save |
---|---|---|
IO类型 | 异步 | 同步 |
是否阻塞redis其他命令 | 否(再生成子进程执行调用fork函数是会有短暂的阻塞) | 是 |
复杂度 | O(n) | O(n) |
优点 | 不阻塞客户端其他的命令 | 不会消耗额外的内存 |
缺点 | 需要fork子进程,消耗内存 | 阻塞客户端其他的命令 |
bgsave的写时复制机制(Copy-On-Write,COW)
Redis借助操作系统提供的写时复制技术,在生成快照的同时,依然可以执行写命令,简单点说,bgsave子进程是由主进程调用redis的Fork函数生成的,子进程可以共享主进程的所有的内存数据,bgsave子进程运行后,开始读取主进程中的内存数据,并把它们写入.rdb文件,此时,如果主进程对这些数据也都是读操作,那么父子进程互不影响,但是如果父进程要修改其中的一条数据,那么,这块数据就会被copy一份,生成该数据的副本.然后,bgsave子进程会把这个副本数据写入.rdb文件.与此同时,主进程仍然可以直接修改原来的数据
测试rdb
dump.rdb文件
AOF
rdb持久化方式并不是非常耐久的,例如"save 300 10",再300S内有10条记录发生改变才会自动保存一次数据集至rdb文件内;如果Redis因为某些原因造成故障而停机,那么Redis将会丢失最近300S内写入且未保存至rdb文件内的数据;从1.1版本开始,Redis增加一中完全耐久的持久化方式:AOF(append-only file)持久化,将修改的每一条指令直接记录尽文件appendonly.aof中(先写入操作系统缓存中,每隔一段时间fsync到磁盘)
fsync策略
测试aof
appendonly.aof文件:
AOF重写
aof文件里可能有太多没用的指令,所以AOF会定期根据内存的最新数据生成aof文件,例如:
重写过后的aof文件为:
redis自动重写策略
除了自动重写策略外,bgrewriteaof命令也可以自动重写,AOF重写与bgsave相似,redis同样会调用fork函数fork出一个子进程去做,不会对redis正常命令处理产生影响
RDB VS AOF
持久化方式 | RDB | AOF |
---|---|---|
启动优先级 | 低 | 高 |
文件体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全 | 容易丢失一段时间内的数据 | 视fsync策略而定 |
Redis 混合持久化
rdb容易丢失数据,aof恢复速度又很慢,Redis4.0版本为了解决这个问题,推出了一个新的持久化机制:混合持久化.
如果开启了混合持久化,AOF再重写时,不再将内存数据转换成命令写入aof文件,而是再重写这一刻之前的内存做rdb快照处理,并且将rdb内容和aof修改内存数据命令储存到一起,全部写入aof文件,新的文件一开始不叫appendonly.aof,等到重写完新的aof文件才会改为appendonly.aof,覆盖原有的aof文件,再开启混合持久化机制时,redis重启的时候可以先加载rdb的内容,然后再加载aof的内容,效率会得到大幅度的提升
Redis数据备份策略
- 写crontab定时调度脚本,每小时都copy一份rdb/aof的备份到一个目录中去,仅保留最近48小时的备份
- 每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份
- 每次添加最新备份时,同时删除最旧的备份
- 每天晚上将当前机器的备份copy到其他机器上,防止机器损坏造成的数据丢失