做网站客户没有付定金深圳涂料网站建设
2026/4/18 12:16:30 网站建设 项目流程
做网站客户没有付定金,深圳涂料网站建设,数字化展厅建设方案,顺德 网站设计背景 有个同学阿里二面#xff0c;面试官问#xff1a;redis宕机了#xff0c;如何恢复数据#xff1f; 这位同学当时一脸懵#xff0c;不知道如何回答。 分析分析这个问题#xff0c;redis宕机#xff0c;要想恢复数据#xff0c;首先redis的数据有没有做持久化…背景有个同学阿里二面面试官问redis宕机了如何恢复数据这位同学当时一脸懵不知道如何回答。分析分析这个问题redis宕机要想恢复数据首先redis的数据有没有做持久化用的是哪种策略这种策略的机制是什么有趣点是什么以及你们是从什么方面考虑用着中机制的其实面试官就是想考察你们业务中redis的持久化策略以及你对持久化策略有没有了解过还是就直接使用不管数据会回丢失反正丢失了都是运维的锅那你这样基本上GG了为什么要做持久化Redis是个基于内存的数据库。那服务一旦宕机内存中的数据将全部丢失。通常的解决方案是从后端数据库恢复这些数据但后端数据库有性能瓶颈如果是大数据量的恢复会对数据库带来巨大的压力严重可能导致mysql宕机数据库的性能不如Redis。导致程序响应慢。所以对Redis来说实现数据的持久化避免从后端数据库中恢复数据是至关重要的。持久化策略官方支持的持久化有四种如下RDBRedis 数据库RDB 持久性以指定的时间间隔执行数据集的时间点快照。AOF仅追加文件AOF 持久性记录服务器接收到的每个写操作。然后可以在服务器启动时再次重播这些操作从而重建原始数据集。命令使用与 Redis 协议本身相同的格式进行记录。RDB AOF您还可以在同一个实例中组合 AOF 和 RDB。无持久性您可以完全禁用持久性。这种策略一般很少有人使用吧下面我们对这几种策略进行详细梳理下RDBRDB 就是 Redis DataBase 的缩写中文名为快照/内存快照RDB持久化是把当前进程数据生成快照保存到磁盘上的过程由于是某一时刻的快照那么快照中的值要早于或者等于内存中的值。默认情况下Redis 将数据集的快照保存在磁盘上名为dump.rdb的二进制文件中。Redis 提供了两个命令来生成 RDB 文件分别是 save 和 bgsave。save在主线程中执行会导致阻塞bgsave创建一个子进程专门用于写入 RDB 文件避免了主线程的阻塞这也是 Redis RDB 文件生成的默认配置。一般通过 bgsave 命令来执行全量快照这既提供了数据的可靠性保证也避免了对 Redis 的性能影响。redis.conf中配置RDB内存快照虽然可以通过技术人员手动执行SAVE或BGSAVE命令来进行但生产环境下多数情况都会设置其周期性执行条件。# 周期性执行条件的设置格式为 save seconds changes # 默认的设置为 save 900 1 save 300 10 save 60 10000 # 以下设置方式为关闭RDB快照功能 save 以上三项默认信息设置代表的意义是如果900秒内有1条Key信息发生变化则进行快照如果300秒内有10条Key信息发生变化则进行快照如果60秒内有10000条Key信息发生变化则进行快照。Copy-On-Write, COWredis在执行bgsave生成快照的期间将内存中的数据同步到硬盘的过程可能就会持续比较长的时间而实际情况是这段时间Redis服务一般都会收到数据写操作请求。那么如何保证快照的完整性呢可能会说为了保证快照完整性redis只能处理读操作不能修改正在执行快照的数据。你想如果这样为了快照而暂停写操作同时候你的业务会受到很大的影响是不可接受的那有其他方案吗Redis 就会借助操作系统提供的写时复制技术Copy-On-Write, COW在执行快照的同时正常处理写操作。bgsave 子进程是由主线程 fork 生成的可以共享主线程的所有内存数据。bgsave 子进程运行后开始读取主线程的内存数据并把它们写入 RDB 文件。此时如果主线程对这些数据也都是读操作例如图中的键值对 A那么主线程和 bgsave 子进程相互不影响。但是如果主线程要修改一块数据例如图中的键值对 C那么这块数据就会被复制一份生成该数据的副本键值对 C’。然后主线程在这个数据副本上进行修改。同时bgsave 子进程可以继续把原来的数据键值对 C写入 RDB 文件。写时复制机制保证快照期间数据可修改这既保证了快照的完整性也允许主线程同时对数据进行修改避免了对正常业务的影响。快照的频率如何把握对于快照来说所谓“连拍”就是指连续地做快照。这样一来快照的间隔时间变得很短即使某一时刻发生宕机了因为上一时刻快照刚执行丢失的数据也不会太多。但是这其中的快照间隔时间就很关键了。如下图为了尽可能保证在宕机的情况下保证数据尽量不丢失比如一秒一次快照那丢失的数据也是一秒。这看上去很美好其实为带来很大的问题如果频繁地执行全量快照也会带来两方面的开销一方面频繁将全量数据写入磁盘会给磁盘带来很大压力多个快照竞争有限的磁盘带宽前一个快照还没有做完后一个又开始做了容易造成恶性循环。另一方面bgsave 子进程需要通过 fork 操作从主线程创建出来。虽然子进程在创建后不会再阻塞主线程但是fork 这个创建过程本身会阻塞主线程而且主线程的内存越大阻塞时间越长。如果频繁 fork 出 bgsave 子进程这就会频繁阻塞主线程了那这个频率怎么控制呢这需要根据业务自身的情况决定快照的频率。比如笔者我们目前的使用的策略是关闭系统的自动快照功能就是 设置save ,定时凌晨连接redis手动执行bgsave进行快照生成。可能有人说如果执行这样的策略数据丢失就是一天的对你说的对但是我们的业务丢失一天的数据也没关系这是业务能容忍的 在生产的情况下redis的稳定性相当高基本上不会宕机出现宕机的情况也是因为服务器自身的问题导致机器重启redis产生数据丢失。优缺点优点RDB文件是某个时间节点的快照默认使用LZF算法进行压缩压缩后的文件体积远远小于内存大小适用于备份、全量复制等场景Redis加载RDB文件恢复数据要远远快于AOF方式缺点RDB方式实时性不够无法做到秒级的持久化每次调用bgsave都需要fork子进程fork子进程属于重量级操作频繁执行成本较高RDB文件是二进制的没有可读性AOF文件在了解其结构的情况下可以手动修改或者补全总结rdb数据恢复速度非常快就是无法做到秒级的持久化那有其他方式做到秒级的持久化吗AofAOFAOF 持久性记录服务器接收到的每个写操作。然后可以在服务器启动时再次重播这些操作从而重建原始数据集。命令使用与 Redis 协议本身相同的格式进行记录Redis 是先执行命令把数据写入内存然后才记录日志AOF日志内容我们以 Redis 收到“set testkey 1”命令后记录的日志为例看看 AOF 日志的内容日志格式说明*3表示当前命令有三个部分每部分都是由$数字开头后面紧跟着具体的命令、键或值。这里数字表示这部分中的命令、键或值一共有多少字节。例如$3 set表示这部分有 3 个字节也就是set命令redis.conf中配置AOF默认情况下Redis是没有开启AOF的可以通过配置redis.conf文件来开启AOF持久化关于AOF的配置如下# appendonly参数开启AOF持久化 appendonly no # AOF持久化的文件名默认是appendonly.aof appendfilename appendonly.aof # AOF文件的保存位置和RDB文件的位置相同都是通过dir参数设置的 dir ./ # 同步策略 # appendfsync always appendfsync everysec # appendfsync no # aof重写期间是否同步 no-appendfsync-on-rewrite no # 重写触发配置 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 加载aof出错如何处理 aof-load-truncated yes # 文件重写策略 aof-rewrite-incremental-fsync yes写回策略AOF 机制给我们提供了三个选择也就是 AOF 配置项 appendfsync 的三个可选值。Always同步写回每个写命令执行完立马同步地将日志写回磁盘Everysec每秒写回每个写命令执行完只是先把日志写到 AOF 文件的内存缓冲区每隔一秒把缓冲区中的内容写入磁盘No操作系统控制的写回每个写命令执行完只是先把日志写到 AOF 文件的内存缓冲区由操作系统决定何时将缓冲区内容写回磁盘。针对避免主线程阻塞和减少数据丢失问题这三种写回策略都无法做到两全其美。我们来分析下其中的原因。“同步写回”可以做到基本不丢数据但是它在每一个写命令后都有一个慢速的落盘操作不可避免地会影响主线程性能虽然“操作系统控制的写回”在写完缓冲区后就可以继续执行后续的命令但是落盘的时机已经不在 Redis 手中了只要 AOF 记录没有写回磁盘一旦宕机对应的数据就丢失了“每秒写回”采用一秒写回一次的频率避免了“同步写回”的性能开销虽然减少了对系统性能的影响但是如果发生宕机上一秒内未落盘的命令操作仍然会丢失。所以这只能算是在避免影响主线程性能和避免数据丢失两者间取了个折中。我把这三种策略的写回时机以及优缺点汇总在了一张表格里以方便你随时查看。根据系统对高性能和高可靠性的要求来选择使用哪种写回策略了。总结一下就是想要获得高性能就选择 No 策略如果想要得到高可靠性保证就选择 Always 策略如果允许数据有一点丢失又希望性能别受太大影响的话那么就选择 Everysec 策略。虽然AOF策略能保证秒级数据丢失但是随着redis的长时间运行aof文件会越来越大如果宕机进行数据恢复的时候速度是特别慢影响业务那有什么好的发案处理吗AOF日志重写AOF 文件是以追加的方式逐一记录接收到的写命令的。当一个键值对被多条写命令反复修改时AOF 文件会记录相应的多条命令。但是在重写的时候是根据这个键值对当前的最新状态为它生成对应的写入命令。这样一来一个键值对在重写日志中只用一条命令就行了而且在日志恢复时只用执行这条命令就可以直接完成这个键值对的写入了。重写机制具有“多变一”功能。所谓的“多变一”也就是说旧日志文件中的多条命令在重写后的新日志中变成了一条命令例如我们对列表先后做了 6 次修改操作后列表的最后状态是[“D”, “C”, “N”]此时只用 LPUSH u:list “N”, “C”, “D”这一条命令就能实现该数据的恢复这就节省了五条命令的空间。对于被修改过成百上千次的键值对来说重写能节省的空间当然就更大了。不过虽然 AOF 重写后日志文件会缩小但是要把整个数据库的最新数据的操作日志都写回磁盘仍然是一个非常耗时的过程。那这个过程会阻塞主线程吗AOF重写会阻塞吗AOF重写过程是由后台进程bgrewriteaof来完成的。主线程fork出后台的bgrewriteaof子进程fork会把主线程的内存拷贝一份给bgrewriteaof子进程这里面就包含了数据库的最新数据。然后bgrewriteaof子进程就可以在不影响主线程的情况下逐一把拷贝的数据写成操作记入重写日志。优缺点优点数据能做到秒级丢失也就是说使用了aof这种机制能做到最多丢失一秒的数据缺点恢复数据比较慢虽然aof日志重写可以减小文件但是速度还是很慢那有没有一种机制能做到秒级丢失恢复速度又比较快呢RDB和AOF混合方式RDB和AOF混合方式Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说内存快照以一定的频率执行在两次快照之间使用 AOF 日志记录这期间的所有命令操作。这样一来快照不用很频繁地执行这就避免了频繁 fork 对主线程的影响。而且AOF 日志也只用记录两次快照间的操作也就是说不需要记录所有操作了因此就不会出现文件过大的情况了也可以避免重写开销。如下图所示T1 和 T2 时刻的修改用 AOF 日志记录等到第二次做全量快照时就可以清空 AOF 日志因为此时的修改都已经记录到快照中了恢复时就不再用日志了。内存快照和AOF混合使用这个方法既能享受到 RDB 文件快速恢复的好处又能享受到 AOF 只记录操作命令的简单优势颇有点“鱼和熊掌可以兼得”的感觉建议你在实践中用起来。总结Rdb、Aof两种持久化机制各有优缺点需要根据自己的实际业务来衡量到底使用哪种机制最能满足当下业务我的建议数据不能丢失时内存快照和 AOF 的混合使用是一个很好的选择如果允许分钟级别的数据丢失可以只使用 RDB如果只用 AOF优先使用 everysec 的配置选项因为它在可靠性和性能之间取了一个平衡。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询