1. 为什么需要持久化?
Redis的读写和响应速度为什么如此之快?不同于传统的关系型数据库,Redis的数据库是全部加载在实时内存中的,读写操作能够直接在内存中进行,省去了大量IO操作,因此性能非常优越。但一切依托于内存的服务都有个最大的软肋,那便是在设备出现故障(如断点)时,内存中所有的实时数据都将会丢失。为了解决这个问题,Redis中提供了两种持久化方案:RDB和AOF,其机制实际上都是设法将内存中的数据以文件的形式备份到磁盘上,从而解决断电等机器故障导致数据丢失的问题。
2. RDB (Redis DataBase)
实现机制:Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程结束后,再用这个临时文件替换上次持久化好的文件(dump.rdb)。整个过程中,主进程不会进行任何IO操作的,这样就能够保证Redis主进程持续的高性能。在恢复数据时,重启后会Redis会自动加载工作目录下的dump.rdb文件恢复数据到内存
相关参数:
## 设置触发RDB dump的条件,在<seconds>时间至少发生了<changes>次数据的操作,则<seconds>时间到了就将数据写到磁盘中,为dump.rdb Redis默认设置了三个条件,满足之一即可触发。移除所有条件或者设置 save 后加空字符串为禁用RDB功能
save <seconds> <changes>
save 900 1 ## for 低频写入
save 300 10 ## for 中频写入
save 60 10000 ## for 高频写入
## 设置当RDB进程出现故障时,Redis是否停止写操作,默认为yes
stop-writes-on-bgsave-error yes
## 设置RDB时是否使用LZF压缩算法对dump.rdb文件进行压缩,默认yes
rdbcompression yes
## 设置是否对dump.rdb文件进行校验,默认CRC64校验算法,会消耗RDB进程的CPU资源的10%,默认开
rdbchecksum yes
## 设置输出文件名, 默认dump.rdb
dbfilename dump.rdb
## 设置dump.rdb文件输出路径,默认为当前启动工作目录
dir ./
优势:
- 无论是持久化过程还是数据恢复过程,RDB的速度都非常快
- 用户能够手动设置参数以控制持久化的频率,应用场景更加灵活
- 适合大规模且对数据的完整性和一致性要求不高的数据恢复,
劣势:
- RDB的持久化需要fork一条子线程,且子线程将会copy主线程所有数据,相当于设备的内存使用临时翻了一倍,在数据量特别大的情况下使用RDB可能有内存溢出风险
- 最后一次持久化的数据可能丢失,因此对数据完整性比较敏感的业务不建议使用RDB进行持久化
PLUS:为什么最后一次持久化的数据可能丢失?
RDB通过设置save <seconds> <changes>条件来触发dump,其机制为满足任一save条件后再该条件的<seconds>后进行刷写,但实际上可能最后一次dump时虽然达到修改次数<changes>要求,但在时间还未到达时redis进程中止,则这一阶段的数据就丢失了。比如save 300 10这一条件,Redis在300s内的修改操作次数超过了10次,因此触发持久化条件,系统将会在300s到期后进行刷写,但是可能在到期前几秒,设备异常关机,那么这300s内产生的数据修改信息将会全部丢失
3. AOF(Append Only File)
实现机制:与RDB直接写原数据不同,AOF记录的是Redis自启动期间所有的写操作,类似于日志,且写入的方式只允许在末尾追加,不允许修改之前写入的内容,默认保存为appendonly.aof文件。恢复数据时,Redis将AOF加载到内存并执行其中的每一条数据进行数据的恢复。
相关参数:
## 启动开关 -- 默认关闭
appendonly no
## 文件名
appendfilename "appendonly.aof"
## 刷写频率
appendfsync always ## 同步持久化,每当有数据变更就立即记录到磁盘,性能较差但数据完整性好
appendfsync everysec ## 出厂默认配置,异步操作,每秒记录,如果一秒内宕机,则会有数据丢失
append no ## 不设置刷写频率,当Redis自己触发刷写条件时才进行刷写
优势:
- 默认的刷写频率为每秒一次,因此能够最大程度地保证数据的完整性
- AOF只是记录运行时的写操作,并不会复制所有主线程数据,因此发生内存溢出的风险较小
劣势:
- 只支持追加形式写入,因此形成的appendonly.aof文件会越来越大,会影响Redia恢复数据的性能
- 恢复数据时需要Redis执行appendonly.aof记录的每条指令,恢复速度较慢
- 实际上操作指令有很大的整合空间,比如10000条自增1语句可以归并为一条自增10000语句,AOF在这方面仍然有较大可优化空间
Rewrite机制:为解决appendonly.aof文件会越来越大的隐患,AOF设置了Rewrite机制,默认当appendonly.aof文件大小达到了上次Rewrite后appendonly.aof文件的大小时并且文件的大小超过64M,AOF将会启动Rewrite,fork出一条新进程创建一个临时文件,然后遍历整个数据库,将每个key、value对以Redis命令的格式输出到临时文件。这一过程会将多个键值对集合起来用一条命令表达以减小最终文件的大小。在rewrite期间的写操作会保存在内存的rewrite buffer中,rewrite成功后这些操作也会append到临时文件中,rewrite完成后该临时文件便会代替appendonly.aof文件
## 触发Rewrite条件 -- and --
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
## 发生重写时是否支持appendfsync刷写? 默认为no,保证数据安全
no-appendfsync-on-rewrite no
4. 小结
使用场景:
- RDB适合数据流大、数据恢复快但对数据完整性依赖不高的业务,比如用户行为分析等
- AOF则适合对数据完整性有很高限制的业务,比如银行金融类业务
共存性:
官方虽然默认关闭AOF功能,但实质上RDB和AOF是可以共存的,当Redis同时开启了AOF和RDB持久化,Redis重启时会优先读取AOF文件进行数据恢复,因为AOF比RDB更能保证数据完整性。此外,由于Redis数据的恢复需要读取AOF文件或者RDB文件,因此,为了防止这两个文件出现损毁或者被恶意修改,Redis提供了两个修复脚本专门修复这两个文件
## 修复AOF文件
redis-check-aof --fix appendonly.aof
## 修复RDB文件
redis-check-dump --fix dump.rdb
安全性拓展:
实际生产时,无论是AOF还是RDB,都需要将生成的appendonly.aof和dump.rdb文件进行异地备份,这样才能避免单机彻底损坏造成的数据不可恢复问题
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。