本文主要回答以下问题:mysql
Redis如何作持久化的?redis
Redis的持久化支持2种方式:rdb 和aof 两种方式。这个和mysql的binlog支持几种格式有点相似。好比mysql binlog支持(row(数据快照,二进制格式),statement(文本,存修改操做的sql语句),mix)等等多种格式。rbd相似于mysql的row,aof相似于mysql的statement。
复制代码
RDB持久化是将当前进程中的数据生成快照保存到硬盘(所以也称做快照持久化),保存的文件后缀是rdb;当Redis从新启动时,能够读取快照文件恢复数据。
复制代码
触发条件算法
RDB持久化的触发分为手动触发和自动触发两种。
复制代码
1)手动触发 经过手动执行save命令和bgsave命令均可以生成RDB文件。sql
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命令,并将生成的rdb文件发送给从节点;网络
执行shutdown命令时,自动执行rdb持久化。app
RDB文件是通过压缩的二进制文件。Redis默认采用LZF算法对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文件所在目录。
复制代码
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 开发与运维>>