前言
本文主要回答如下问题:
-
Redis如何做持久化的?
Redis的持久化支持2种方式:rdb 和aof 两种方式。这个和mysql的binlog支持几种格式有点类似。比如mysql binlog支持(row(数据快照,二进制格式),statement(文本,存修改操作的sql语句),mix)等等多种格式。rbd类似于mysql的row,aof类似于mysql的statement。 复制代码
目录
- RDB 持久化
- AOF 持久化
- 两种持久化方式比较
RDB 持久化
RDB持久化是将当前进程中的数据生成快照保存到硬盘(因此也称作快照持久化),保存的文件后缀是rdb;当Redis重新启动时,可以读取快照文件恢复数据。
复制代码
-
触发条件
RDB持久化的触发分为手动触发和自动触发两种。 复制代码
-
1)手动触发 通过手动执行save命令和bgsave命令都可以生成RDB文件。
save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求。而bgsave命令会创建一个子进程,由子进程来负责创建RDB文件,父进程(即Redis主进程)则继续处理请求。bgsave命令执行过程中,只有fork子进程时会阻塞服务器,而对于save命令,整个过程都会阻塞服务器,因此save已基本被废弃,线上环境要杜绝save的使用,后文中也将只介绍bgsave命令。此外,在自动触发RDB持久化时,Redis也会选择bgsave而不是save来进行持久化。 复制代码
备注: fork 子进程时会阻塞,而fork的过程与redis进程占用的内存大小有关,占用内存过大时,fork阻塞时间会变长。
-
2)自动触发
自动触发是通过redis的配置文件中save m n 进行条件配置的,指的是在m秒内发生n次修改时,会触发进行bgsave。 复制代码
其中save 900 1的含义是:当时间到900秒时,如果Redis数据发生了至少1次变化,则执行bgsave;save 300 10和save 60 10000同理。当三个save条件满足任意一个时,都会引起bgsave的调用。
复制代码
提示: 因为自动触发需要满足一定的配置条件后才能触发,因而在redis出现故障时,可能部分数据还没有被持久化到rdb文件中,因而会出现数据丢失
。
- 触发bgsave的其他方式
-
在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行bgsave命令,并将生成的rdb文件发送给从节点;
-
执行shutdown命令时,自动执行rdb持久化。
-
RDB文件
RDB文件是经过压缩的二进制文件。Redis默认采用LZF算法对RDB文件进行压缩。虽然压缩耗时,但是可以大大减小RDB文件的体积,因此压缩默认开启
复制代码
RDB常用配置总结
save m n:bgsave自动触发的条件;如果没有save m n配置,相当于自动的RDB持久化关闭,不过此时仍可以通过其他方式触发。
stop-writes-on-bgsave-error yes:当bgsave出现错误时,Redis是否停止执行写命令;设置为yes,则当硬盘出现问题时,可以及时发现,避免数据的大量丢失;设置为no,则Redis无视bgsave的错误继续执行写命令,当对Redis服务器的系统(尤其是硬盘)使用了监控时,该选项考虑设置为no。
rdbcompression yes:是否开启RDB文件压缩。
rdbchecksum yes:是否开启RDB文件的校验,在写入文件和读取文件时都起作用;关闭checksum在写入文件和启动文件时大约能带来10%的性能提升,但是数据损坏时无法发现。
dbfilename dump.rdb:RDB文件名。
dir ./:RDB文件和AOF文件所在目录。
复制代码
AOF持久化
RDB持久化是将进程数据写入文件,而AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令
记录到单独的日志文件中,当Redis重启时再次执行AOF文件中的命令来恢复数据。相比RDB,AOF的优先级要高。
-
开启AOF
Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在配置文件中配置:
appendonly yes 复制代码
AOF 命令执行过程:
-
命令写入(append)
Redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。 复制代码
-
文件写入(write)和文件同步(sync)
Redis提供了多种AOF缓存区的同步文件策略,策略涉及到操作系统的write函数和fsync函数,说明如下: 为了提高文件写入效率,在现代操作系统中,当用户调用write函数将数据写入文件时,操作系统通常会将数据暂存到一个内存缓冲区里,当缓冲区被填满或超过了指定时限后,才真正将缓冲区的数据写入到硬盘里。这样的操作虽然提高了效率,但也带来了安全问题:如果计算机停机,内存缓冲区中的数据会丢失;因此系统同时提供了fsync、fdatasync等同步函数,可以强制操作系统立刻将缓冲区中的数据写入到硬盘里,从而确保数据的安全性。 复制代码
AOF缓存区的同步文件策略由参数appendfsync控制,各个值的含义如下:
always:命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下,每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。
no:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置。
复制代码
-
文件重写(rewrite)
随着时间流逝,Redis服务器执行的写命令越来越多,AOF文件也会越来越大;过大的AOF文件不仅会影响服务器的正常运行,也会导致数据恢复需要的时间过长。 复制代码
文件重写的触发,分为手动触发和自动触发:
手动触发:
直接调用bgrewriteaof命令,该命令的执行与bgsave有些类似:都是fork子进程进行具体的工作,且都只有在fork时阻塞。
复制代码
自动触发:
根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数,以及aof_current_size和aof_base_size状态确定触发时机。
auto-aof-rewrite-min-size:执行AOF重写时,文件的最小体积,默认值为64MB。
auto-aof-rewrite-percentage:执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值。
只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个参数同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。
复制代码
-
AOF 常用配置项:
appendonly no:是否开启AOF appendfilename "appendonly.aof":AOF文件名 dir ./:RDB文件和AOF文件所在目录 appendfsync everysec:fsync持久化策略 no-appendfsync-on-rewrite no:AOF重写期间是否禁止fsync;如果开启该选项,可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘),但是可能会丢失AOF重写期间的数据;需要在负载和安全性之间进行平衡 auto-aof-rewrite-percentage 100:文件重写触发条件之一 auto-aof-rewrite-min-size 64mb:文件重写触发提交之一 aof-load-truncated yes:如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件 复制代码
两种持久化方式的比较
RDB和AOF各有优缺点:
复制代码
RDB持久化:
优点:RDB文件紧凑,体积小,网络传输快,适合全量复制;恢复速度比AOF快很多。当然,与AOF相比,RDB最重要的优点之一是对性能的影响相对较小
。
缺点:RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。此外,RDB文件需要满足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)
。
AOF持久化
与RDB持久化相对应,AOF的优点在于支持秒级持久化、兼容性好,缺点是文件大、恢复速度慢、对性能影响大。
小结
本文简单的总结了一下redis的持久化策略以及相关配置。 参考资料:
<<redis 开发与运维>>