CHECK-SUM RDB 文件所有内容的校验和,一个 uint_64t 类型值, REDIS 在写入 RDB 文件时将校验和保存在 RDB 文件的末尾,当读取时,根据它的值对内容进行校验
。如果这个域的值为 0 ,那么表示 Redis 关闭了校验和功能。
1.3 启动时加载 RDB文件的载入工作是在服务器启动时自动执行的,并没有专门的命令。但是由于AOF的优先级更高,因此当AOF开启时,Redis会优先载入AOF文件来恢复数据;只有当AOF关闭时,才会在Redis服务器启动时检测RDB文件,并自动载入。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止
2. AOF持久化AOF(Append Only File) 则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF
文件,以此达到记录数据库状态的目的
Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在配置文件中配置:
appendonly yes
2.2 执行流程 2.2.1 命令写入缓冲区 //缓冲区的定义 是一个SDS, 可以兼容C语言的字符串 struct redisServer { // AOF缓冲区, 在进入事件loop之前写入 sds aof_buf; };
命令传播: Redis将执行完的命令、命令的参数、命令的参数个数等信息发送到 AOF 程序中
缓存追加: AOF程序根据接收到的命令命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的 AOF 缓存中。
将命令以文本协议格式保存在缓存中
为什么使用文本协议格式?兼容性,避免二次开销,可读性
为什么写入缓存?这样不会受制于磁盘的IO性能,避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈
文件写入和保存:AOF 缓存中的内容被写入到 AOF 文件末尾,如果设定的 AOF 保存
条件被满足的话,fsync 函数或者 fdatasync 函数会被调用,将写入的内容真正地保存到磁盘中。
为了提高文件写入效率,在现代操作系统中,当用户调用write函数将数据写入文件时,操作系统通常会将数据暂存到一个内存缓冲区里,当缓冲区被填满或超过了指定时限后,才真正将缓冲区的数据写入到硬盘里。这样的操作虽然提高了效率,但也带来了安全问题:如果计算机停机,内存缓冲区中的数据会丢失;因此系统同时提供了fsync、fdatasync等同步函数,可以强制操作系统立刻将缓冲区中的数据写入到硬盘里,从而确保数据的安全性。
AOF保存模式:
AOF_FSYNC_ALWAYS: 命令写入aof-buf后立即调用系统的fsync操作同步到AOF文件。因为 SAVE 是由 Redis 主进程执行的,所以在 SAVE 执行期间,主进程会被阻塞,不能接受命令请求。这种情况下,每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。
AOF_FSYNC_NO: 命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
AOF_FSYNC_EVERYSEC: 每一秒钟保存一次,命令写入aof_buf后调用系统write操作, write完成后线程返回, fsync同步文件操作由专门线程每秒调用一次
2.2.2. 文件重写随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入AOF重写机制压缩文件体积,AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。
重写后的AOF文件为什么可以变小?
进程内已经超时的数据不再写入文件
旧的AOF文件含有无效命令 ,如有些数据被重复设值(set mykey v1, set mykey v2)、有些数据被删除了(sadd myset v1, del myset)等等, 新的AOF文件只保留最终的数据写入命令
多条写入命令可以合并为一个,如:lpush list a、lpush list b可以转化为:lpush list a b。为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash等类型操作,以64个元素为边界拆分为多条
AOF重写可以手动触发也可以自动触发:
手动触发: 直接调用bgrewriteaof命令
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。
auto-aof-rewrite-min-size:表示运行AOF重写时文件最小体积,默认为64MB
auto-aof-rewrite-percentage:代表当前AOF文件空间(aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的比值
流程说明:
1)执行AOF重写请求。
如果当前进程正在执行AOF重写,请求不执行。
如果当前进程正在执行bgsave操作,重写命令延迟到bgsave完成之后再执行。
2)父进程执行fork创建子进程,开销等同于bgsave过程。
3.1)主进程fork操作完成后,继续响应其它命令。
所有修改命令依然写入AOF文件缓冲区并根据appendfsync策略同步到磁盘,保证原有AOF机制正确性。
3.2)由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据
由于父进程依然响应命令,Redis使用“AOF”重写缓冲区保存这部分新数据,防止新的AOF文件生成期间丢失这部分数据。
4)子进程依据内存快照,按照命令合并规则写入到新的AOF文件。
每次批量写入硬盘数据量由配置aof-rewrite-incremental-fsync控制,默认为32MB,防止单次刷盘数据过多造成硬盘阻塞。
5.1)新AOF文件写入完成后,子进程发送信号给父进程,父进程调用一个信号处理函数,并执行以前操作更新统计信息。
5.2)父进程把AOF重写缓冲区的数据写入到新的AOF文件。这时新 AOF 文件所保存的数据库状态将和服务器当前的数据库状态一致。
5.3)对新的AOF文件进行改名,原子地(atomic)覆盖现有的AOF文件,完成新旧文件的替换。