Redis学习笔记持久化(三)
redis通过两种策略RDB、AOF来实现持久化。
一、RDB持久化
简单来讲RDB持久化是通过将某个时间节点的数据库状态保存到一个经过压缩的二进制文件中,通常默认都是dump.rdb文件,类似关系型数据库中的快照。
载入RDB:当服务器使用RDB作为持久化时,启动时默认加载RDB文件,在此期间服务器处于阻塞状态,直到加载完成为止。若同时开启了AOF持久化,那服务器会优先加载AOF文件(AOF文件更新频率高,时间间隔短,对数据的完整性与一致性要求更高)。
创建与写入RDB:可通过手动执行命令SAVE、BGSAVE来生成RDB文件,当执行SAVE命令时服务器进程将处于阻塞状态、一直到RDB文件生成为止,期间客户端发送的所有命令请求都会拒绝,一般不建议使用。而BGSAVE命令会派生出一个子进程,由子进程负责RDB文件的生成,主进程可继续接收客户端请求,在此期间再次发送SAVE或BGSAVE命令都会拒绝,而BGREWRITEAOF命令将会阻塞至BGSAVE命令执行完后执行。
同时也可以通过配置文件中save选项自动间隔性保存,通过满足配置选项条件程序会自动执行BGSAVE命令。
save 900 1
save 300 10
save 60 10000
只要程序满足以上任意一个条件,都会执行BGSAVE命令。
1)、服务器900秒内对数据库至少执行了1次修改。
2)、服务器300秒内对数据库至少执行了10次修改。
3)、服务器60秒内对数据库至少执行了10000次修改。
实际上服务器状态中维护了一个保存以上三种条件的数组结构,一个用于记录上次BGSAVE命令执行之后数据库执行修改命令次数的计数器以及上次BGSAVE命令执行的时间戳。通过这三个属性服务器会周期检查所设置的条件是否满足,一旦满足条件服务器会立即执行BGSAVE命令。
二、AOF持久化
AOF持久化通过保存redis服务器执行的写命令来记录数据库状态。与RDB二进制文件不同的是AOF文件是一种命令请求协议的纯文本格式。
命令追加:服务器每执行一个写命令都会将写命令追加到服务器状态的aof_buf缓冲区末尾。
写入与同步:服务器每结束一个事件循环之前,都会根据配置选项是否满足条件来决定将aof_buf缓冲区中的内容写入到AOF文件中
appendfsync always
appendfsync everysec
appendfsync no
always:将aof_buf缓冲区中所有内容写入并同步到AOF文件中。
everysec:redis默认选项,将aof_buf缓冲区中所有内容写入到AOF文件中,如果前次同步时间与现在间隔超过一秒,那么将开启一个单独的线程再次对AOF文件进行同步。
no:将aof_buf缓冲区中所有内容写入到AOF文件中,何时同步由操作系统决定。
always级别:每个事件循环都需要对AOF文件进行写入与同步,因为redis中执行一次事件循环都是毫秒级的,所以always数据安全级别是最高的,出现故障停机也只会丢失一个事件循环中所产生的命令,但是效率最慢。
everysec级别:每个事件循环只需要对AOF文件进行写入操作,每隔一秒在子线程中进行一次同步操作,出现故障停机将会丢失一秒钟的命令数据。
no:每个事件循环只需要对AOF文件进行写入操作,由操作系统决定何时同步,理论上效率最高(但实际上写入数据的累积,同步操作时间将会拉长。效率并不一定最高),安全级别最低。出现故障停机时则会丢失距离上次同步期间所产生的所以命令数据。
1、AOF重写:由于AOF持久化是通过保存写命令来保持数据库状态的,通常AOF文件体积将会越来越庞大,在数据库进行AOF数据还原时所需要的时间将会越来越长。为了解决这一问题,redist提供了AOF重写功能,通过子进程读取当前数据库状态(而不是通过记录写命令)最终生成新的AOF文件替换现有AOF文件(BGREWRITEAOF)。
子进程在AOF重写期间,主进程继续执行客户端命令请求,同时为了保证期间数据可能出现不一致的情况,redis服务器设置了一个AOF重写缓冲区,在子进程AOF重写期间,主进程每执行完写命令都将会把写命令同时发给aof_buf缓存区和AOF重写缓存区。当子进程完成AOF重写之后,主进程将会调用信号处理函数将AOF重写缓冲区中的所有命令写入到新的AOF文件中,并以新的文件对现有AOF文件进行原子性覆盖。
注:主进程执行信号处理函数期间将会进行阻塞。
总结:持久化是redis中一大重点,必须掌握的知识。