目录
1.Redis为什么需要持久化?
2.Redis持久化的方法有哪些?
3.RDB(快照持久化)
1)RDB机制实质是什么?
2)RDB的使用(分为手动和自动)
分类一:手动触发
分类二:自动触发
3)RDB优点
4)RDB缺点
4.AOF
1)AOF机制实质是什么?
2)AOF持久化流程
3)优势
4)劣势
5)AOF持久化配置
6)重写/压缩AOF
5.Redis 4.0 对于持久化机制的优化
很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。
Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化,而且支持两种不同的持久化操作。Redis 的一种持久化方式叫快照(snapshotting,RDB),另一种方式是只追加文件(append-only file, AOF)。这两种方法各有千秋。
快照持久化是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。 save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。 save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
根据配置,快照将被写入dbfilename选项指定的文件里面,并存储在dir选项指定的路径上面。如果在新的快照文件创建完毕之前,Redis、系统或者硬件这三者中的任意一个崩溃了,那么Redis将丢失最近一次创建快照写入的所有数据。
举个例子:假设Redis的上一个快照是2:35开始创建的,并且已经创建成功。下午3:06时,Redis又开始创建新的快照,并且在下午3:08快照创建完毕之前,有35个键进行了更新。如果在下午3:06到3:08期间,系统发生了崩溃,导致Redis无法完成新快照的创建工作,那么Redis将丢失下午2:35之后写入的所有数据。另一方面,如果系统恰好在新的快照文件创建完毕之后崩溃,那么Redis将丢失35个键的更新数据。
RDB(Redis DataBase)持久化是把当前Redis中全部数据生成快照保存在硬盘上(在指定的时间间隔内将内存的数据快照写入磁盘)。RDB持久化可以手动触发,也可以自动触发。
save
和bgsave
命令都可以手动触发RDB持久化。
1.save命令
执行save
命令会手动触发RDB持久化,但是save
命令会阻塞Redis服务,直到RDB持久化完成。当Redis服务储存大量数据时,会造成较长时间的阻塞,不建议使用。
2.bgsave命令
执行bgsave
命令也会手动触发RDB持久化,和save
命令不同是:Redis服务一般不会阻塞。Redis进程会执行fork操作创建子进程(Redis会单独创建一个子进程(fork)来进行持久化),RDB持久化由子进程负责,不会阻塞Redis服务进程。Redis服务的阻塞只发生在fork阶段,一般情况时间很短。(Fork 的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程)
具体流程:
1.执行bgsave命令,Redis进程先判断当前是否存在正在执行的RDB或AOF子线程,如果存在就是直接结束。
2.Redis进程执行fork操作创建子线程,首先他会将数据写入到一个临时文件汇中,在fork操作的过程中Redis进程会被阻塞。
3.Redis进程fork完成后,bgsave命令就结束了,自此Redis进程不会被阻塞,可以响应其他命令。
4.子进程根据Redis进程的内存生成快照文件,并替换原有的RDB文件。
5.子进程通过信号量通知Redis进程已完成。
为什么不直接放到持久化文件中呢?
假如说我程序正在执行但是我突然程序非正常挂掉了,而此时复制的不完整数据也被储存在了持久化文件中,这就造成持久化文件的不完整。这样就保证了数据的完整性,一致性和安全性。这就是写时复制技术。(Linux中引入)
除了执行以上命令手动触发以外,Redis内部可以自动触发RDB持久化。自动触发的RDB持久化都是采用bgsave的方式,减少Redis进程的阻塞。那么,在什么场景下会自动触发呢?
1.在配置文件中设置了save的相关配置,如sava m n,它表示在m秒内数据被修改过n次时,自动触发bgsave操作。
当从节点做全量复制时,主节点会自动执行bgsave操作,并且把生成的RDB文件发送给从节点。
如果用户设置了save选项(一般会默认设置),比如 save 60 10000,那么从Redis最近一次创建快照之后开始算起,当“60秒之内有10000次写入”这个条件被满足时,Redis就会自动触发BGSAVE命令。
2.执行debug reload(调试重新加载)命令时,也会自动触发bgsave操作。
3.执行shutdown命令时,如果没有开启AOF持久化也会自动触发bgsave操作。
当Redis通过SHUTDOWN命令接收到关闭服务器的请求时,或者接收到标准TERM信号时,会执行一个SAVE命令,阻塞所有客户端,不再执行客户端发送的任何命令,并在SAVE命令执行完毕之后关闭服务器。
4.一个Redis服务器连接到另一个Redis服务器: 当一个Redis服务器连接到另一个Redis服务器,并向对方发送SYNC命令来开始一次复制操作的时候,如果主服务器目前没有执行BGSAVE操作,或者主服务器并非刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE命令
RDB文件是一个紧凑的二进制压缩文件,是Redis在某个时间点的全部数据快照。所以使用RDB恢复数据的速度远远比AOF的快,非常适合备份、全量复制、灾难恢复等场景。
整个过程中,主进程是不进行任何IO操作的,这就保证了极高的性能,如果需要进行大规模数据的回复,且对于数据的恢复,且对于数据的恢复的完整性不是很敏感,那RDB的方式比AOF方式更加的高效。
每次进行bgsave操作都要执行fork操作创建子经常,属于重量级操作,频繁执行成本过高,所以无法做到实时持久化,或者秒级持久化。
另外,由于Redis版本的不断迭代,存在不同格式的RDB版本,有可能出现低版本的RDB格式无法兼容高版本RDB文件的问题
周期性备份,若果某一时刻redis突然挂掉,会丢失最后一次数据。
开启AOF持久化后每执行一条会更改(读操作不保存)Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件(以日志的形式)。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof。
只允许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一遍以完成数据恢复工作
1.命令追加(append):所有写命令都会被追加到AOF缓存区(aof_buf)中。
2.文件同步(sync):根据不同策略将AOF缓存区同步到AOF文件中。
3.文件重写(rewrite):定期对AOF文件进行重写,以达到压缩的目的。
4.数据加载(load):当需要恢复数据时,重新执行AOF文件中的命令。
文件同步策略
AOF持久化流程中的文件同步有以下几个策略:
1.always:每次写入缓存区都要同步到AOF文件中,硬盘的操作比较慢,限制了Redis高并发,不建议配置。
2.no:每次写入缓存区后不进行同步,同步到AOF文件的操作由操作系统负责,每次同步AOF文件的周期不可控,而且增大了每次同步的硬盘的数据量。
3.eversec:每次写入缓存区后,由专门的线程每秒钟同步一次,做到了兼顾性能和数据安全。是建议的同步策略,也是默认的策略。
触发文件重写
AOF持久化流程中的文件重写可以手动触发,也可以自动触发。
1.手动触发:使用bgrewriteaof命令。
2.自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage配置确定自动触发的时机。auto-aof-rewrite-min-size表示运行AOF重写时文件大小的最小值,默认为64MB;auto-aof-rewrite-percentage表示当前AOF文件大小和上一次重写后AOF文件大小的比值的最小值,默认为100。只用前两者同时超过时才会自动触发文件重写。
1.备份机制更稳健,丢失数据概率更低。
2.可读的日志文本,通过操作AOF稳健,可以处理误操作
AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
3.Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写
1、AOF问价体积太大,比起RDB 占用更多的磁盘空间。
2、恢复备份速度要慢。
3、每次读写都同步的话 ,有一定的性能压力。
对AOF持久化的具体流程有了了解后,我们来看一下如何配置AOF。AOF持久化默认是不开启的,需要修改配置文件,如:
# appendonly改为yes,开启AOF
appendonly yes
# AOF文件的名字
appendfilename "appendonly.aof"
# AOF文件的写入方式
# everysec 每个一秒将缓存区内容写入文件 默认开启的写入方式
appendfsync everysec
# 运行AOF重写时AOF文件大小的增长率的最小值
auto-aof-rewrite-percentage 100
# 运行AOF重写时文件大小的最小值
auto-aof-rewrite-min-size 64mb
AOF虽然在某个角度可以将数据丢失降低到最小而且对性能影响也很小,但是极端的情况下,体积不断增大的AOF文件很可能会用完硬盘空间。另外,如果AOF体积过大,那么还原操作执行时间就可能会非常长。
为了解决AOF体积过大的问题,用户可以向Redis发送 BGREWRITEAOF命令 ,这个命令会通过移除AOF文件中的冗余命令来重写(rewrite)AOF文件来减小AOF文件的体积。BGREWRITEAOF命令和BGSAVE创建快照原理十分相似,所以AOF文件重写也需要用到子进程,这样会导致性能问题和内存占用问题,和快照持久化一样。更糟糕的是,如果不加以控制的话,AOF文件的体积可能会比快照文件大好几倍。
重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble
开启)。
如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分就是压缩格式不再是 AOF 格式,可读性较差。