电话

028-126520321

BOB半岛入口:面试官:您提到熟悉Redis,您了解持久化配置吗?

标签: 2024-06-21 

在之前的文章中,我们已经介绍了Redis五种数据类型的命令以及基本配置文件。今天我们将从理论和配置两个层面来揭开Redis持久化的神秘面纱。持久化"是指将内存中的数据转存到硬盘上进行永久储存的过程。数据持久化后,确保数据在系统重启或宕机后仍然可访问,从而保障数据安全。Redis有两种持久化方案,一种是快照方式,简称RDB;另一种是只追加模式,称为AOF。让我们来分别了解一下它们的用途和注意事项。RDB是Redis DataBase的简称,是Redis的默认持久化方案。它可以在指定时间间隔内把内存数据集快照写入磁盘,并在恢复时从快照文件(dump.rdb)中读回内存。我们首先来看一下配置文件中关于快照的部分:配置文件中的保存save指令 <秒数> <改动数> 在指定的秒数内,如果对数据库的写入操作达到设定的值,数据将同步到数据文件中。支持多个条件配合,Redis默认配置文件中提供了三个条件:

save 900 1 //900秒内有1次更改 save 300 10 //300秒内有10次更改 save 60 10000 //60秒内有10000次更改 

注意:若不想使用RDB方案,可以取消上述三个条件的注释,将 save "" 的注释打开。当bgsave出现错误时,Redis是否停止执行写命令?\n如果设置为yes,则当硬盘出现问题时,Redis将停止接受写入操作,以便及时发现并避免大量数据丢失;\n如果设置为no,则Redis将忽略bgsave错误并继续执行写命令。如果已经配置好了对Redis服务器的正确监控与持久化,也采取了其他措施来检测和维护数据完整性,可能会考虑禁用这项功能。这样即使在处理磁盘、权限等问题时,Redis仍能保持正常运作。请注意,如果后台保存进程重新开始工作,Redis将自动允许再次进行写入。启用本地数据库存储时是否压缩的选项(Redis使用LZF算法压缩数据),默认为是。为了减少CPU时间的消耗,可以选择关闭该选项,但这样会导致数据库文件变得非常大。自RDB版本5开始,在存储快照后,可以使用CRC64算法进行数据校验,CRC64校验结果会放置在文件的末尾。打开后,当进行RDB文件的保存和加载时,性能消耗会增加大约10%。如果想获得更大的性能提升,可以选择关闭该功能。禁用创建的RDB文件的校验和为零,这将告诉加载代码跳过检查。

dbfilename dump.rdb

用于指定本地的数据库文件名,系统重启后会自动将其加载到内存中。如果手动执行save命令,更改会立即生效。请注意,使用flushall和shutdown命令会清空并将数据提交到dump.rdb。使用dir ./

可以指定本地数据库存放目录。当Redis需要保存dump.rdb文件时,它会使用系统函数fork()创建一个与主进程完全一致的子进程。子进程会将数据集写入临时文件RDB中。当子进程完成对新的RDB文件的写入时,Redis会用新的RDB文件替换原来的RDB文件,并删除旧的RDB文件。通过这种工作方式,Redis 可以充分利用写入时复制(copy-on-write)机制。如何触发RDB快照有以下几种方式:在配置文件中默认的快照设置;使用save命令(阻塞操作,只负责保存快照,其他操作需等待)或者bgsave命令(异步操作),快照生成的同时还能响应客户端请求;执行flushall命令会清空数据库,但并没有太大意义;执行shutdown命令可以确保服务器正常关闭且不会丢失数据,但也并不太有意义。使用RDB文件进行数据恢复是非常普遍的。在实际开发中,通常会考虑到物理机硬盘损坏的可能性,因此我们会选择备份dump.rdb文件。把备份好的dump.rdb文件复制到redis安装目录的bin文件夹中,然后重新启动redis服务即可。RDB有多个优点。它是一个非常紧凑的文件,非常适合用于备份数据集;RDB是一个紧凑的单一文件,可以方便地传输到另一个远程数据中心或亚马逊的S3(可能会进行加密),非常适合用于灾难恢复;Redis的主进程不执行I/O操作,从而确保了极高的性能;适合大规模数据的恢复,对于数据的完整性和一致性要求不高的情况下,RDB比AOF方式更加高效。在Redis意外宕机时,可能会损失几分钟的数据;RDB需要定期fork子进程将数据集保存到硬盘上,当数据集较大时,fork过程会非常耗时,可能导致Redis在一些毫秒级内无法响应客户端请求。如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒;AOF也需要fork,但是可以调节重写日志文件的频率来提高数据集的耐久度。AOF日志为了解决RDB在宕机时丢失大量数据的问题,Redis在1.1版本开始引入了一种持久化方式:AOF。

AOF是Append Only File的简称,缺省情况下是关闭的。AOF会以日志的形式记录每次写入操作,只允许追加文件而不允许覆盖文件内容,服务器重启时将重新执行这些命令以恢复原始数据。让我们再次来检查一下配置文件中的APPEND ONLY MODE:\n配置文件中的 appendonly 默认为关闭状态,改为 yes 可以打开持久化。AOF和RDB可以同时开启而不会有任何问题发生。启动即创建的文件默认名称是“appendonly.aof”。在执行dump.rdb文件的加载

时,会优先考虑同步策略

面试官:您提到熟悉Redis,您了解持久化配置吗?

:系统函数fsync() 会指示操作系统立即将数据写入磁盘。Redis支持三种不同的模式

appendfsync always //每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好

appendfsync everysec //默认推荐,异步操作,每秒记录,如果宕机,有1秒内数据丢失

appendfsync no //不同步,只有在操作系统需要时在刷新数据

要想了解接下来的配置内容,先得说一下“日志重写”的原理:

重写

由于AOF采用的是将命令追加到文件末尾的方式,所以随着写入命令的不断增加,AOF文件的大小会逐渐变大。为避免出现此种情况,新增了重写机制:可以在不打断服务客户端的情况下,对AOF文件进行重建(rebuild)。为了防止这种情况发生,我们添加了一个重新构建机制:可以在不中断客户端服务的情况下,重建AOF文件。

重新构建触发:通过执行bgrewriteaof命令,可以生成一个新的AOF文件,其中包含重新构建当前数据集所需的最少命令。Redis 2.2需要手动执行这个命令,而Redis 2.4可以通过修改配置文件的方式自动触发(有关配置在下面涉及)。

重写原理:

Redis 执行系统函数fork() ,创建一个子进程(与主进程完全一致); 子进程开始将新 AOF 文件的内容写入到临时文件; 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样即使在重写的中途发生停机,现有的 AOF 文件也是安全的; 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。Redis 以原子方式用新文件替换旧文件,然后所有命令都将直接追加到新AOF文件的末尾。

no-appendfsync-on-rewrite no

当我们同时执行主进程的写操作和子进程的重写操作时,两者都会操作磁盘,而重写往往会涉及到大量的磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形。為了解決這個問題,no-appendfsync-on-rewrite選項應運而生。

当参数设为no时,这是最安全的选择,不会丢失数据,但会经历阻塞问题; 如果设为yes,则相当于将appendfsync设为no,表示并未执行磁盘操作,只是将数据写入缓冲区。因此在这种情况下不会发生阻塞(因为没有竞争硬盘),但如果此时redis发生故障,数据将会丢失。损失了多少数据呢?在Linux操作系统的默认配置下,最多可能会丢失30秒的数据。若应用系统无法容忍延迟,但可忍受少许数据遗失,则设为是;若应用系统无法容忍数据遗失,则设为否。

auto-aof-rewrite-percentage 100

重写百分比,默认为上次重写后aof文件大小的一倍。

auto-aof-rewrite-min-size 64mb

重写触发的最小值:64mb。根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数的设定来确定何时自动触发。Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。大型互联网公司通常从3G起步。启用截断是的场景发生在AOF文件的末尾有命令不完整,当Redis重启时,会加载AOF数据到内存,这时候可能会有一些问题。

是的:当加载被截断的AOF时,Redis服务器会开始记录日志并通知用户该事件; 不:服务器将立即中止并报错,拒绝启动。当我们发现 AOF 文件出现错误时,可以采用以下方法来修复它:

\n1. 为现有的 AOF 文件创建一个备份;\n2. 使用 Redis 附带的 redis-check-aof 命令对原始的 AOF 文件进行修复;\n3BOB半岛下载. 可以选择使用 diff -u 命令来比较修复后的 AOF 文件和原始 AOF 文件备份。查看两个文件之间的差异;重新启动。服务器正在等待修复后的 AOF 文件加载,并执行数据恢复。 Redis在重新编写AOF文件时,会启用使用RDB前导,以加速重新编写和恢复速度。启用此选项后,重写的AOF文件由两个不同的节组成:RDB file、AOF tail

加载Redis时,会识别AOF文件以Redis字符串开头,并加载带前缀的RDB文件,然后继续加载AOF尾部。

理论

优点

数据的完整性和一致性更高,AOF的持久化通过使用不同的策略,最多丢失1秒的数据; AOF文件是一个只进行追加的日志文件,不需要写入seek; Redis可以在 AOF文件体积变得过大时,自动地在后台对 AOF 进行重写,重写操作是绝对安全的; AOF文件记录的写入操作以Redis协议的格式保存,容易读懂,容易对文件进行分析;

缺点

面试官:您提到熟悉Redis,您了解持久化配置吗?

对于相同的数据集来说,AOF文件的体积通常要大于RDB文件的体积;

根据所使用的 fsync 策略,AOF 的执行速度可能比 RDB 较慢。通常情况下,每秒进行一次 fsync 的性能非常出色。关闭 fsync 后,AOF 的速度可以达到和 RDB 一样快的水平,即使在高负荷时也是如此。通常情况下,每秒执行fsync的性能非常出色。当关闭fsync时,AOF的速度将与RDB相当,即使在高负载情况下也是如此。然而,在处理大量写入时,RDB可以提供更可靠的最大延迟时间。如何选择哪种持久化方式,要考虑

和 的对比以及总结。

通常情况下,为了达到与 PostgreSQL 相媲美的数据安全性水平,需同时利用两种持久化功能。如果你非常在意数据的情况,但可以容忍在几分钟内丢失数据,那么可以考虑仅使用 RDB 持久化。AOF是当前主流的持久化方式,因为它具有更好的实时性,即在进程意外退出时丢失的数据更少。许多

用户只使用AOF持久化方式,但我们不建议这种做法。因为通过定期生成 RDB 快照(snapshot)容易进行数据库备份,而且在恢复数据集时 RDB 的恢复速度比 AOF 快。Redis版本号大于等于2.4时,在进行BGSAVE操作期间,不允许执行BGREWRITEAOF。换句话说,在执行 BGREWRITEAOF 的过程中,不能同时执行 BGSAVE。这样可以避免两个 Redis 后台进程同时对磁盘进行大规模的I/O 操作。 如果BGSAVE正在运行,并且用户主动调用BGREWRITEAOF命令,那么服务器会回复一个OK状态,告知用户BGREWRITEAOF已经被预定执行:待BGSAVE执行完毕后,BGREWRITEAOF将正式开始。Redis启动时,如果同时开启了RDB持久化和AOF持久化,程序将优先使用AOF文件来恢复数据集,因为AOF文件保存的数据通常更完整。为了备份redis数据,需要创建一个定期任务(cron job)来执行备份操作。每小时将一个RDB文件备份到一个文件夹,并且每天将一个RDB文件备份到另一个文件夹。要确保备份的快照都带有相应的日期和时间信息,并且在执行备份任务脚本时,使用find命令来删除过期的快照。至少每天将RDB备份到数据中心之外,或者至少备份到运行Redis服务器的物理机器之外。对于

性能方面的建议

在使用中,由于RDB文件仅用作备份目的,建议仅在从服务器上持久保存RDB文件,并且只需每15分钟备份一次即可,只保留save 900 1这一个规则。启用AOF后,最大的好处是即使在最糟糕的情况下也只会丢失不超过2秒的数据。而且启动脚本也更为简单,只需要加载自己的AOF文件即可。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。

只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设置到5G以上。当超过初始大小的100%时,可以调整至合适的尺寸。如果不启用AOF,通过主从复制也可以实现高可用性。能省掉一大笔IO,也减少了rewrite时带来的系统波动。当Master/Slave同时崩溃时,可能会丢失十几分钟的数据。启动脚本还需要比较两对Master/Slave中的RDB文件,并选择载入较新的那一个。以上就是今天的全部内容了。如果您对此有不同的意见或更好的想法,欢迎联系我,我可以将您加入技术交流群并参与讨论哦!

这篇文章是从微信公众号「阿Q说代码」转载的,扫描以下二维码可以关注该公众号。请在转载本文时与阿Q说代码公众号联系。

 

BOB半岛入口

BOB半岛官方

BOB半岛平台

面试官:您提到熟悉Redis,您了解持久化配置吗?

BOB半岛首页


BOB半岛官方

推荐新闻