去年得了一场大病,我现在不再那么执着于当架构师,多少年后我要做到什么title,挣多少钱,没有这样的想法,反而有了新的目标和计划, 不算太迷茫。
一直想记录一个关于redis相关的内容。
我很喜欢Redis的持久化机制,原因在于现在Redis发展到哪怕突然被人拔电线,重启后仍然能够快速恢复数据,掉电数据丢失率很低很低,目前持久化的机制还是很强的。
Redis的持久化有三种模式:RDB, AOF, RDB&AOF
RDB模式
RDB模式下,redis会每隔一段时间,将内存中的该时刻的数据快照存到硬盘里,会在一个xxx.rdb文件里,宕机重新启动后从xxx.rdb恢复,RDB恢复很爽快,直接把rdb文件里的存的快照整个给内存贴过去完事。 在redis.conf配置文件里可以设置该模式的参数:
1 | |
这个模式,不好,它在隔时间地一段一段地在持久化数据,比如save 60 1000:假如距离上一次持久化已经过60秒了,键的改动次数没到1000个,就不触发持久化。在这个60秒段内任意一个时间截点拔电源,都会造成数据丢失,因为距离上一次持久化后内存中有增量的数据,它们没有被持久化保护。
AOF模式
AOF模式下,来一行指令持久化一行指令到xxx.aof的一个文件里,宕机重新启动后从xxx.aof恢复,这样可以认为数据不再丢失了。xxx.aof文件里是这样一样一行记录的:
1 | |
虽然这样一行一行的一个不落地记录能大大地降低数据丢失率,同时带来两个问题。
第一,持久化是一个磁盘同步的操作,而redis操作是内存操作,现在aof要每次redis操作都要伴随着持久化,岂不是会有无数次磁盘IO累活?
AOF模式提供了三种解决方案:
appendfsync always:每次有新命令追加到 AOF 文件时就执行一次 持久化 ,100%累赘,也非常安全。
appendfsync everysec:每秒持久化一次,足够快,并且在故障时只会丢失 1 秒钟的数据。
appendfsync no:从不持久化 ,将数据交给操作系统来处理。更快,也更不安全的选择。
权衡后我估计选择第二种,根据访问量和磁盘的优秀度配置一个合适的参数,比如设置 每1s把增量的数据持久化进来,那可以保证最近1s以前的数据绝对安全。
第二, AOF这个记录方式是不停地将所有历史数据向xxx.aof文件里堆加,随着时间文件会非常庞大,而aof的重启恢复的原理是把aof文件从0位置运行到宕机时的位置,这个时间好比把秦始皇到现代的时间走一遍。怎么加快恢复速度呢?
答案是AOF的重写。
1 | |
显然恢复中这些指令是浪费时间的,重写就是把这三个指令从aof中抹掉,这样一定程度上加快了恢复速度。
AOF 其实还是差点儿意思,AOF只是在保证数据安全上比RDB好,而RDB在恢复数据上比AOF快。
RDB & AOF混合持久化模式
结合RDB和AOF,结合优点,相消缺点。持久化会继续记录aof文件,底座是RDB快照,往上追加RDB持久化后增量的指令,如下:

- 持久化
- 每隔一段时间AOF文件会被RDB刷满
- 按照AOF模式,新增的指令往上追加
- 恢复
- 将RDB部分的快照装在进redis内存里
- 执行AOF部分的指令
Conclusion
我认为Redis的机制选型不需要太客观,大部分的redis服务部署完后,不要犹豫,选第三种混合型持久化模式。
- 恢复起来非常快
- 宕机那一刹那间小概率丢一两个数据,重启后排查,补上去就行。灾难级丢失是不会的,一大块儿丢失也是不会的。