当前位置: 首页 > 科技观察

面试官:你说你精通Redis,你见过持久化配置吗?

时间:2023-03-23 12:16:16 科技观察

我们已经介绍了Redis的五种数据类型的命令和配置文件的基本配置。今天,就让我们从理论和配置两个层面来揭开Redis持久化的神秘面纱。所谓持久化,可以简单理解为将内存中的数据保存到硬盘中存储的过程。持久化的数据在系统重启或宕机后仍然可以访问,保证数据安全。Redis有两种持久化方案,一种是快照模式(SNAPSHOTTING),简称RDB;另一种是只追加模式(APPENDONLYMODE),称为AOF。接下来,我们就来看看它们的使用方法和注意事项吧。RDBRDB是RedisDataBase的缩写,是Redis默认的持久化方案。它可以按指定的时间间隔将内存数据集的快照(snapshot)写入磁盘,并在恢复时将快照文件(dump.rdb)读回内存。我们先看一下配置文件中的SNAPSHOTTING:configurationfilesave在给定的秒数内,如果对数据库的写操作次数达到设定值,则将数据同步到数据文件。支持多种条件,Redis默认配置文件提供三种条件:save9001//900s变化1次save30010//300s变化10次save6010000//60s变化10000次注意:如果不想使用RDB方案,可以打开save""的注释,把上面三个注释掉。stop-writes-on-bgsave-erroryes当bgsave出错时,Redis是否停止执行写命令;如果是,当硬盘出现问题时,Redis会停止接受写操作,方便我们及时发现,避免数据大量丢失;如果不是,Redis忽略bgsave错误,继续执行写命令。如果您已经为您的Redis服务器设置了适当的监控和持久化,即使用其他方法来发现和控制数据完整性,您可能希望禁用此功能,以便即使磁盘、权限等出现问题,Redis仍然可以工作。注意:如果后台保存进程将再次开始工作,Redis将自动允许再次写入。rdbcompressionyes指定数据存储到本地数据库时是否压缩(Redis使用LZF压缩)数据,默认是yes。如果想节省CPU时间,可以关闭这个选项,但是会导致数据库文件变得巨大。rdbchecksumyes从RDBversion5开始,还可以使用CRC64算法对存储快照后的数据进行校验,CRC64校验和放在文件末尾。启用后,保存和加载RDB文件会增加10%左右的性能消耗。如果你想获得最大的性能提升,你可以关闭这个功能。Disablechecksumming会创建校验和为零的RDB文件,这会告诉加载代码跳过检查。dbfilenamedump.rdb指定本地数据库文件名,重启后会自动加载到内存中,如果手动执行save命令会立即生效。大坑请注意:flushall和shutdown命令会清空并提交到dump.rdbdir./指定本地数据库存放目录。理论工作方法当Redis需要保存dump.rdb文件时,会调用系统函数fork()创建一个子进程(与主进程完全一样);子进程将数据集写入临时文件RDB;当子进程完成写入一个新的RDB文件时,Redis会用新的RDB文件替换原来的RDB文件,并删除旧的RDB文件。这种工作方式让Redis受益于写时复制机制。如何触发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方式宕机时数据丢失过多的问题,从1.1版本开始,Redis增加了持久化的持久化方式:AOF。AOF是AppendOnlyFile的缩写,默认不启用。AOF以日志的形式记录每一次写操作。它只允许追加文件而不允许重写文件。当服务器重新启动时,这些命令将被重新执行以恢复原始数据。我们看一下配置文件中的APPENDONLYMODE:配置文件appendonlyno默认是关闭的,改为yes开启持久化。AOF和RDB可以同时启用而不会出现问题。appendfilename"appendonly.aof"是文件的默认名称,将在启动时创建。加载先于dump.rdb文件appendfsync同步策略:系统函数fsync()告诉操作系统将数据实际写入磁盘。Redis支持三种不同的模式appendfsyncalways//每次发生数据变化,立即记录到磁盘,性能较差但数据完整性更好appendfsynceverysec//推荐默认,异步操作,每秒记录一次,ifdowntime,1秒内有数据丢失appendfsyncno//不同步,只在操作系统需要的时候刷新数据追加命令到文件末尾的方式,这样随着写命令的增加,sizeofAOF文件会越来越大。为了避免这种情况,增加了一种重写机制:可以在不中断服务客户端的情况下重建AOF文件。重写触发器:通过执行bgrewriteaof命令,可以生成一个新的AOF文件,其中包含重建当前数据集所需的最少命令。Redis2.2需要手动执行该命令,而Redis2.4可以通过修改配置文件自动触发(配置见下文)。改写原理:Redis执行系统函数fork()创建子进程(与主进程完全一样);子进程开始将新的AOF文件内容写入临时文件;对于所有新执行的写入命令,父进程在将它们累积到内存缓存中的同时,将这些变化追加到已有的AOF文件的末尾,这样即使重写中途出现宕机,已有的AOF文件也是安全的;当子进程完成重写工作时,它向父进程发送信号,父进程收到信号后将内存缓存中的所有数据追加到新的AOF文件的末尾。Redis自动用新文件替换旧文件,之后所有命令都直接附加到新AOF文件的末尾。no-appendfsync-on-rewriteno当我们同时进行主进程的写操作和子进程的重写操作时,两者都会对磁盘进行操作,而重写往往会涉及到大量的磁盘操作,这会导致主进程在写aof文件时出现阻塞情况。为了解决这个问题,no-appendfsync-on-rewrite参数发挥了作用。如果这个参数设置为no,是最安全的方式,不会丢失数据,但是你要忍受阻塞的问题;如果设置为yes,这相当于将appendfsync设置为no,表示不进行任何磁盘操作,只是写入buffer。所以这样不会造成阻塞(因为没有竞争的磁盘),但是如果此时redis挂了,数据就会丢失。丢失了多少数据?在Linux操作系统的默认设置下,最多会丢失30s的数据。因此,如果应用系统不能容忍延迟,但可以容忍少量数据丢失,则设置为yes;如果应用系统不能容忍数据丢失,则设置为no。auto-aof-rewrite-percentage100重写百分比,默认为上次重写后aof文件大小的两倍。auto-aof-rewrite-min-size64mb重写触发器的最小值:64mb。根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。Redis会记录上次重写的AOF大小。默认配置是当AOF文件大小是上次rewrite后的两倍大小,且文件大于64M时触发。大型互联网公司一般都是3G开头的aof-load-truncatedyes。当AOF文件被截断时,即AOF文件的最后一条命令不完整。如果此时启动Redis,AOF的数据会重新加载到内存中,此时就会出现问题。.yes:加载截断的AOF,Redis服务器开始发出日志,通知用户该事件;否:服务器将因错误而中止,拒绝启动。当我们得知AOF文件报错时,我们可以使用以下方法来修复错误的AOF文件:为已有的AOF文件创建一个备份;使用Redis附带的redis-check-aof命令修复原始AOF文件;redis-check-aof–fixredis-check-aof–fixappendonly.aof修复命令,杀死所有不兼容的语法(可选)使用diff-u比较修复后的AOF文件和原始AOF文件的备份,检查two两个文件的区别;重启Redis服务器,等待服务器加载修复后的AOF文件,进行数据恢复。aof-use-rdb-preambleyes在重写AOF文件时,Redis可以在AOF文件中使用RDBpreamble来加速重写和恢复。启用该选项后,重写后的AOF文件由两个不同的部分组成:RDB文件,AOF尾加载Redis时,会识别AOF文件以Redis字符串开头,加载带前缀的RDB文件,然后继续加载AOF尾部。理论优势数据的完整性和一致性更高,AOF的持久化采用不同的策略最多丢失1秒的数据;AOF文件是只追加的日志文件,不需要写seek;Redis可以在AOF文件变大时,在后台自动重写AOF,重写操作绝对安全;AOF文件记录的写入操作以Redis协议的格式保存,便于文件的读取和分析;缺点对于相同的数据集,AOF文件的体积通常比RDB文件大;根据使用的fsync策略,AOF的速度可能比RDB慢。总的来说每秒fsync的性能还是很高的,关闭fsync可以让AOF和RDB一样快,即使是在高负载下。但是,在处理巨大的写入负载时,RDB可以提供更有保障的最大延迟(latency)。比较总结如何选择使用哪种持久化方式?一般来说,如果要达到媲美PostgreSQL的数据安全性,应该同时使用两种持久化功能。如果你非常在意你的数据,但仍然可以容忍数据在几分钟内丢失,那么你可以使用RDB持久化。因为AOF持久化的实时性更好,即进程意外退出时丢失的数据更少,所以AOF是目前主流的持久化方式。很多用户只使用AOF持久化,但我们不推荐这种方式:因为定期生成RDB快照(snapshots)非常方便数据库备份,RDB恢复数据集的速度也比AOF恢复快。AOF与RDB交互在版本号大于等于2.4的Redis中,BGSAVE执行过程中不能执行BGREWRITEAOF。反之,在BGREWRITEAOF执行过程中不能执行BGSAVE。这可以防止两个Redis守护进程同时对磁盘进行大量I/O。如果正在执行BGSAVE,用户显式调用BGREWRITEAOF命令,服务器会回复用户一个OK状态,并告知用户BGREWRITEAOF已被调度执行:一旦BGSAVE执行完毕,BGREWRITEAOF将正式启动。Redis启动时,如果同时开启RDB持久化和AOF持久化,程序会优先使用AOF文件恢复数据集,因为AOF文件保存的数据通常是最完整的。备份redis数据创建定时任务(cronjob)每小时备份一个RDB文件到一个文件夹,每天备份一个RDB文件到另一个文件夹;确保快照备份有对应的日期和时间信息,每次执行周期任务脚本时使用find命令删除过期的快照;至少每天一次,在数据中心之外备份RDB,或者至少在运行Redis服务器的物理机器上备份。在实际应用中,由于RDB文件只用于备份,所以建议只在slave上持久化RDB文件,每隔15分钟只需要备份一次。仅保留save9001规则。如果开启AOF,好处是在最坏的情况下,你只会丢失不超过2秒的数据。启动脚本比较简单,只需要加载自己的AOF文件即可。第一个成本是不断的IO,第二个是AOFrewrite最终将rewrite过程中产生的新数据写入到新文件中,这几乎是不可避免的。只要硬盘允许,尽量减少AOF重写的频率。AOFrewrite的basesize默认值是64M,太小了,可以设置到5G以上。当默认值超过原始大小的100%时,rewrite可以改成合适的值。如果不开启AOF,也可以只通过Master-SlaveReplication实现高可用。可以节省大量IO,减少rewrite带来的系统波动。代价是如果Master/Slave同时dump掉,十几分钟的数据会丢失。启动脚本还会比较两个Master/Slave中的RDB文件,并加载较新的一个。以上就是今天的全部内容。如果有不同意见或者更好的想法欢迎联系阿Q,加阿Q加入技术交流群参与讨论!本文转载自微信公众号“阿Q说码”,可关注下方二维码。转载本文请联系阿Q获取代码公众号。