Redis 长期化原理分析和使用建议
作者:来自 vivo 互联网存储团队- Qiu Xu本文主要先容了 Redis 提供的三大长期化机制,即 AOF 日记、RDB 快照以及混合长期化机制。
一、Redis 为什么需要举行长期化
Redis 为了保证性能,会将全部数据存放在内存中,这极大的进步了 Redis 的响应速度,但是这也引入了一个十分严峻的问题:一旦服务器宕机,内存中的数据将全部丢失。这对于一款数据库产品来说是不能接受的。要克制数据丢失,最好将内存数据长期化到磁盘等永久存储介质上。服务重启时,先加载磁盘文件内的数据到内存,完成数据恢复。目前,Redis 主要提供了三大长期化机制,即 AOF(Append Only File)日记、RDB 快照、AOF 与 RDB 相联合的混合长期化。
二、AOF
2.1 AOF 概述
AOF 全称为 Append Only File,即实时将每一条写命令记录到 AOF 文件中,当 Redis 服务重启时会顺序实行一遍 AOF 文件中的全部命令,以达到数据恢复的目标。我们常见的日记记录方式主要为两种,一种为写前日记(Write Ahead Log, WAL),以 Mysql 数据库为例,Mysql 在将数据写入磁盘前,会先把修改的数据记到 redo 和 bin log 日记文件中,以便故障时举行恢复。
而另一种则是 Redis AOF 日记所采用的写后日记,“写后”的意思是 Redis 会先实行所接收到的写命令,把数据写入内存,然后才将命令写入 AOF 日记文件。Redis 在将命令记录到 AOF 日记中的时候,并不会去检验命令语法的正确性。因此先实行命令,利用命令实行这一环节对这些命令举行语法校验,这样既克制了写日记时额外的检查开销,也不会将存在语法错误的命令记录到 AOF 日记中,保证了 Redis 在使用 AOF 日记恢复数据时的正确性。
https://static001.geekbang.org/infoq/3c/3cb630459d06c2afe03e85cdc75dcb4f.png
2.2 AOF 开启方式
由于 AOF 功能开启后对 Redis 性能会产生一定影响,因此 AOF 功能默认是关闭的。我们可以通过修改 redis.conf 配置文件中的配置参数来开启 AOF 功能,还可以通过“config set”命令在线动态的开启和关闭 AOF 功能。
https://static001.geekbang.org/infoq/4b/4bb78be0791ed205fffdf82fdd73c98e.png
2.3 AOF 配置项
我们可以通过 redis.conf 配置文件中与 AOF 相关的配置项来自定义相应的 AOF 功能,例如:
[*]可以通过 appendfilename、appenddirname 配置项来指定 AOF 文件名以及文件存放目次。
[*]可以通过 appendfsync 配置项来指定 AOF 刷盘计谋,此中不同的配置项值在数据安全性以及服务性能方面的体现都不相同。
[*]配置项 no-appendfsync-on-rewrite 表示是否在 AOF 重写或写 RDB 期间,举行 AOF 刷盘。在 AOF 重写和写 RDB 文件期间会产生大量的磁盘 IO 读写操作,如果配置为 no,则表示在此期间可以举行刷盘操作,此时如果需要同步的数据量非常大可能会阻塞 Redis 主线程,降低 Redis 服务性能。因此在生产环境中,如果存在大量并发的写操作则可将该值设置为 yes;如果为大量并发的读操作则可以设置为 no。
[*]可以通过 auto-aof-rewrite-percentage、auto-aof-rewrite-min-size 配置项来指定触发 AOF 重写的条件,以防止 AOF 文件过分膨胀,占用大量存储空间。
[*]在举行 AOF 长期化期间,可能由于 Redis 服务突然宕机等原因导致写入 AOF 文件的末了一条命令不完整。在 Redis 服务重启并加载 AOF 文件时,配置项 aof-load-truncated 的值决定了 Redis 服务能否重启成功。若值为 yes,则删除不完整的命令,Redis 服务正常启动;若值为 no,则 Redis 服务无法启动。
[*]可以通过 aof-use-rdb-preamble 配置项来指定是否开启混合长期化功能。
2.4 AOF 文件内容
通过上述方式开启 AOF 功能后,我们以一条 “set testkey testvalue” 命令来看一下命令是以怎样的格式存储在 AOF 文件中的。如图所示此中,“*3” 表示当前命令有三个部分,每部分都是由 “$+数字” 开头,后面紧跟着详细的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例如,“$3” 表示这部分数据有 3 个字节,也就是 “set” 命令。
https://static001.geekbang.org/infoq/de/decabb050ad00c7c553d01c3a2e88289.png
2.5 写回计谋
Redis 是先实行写操作命令,然后将该命令记录到 AOF 缓冲区中,末了再将缓冲区中的数据写入磁盘。这么做克制了额外的检查开销,不会阻塞当前写操作命令的实行。AOF 配置项 appendfsync 的参数值,为 AOF 日记写回磁盘的机遇提供了三个选择。
[*]Always,同步写回:每个写命令实行完,立马将日记写回磁盘;“同步写回”可以做到根本不丢数据,但是在每一个写命令实行后都会有一个对磁盘的写操作,这不可克制地会影响主线程性能。
[*]Everysec,每秒写回:每个写命令实行完,只是先把日记写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;“每秒写回”采用一秒写回一次的频率,克制了“同步写回”的性能开销,减少了对 Redis 性能的影响,但是如果发生宕机,将丢失一秒内的全部写操作。
[*]No,操作系统控制的写回:每个写命令实行完,只是先把日记写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。由于 Redis 已不再掌握落盘的机遇,因此一旦宕机没有写入 AOF 文件的数据就丢失了。
写回计谋对比:
https://static001.geekbang.org/infoq/98/9841b02eb5a901a70fb30ec5ae21746d.png
2.6 AOF 重写
在上面我们向 AOF 文件中记录了一条 set 命令,如果此时我们对该 key 的值举行了更新,那么 AOF 文件中记录的日记是否也会随之更新呢?通过 AOF 文件我们可以看到,原先写入AOF 文件的 set 命令并没有发生改变,而是在 AOF 文件末端追加了一条 set testkey value 命令。
https://static001.geekbang.org/infoq/17/170323fd010edc199439e833807b302a.png
由于 AOF 日记文件中记录的是自 Redis 启动后每一条写操作,因此随着写操作的不停增长,AOF 文件将越来越膨胀,为了防止 AOF 文件不停地膨胀,Redis 为我们提供了一种 AOF 文件的重写机制。AOF 文件在重写时,Redis 会根据数据库的现状创建一个新的 AOF 文件,即读取数据库中的全部键值对,然后用一条命令将每一个键值对记录到新的 AOF 文件中。比如说,当读取了键值对 “testkey”: “value” 之后,重写机制会记录 set testkey value 这条命令。
这样,当需要恢复时,可以重新实行该命令,实现 “testkey”: “value” 的写入,而并不关心中间对这个 key 的其他写操作。以下图为例,当我们对一个列表先后做了 6 次修改操作后,列表的末了状态是 [“D”, “E”, “F”],此时,只用 LPUSH mylist “D”, “E”, "F" 这一条命令就能实现该数据的恢复,这就节省了五条命令的空间。这样对于被频繁修改过的键值对来说,重写能节省大量的空间。
https://static001.geekbang.org/infoq/31/318cdabdebba5eb502f6303b4867ce7c.png
注:图片泉源于 https://time.geekbang
固然 AOF 重写后,日记文件会缩小,但是,要把整个数据库最新数据的操作日记都写回磁盘,仍旧是一个非常耗时的过程。为了克制阻塞主线程,导致数据库性能下降,重写过程是由 bgrewriteaof 子进程来完成。每次实行重写时,主线程 fork 出 bgrewriteaof 子进程。由子进程逐一把内存中的数据写成操作,记入重写日记。由于主线程未阻塞,仍旧可以处理新来的操作。
此时,如果有写操作,Redis 会把这个操作写到 AOF 日记缓冲区。这样一来,纵然宕机了,这个 AOF 日记的操作仍旧是齐全的,可以用于恢复。并且这个操作也会被写到重写日记的缓冲区。这样,重写日记也不会丢失最新的操作。等到内存数据的全部操作记录重写完成后,重写日记记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。此时,就可以用新的 AOF 文件替代旧文件了。
https://static001.geekbang.org/infoq/f1/f1b42ec818ba4d822cd9d65a8762e1d3.png
注:图片泉源于 https://time.geekbang
触发 AOF 后台重写的条件
[*]AOF 重写可以由用户通过调用 `BGREWRITEAOF` 手动触发。
[*]每次当 `serverCron`(服务器周期性操作函数)函数实行时,它会检查以下条件是否全部满意,如果全部满意的话,就触发主动的 AOF 重写操作:
(1)没有 BGSAVE 命令(RDB 长期化)/ AOF 长期化在实行;
(2)没有 BGREWRITEAOF 在举行;
(3)当前 AOF 文件巨细要大于
`server.aof_rewrite_min_size`(默以为1MB),大概在 `redis.conf` 配置了 `auto-aof-rewrite-min-size` 巨细;
(4)当前 AOF 文件巨细和末了一次重写后的巨细之间的比率大于大概即是指定的增长百分比(在配置文件设置了 `auto-aof-rewrite-percentage` 参数,不设置默以为100%)
2.7 AOF 长期化详细流程
[*]Redis 在接收到一条客户端发送过来的写命令后,会先实行该写命令,待命令实行成功后将该命令按照 Redis 通信协议格式写入 AOF 缓冲区。
[*]根据设置的 AOF 写回计谋,当满意写回条件时,将 AOF 缓冲区中的数据写入磁盘 AOF 文件中。
[*]当 AOF 文件巨细达到重写条件后,主进程 fork 出 bgrewriteaof 子进程,由子进程将内存中的数据重写为写命令写入暂时文件。
[*]若重写期间,主线程实行了新的写操作,主线程在将该写操作记录到 AOF 缓冲区的同时会将该写操作写入重写缓存区。
[*]待子进程完成内存中数据的记录后,会将重写缓存区记录的数据一并写入暂时文件。
[*]末了利用暂时文件替换原来的 AOF 文件。
https://static001.geekbang.org/infoq/ab/abf12d6fbe54d677f52d1d9a07223d18.png
2.8 AOF 日记优缺点
优点:
(1)AOF 可以更好的掩护数据不丢失,一般 AOF 会每隔1秒,通过一个后台线程实行 fsync 操作,最多丢失 1 秒钟的数据。
(2)Redis 提供了 AOF 文件的重写机制,因此 AOF 日记文件不会膨胀的很大,并且在重写期间也不会影响客户端的读写。
(3)AOF 文件中保存的是实行的指令,以是这个特性非常得当做劫难性的误操作紧急恢复。
缺点:
(1)由于 AOF 文件中记录的是写操作的命令,因此对于同一份数据来说,AOF 的日记文件通常要比 RDB 的数据快照文件要大。
(2)AOF 开启之后,Redis 服务支持的写 QPS 会比 RDB 支持的写 QPS 低。
三、RDB
3.1 RDB 概述
RDB 长期化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。所谓内存快照,就是指内存中的数据在某一个时候的状态记录。这样一来,纵然宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为 RDB 文件,此中,RDB 就是 Redis DataBase 的缩写。因为 RDB 记录的是某一时候的数据,并不是操作,以是,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成数据恢复。
3.2 RDB 触发方式
3.2.1 save 触发方式
save 命令实行时将阻塞 Redis 服务器,在此期间 Redis 不能实行其他客户端的命令,直到 RDB 过程完成为止。实行完成后,用新的 RDB 文件替代掉旧的 RDB 文件。由于 save 命令会阻塞 Redis 服务器,极大的影响了 Redis 的性能,因此不保举 save 命令触发方式。
https://static001.geekbang.org/infoq/2b/2bd9e6afaf951bcb1a225c737db238e4.png
3.2.2 bgsave 触发方式
实行该命令时,Redis 会在后台异步将数据记录到 RDB 文件中,同时 Redis 还可以响应客户端哀求。bgsave 命令实行时 Redis 主进程将实行 fork 操作创建子进程,RDB 长期化过程由子进程负责,完成后用新的 RDB 文件替换掉旧的 RDB 文件。阻塞只发生在 fork 阶段,一般时间很短。根本上 Redis 内部全部的 RDB 操作都是采用 bgsave 命令。
https://static001.geekbang.org/infoq/41/41a69433d8232c3b384e8cd586dbc0ea.png
3.2.3 主动触发
主动触发是由我们的配置文件来完成的。在 redis.conf 配置文件中,内里有如下配置:
save:这里是用来配置触发 Redis 的 RDB 长期化条件,也就是什么时候将内存中的数据保存到硬盘。比如 “save m n”。表示 m 秒内数据集存在 n 次修改时,主动触发 bgsave。因此主动触发的团体流程和 bgsave 命令触发是同等的。
RDB 触发方式对比
https://static001.geekbang.org/infoq/8f/8fa93e3b18cae680f3fa56ffaca5074b.png
3.3 RDB 配置项
在 redis.conf 配置文件中除了用于开启 RDB 功能的 save 配置项外,还有其他用于自定义 RDB 功能的配置项,例如:
[*]开启 RDB 功能后,可以将配置项 stop-writes-on-bgsave-error 的值设置为 yes,在 bgsave 命令实行失败后制止后续的写命令实行。通过这种方式可以让用户意识到数据并没有被成功的长期化到磁盘,从而克制数据丢失问题。
[*]可以通过配置项 rdbcompression 来启用 LZF 对 RDB 文件举行压缩,固然压缩后 RDB 文件占用的存储空间变小,但是压缩过程会消耗系统资源,降低 Redis 服务性能。
[*]从 RDB 5 开始,RDB 文件将 CRC64 校验和写入文件末端,以保证 RDB 文件的正确性,但这在保存和加载 RDB 文件时,对性能会产生影响。因此可以通过将配置项 rdbchecksum 的值设置为 no,禁用校验和。
[*]可以通过配置项 dbfilename 和 dir 来指定 RDB 文件名和天生目次。
3.4 写时复制技能
当由 bgsave 方式触发 RDB 长期化时,Redis 在写 RDB 期间是可以正常处理客户端发来的写命令的。因此为了节省在 RDB 长期化过程中内存的使用,Redis 会借助操作系统提供的写时复制技能(Copy-On-Write, COW)。简单来说,bgsave 子进程是由主线程 fork 天生的,可以共享主线程的全部内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。
此时,如果主线程对这些数据也都是读操作(例如图中的键值对 A),那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据(例如图中的键值对 C),那么,这块数据就会被复制一份,天生该数据的副本(键值对 C’)。然后,主线程在这个数据副本上举行修改。同时,bgsave 子进程可以继续把原来的数据(键值对 C)写入 RDB 文件。这既保证了快照的完整性,也答应主线程同时对数据举行修改,克制了对正常业务的影响。
https://static001.geekbang.org/infoq/25/2542bb587df5f958cefd06201e0a1019.png
注:图片泉源于 https://time.geekbang
3.5 RDB 文件格式
RDB 文件由以下五个部分组成;
[*]SOF 为一个长度为 5 的字符串常量 REDIS;用于标识 RDB 文件的开始,在加载 RDB 文件时可以快速识别该文件是否为 RDB 文件。
[*]rdb_version 占 4 个字节,表示 RDB 文件的版本号。
[*]database 是 RDB 文件中的重要部分,包罗了多个非空的数据库。每个 database 又由3个部分组成:SODB 占一个字节表明数据库的开始,db_number 表示数据库的编号,key-value-pairs 表示当前数据库中的键值对。
[*]EOF 占一个字节,用于标识数据的竣事,校验和的开始。
[*]check_sum 校验和,用于校验 RDB 文件数据是否出现损坏。
https://static001.geekbang.org/infoq/28/285e3200d1dc3a0f168d8ea81047ad5d.png
3.6 RDB 快照优缺点
优点:
(1)RDB 会天生多个数据文件,每个数据文件都代表了某一个时候中 Redis 的数据,这种多个数据文件的方式,非常得当做冷备。
(2)由于 Redis 是通过子进程实行磁盘 IO 操作来记录 RDB 文件的,因此 RDB 机制对 Redis 的性能影响非常小,阻塞只发生在 fork 阶段,可以保持 Redis 的高性能。
(3)相对于 AOF 长期化机制来说,直接基于 RDB 数据文件来重启和恢复 Redis 进程,更加的快速。
缺点:
(1)由于 RDB 文件记录的是某个时间段内的数据集,因此当服务器发生宕机时,该时间段后的数据将丢失。
(2)主进程每次在 fork 子进程来记录数据时,如果数据文件特别大,可能会导致主进程阻塞数毫秒,大概以致数秒。
四、混合长期化方式
由于 RDB 文件记录的是某个时间段内的数据集,因此两次 RDB 期间的数据依然存在丢失的风险,但是制作 RDB 文件的频率太高又会对 Redis 性能带来影响。因此为了克制两次 RDB 期间数据的丢失,并且降低对性能所带来的影响, Redis 4.0 提出了一个混合使用 AOF 日记和内存快照的方法。可以通过 redis.conf 配置文件中的配置项 aof-use-rdb-preamble 来开启混合长期化功能。
利用 AOF 日记记录两次快照间的操作,因此, AOF 文件也不会太大,也可以克制重写开销。如下图所示,T1 和 T2 时候的修改,用 AOF 日记记录,等到第二次做全量快照时,就可以清空 AOF 日记,因为此时的修改都已经记录到快照中了,恢复时就不再用日记了。
https://static001.geekbang.org/infoq/9b/9bac819b4a051f765cc87c16df4ff613.png
注:图片泉源于 https://time.geekbang
五、长期化方案选择
Redis 官方保举使用混合长期化方案,但我们也需要根据详细的业务需求和场景并联合三种长期化方案的优缺点选择合适的长期化方案。
[*]如果对数据安全性有较高的要求,就可以选择 AOF 或 混合长期化方案,此中 AOF 长期化方案可通过选择不同的写回计谋来达到不同水平的数据安全性保证。
[*]如果希望数据快速恢复,减少故障恢复时间,可以选择 RDB 或混合长期化方案。
[*]如果对长期化文件巨细有要求,可以选择 RDB 长期化方案,并可以启用 LZF 对 RDB 文件举行压缩。
[*]如果对 Redis 服务性能有较高的要求,可以选择 RDB 或混合长期化方案。
[*]若 Redis 仅用于缓存,可不开启长期化功能以寻求最大的服务性能。
六、参考资料
[*]https://www.tkcnn.com/redis/manual/persistence.html
[*]https://zhuanlan.zhihu.com/p/684331393
[*]https://blog.csdn.net/weixin_43412762/article/details/134795648
[*]https://developer.aliyun.com/article/1419933?spm=5176.26934562.main.1.1732527dM6Snpw
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]