深圳培训公司网站建设,美术学院网站建设,网站落地页制作,网络营销题库案例题原创不易#xff0c;注重版权。转载请注明原作者和原文链接 文章目录 Redis持久化介绍RDB原理Fork函数与写时复制关于写时复制的思考 RDB相关配置 AOF原理AOF持久化配置AOF文件解读AOF文件修复AOF重写AOF缓冲区与AOF重写缓存区AOF缓冲区可以替代AOF重写缓冲区吗AOF相关配置写后… 原创不易注重版权。转载请注明原作者和原文链接 文章目录 Redis持久化介绍RDB原理Fork函数与写时复制关于写时复制的思考 RDB相关配置 AOF原理AOF持久化配置AOF文件解读AOF文件修复AOF重写AOF缓冲区与AOF重写缓存区AOF缓冲区可以替代AOF重写缓冲区吗AOF相关配置写后日志 混合持久化如何选择合适的持久化方式 在现今的数据驱动世界中数据持久化成为了一项至关重要的任务。它不仅需要保证数据的安全还要提供快速读写的功能。 对于许多现代化应用程序和服务来说Redis被广泛使用作为一个高性能的键值存储系统。Redis以其卓越的性能和灵活性赢得了开发者们的青睐。然而这些优点都离不开它强大的持久化机制。
通过本文我们将深入探讨Redis的持久化策略包括RDBRedis DataBase快照和AOFAppend Only File日志并解析如何根据自己的业务需求选择合适的持久化方案。
Redis持久化介绍
你也许会问为什么需要持久化呢因为Redis作为一款内存数据库在进程异常退出或服务器断电之后所有的数据都将消失。如果没有持久化功能无法保证数据的持久性那么这样的数据库还有什么用呢
Redis持久化分为两种「RDBRedis DataBase」和「AOFAppend Only File」。
RDB是指将Redis内存中的数据定期写入磁盘上的一个快照文件中而AOF则是以追加的方式记录Redis执行的每一条写命令。
你也可以同时开启两种持久化方式在这种情况下当Redis重启的时候会优先载入AOF文件来恢复原始的数据。
接下来我们将分别介绍RDB和AOF的实现原理。
RDB原理
RDB是Redis默认的持久化方式它将Redis在内存中的数据定期写入到硬盘中生成一个快照文件。快照文件是一个二进制文件包含了Redis在某个时间点的所有数据。
RDB的优点是快速、简单适用于大规模数据备份和恢复。但是RDB也有缺点例如数据可能会丢失因为Redis只会在指定的时间点生成快照文件。如果在快照文件生成之后但在下一次快照文件生成之前服务器宕机那么这期间的数据就会丢失。
由于RDB文件是以二进制格式保存的因此它非常紧凑并且在Redis重启时可以迅速地加载数据。相比于AOFRDB文件一般会更小。
RDB持久化有两种方式手动和自动。
手动方式通过SAVE命令或BGSAVE命令进行
SAVE命令会阻塞Redis服务器直到快照文件生成完成。BGSAVE命令会Fork一个子进程注意是子进程不是子线程在后台生成快照文件不会阻塞Redis服务器。
自动方式则是在配置文件中设置 让它在**“ N 秒内数据集至少有 M 个改动”**这一条件被满足时 自动保存一次数据集。
比如说以下设置会让 Redis 在满足 “10秒内有至少100 个键被改动” 这一条件时 自动保存一次数据集。
save 10 100Fork函数与写时复制
在 Redis 中Fork 函数被用于创建子进程。Redis 的使用场景中通常有大量的读操作和较少的写操作而 Fork 函数可以利用 Linux 操作系统的写时复制Copy On Write即 COW机制让父子进程共享内存从而减少内存占用并且避免了没有必要的数据复制。
我们可以使用 Linux下的 man fork 命令来查看下Fork函数的说明文档。 翻译如下
在Linux下fork()是使用写时复制的页实现的所以它唯一的代价是复制父进程的页表以及为子进程创建独特的任务结构所需的时间和内存。
简单来说就是 fork()函数会复制父进程的地址空间到子进程中复制的是指针而不是数据所以速度很快。
在 Redis 中当执行 RDB 持久化操作时Redis 会调用 fork 函数创建子进程然后由子进程负责将数据写入到磁盘中。为了避免父子进程同时对内存中的数据进行修改导致数据不一致。Redis 会启用写时复制机制。
这样当父进程修改内存中的数据时 Linux 内核会将该部分内存复制一份给子进程使用从而保证父子进程间的数据互相独立。
示意图如下 当没有发生写的时候子进程和父进程指向地址是一样的发生写的时候就会拷贝出一块新的内存区域实现父子进程隔离。
通过使用 fork 函数和写时复制机制Redis 可以高效地执行 RDB 持久化操作并且不会对 Redis 运行过程中的性能造成太大的影响。同时这种方式也提供了一种简单有效的机制来保护 Redis 数据的一致性和可靠性。
不过需要注意的是
fork的这个过程主进程是阻塞的fork完之后不阻塞。RDB 需要经常fork子进程来保存数据集到硬盘上当数据集比较大的时候fork的过程是非常耗时的可能会导致Redis在一些毫秒级内不能响应客户端的请求数据集很大的时候fork过程可能会持续数秒。
可能会因为数据量大而导致主进程长时间被挂起造成Redis服务不可用。因此在设计时应尽可能减少数据量或者优化fork的调用频率。
关于写时复制的思考
上述写时复制流程貌似有个问题
比如有个键值对 k1 a 。此时Redis正在bgsave。这时客户端发来一个请求主进程发生写操作set k1 b由于写时复制此时子进程里k1的值还是a。最终持久化的也是a。
为什么不直接持久化新值而持久化旧值写时复制的意义是什么
基于上面的问题可以给出的解释主要有两点
其实Redis为了性能考虑内存的持久化是一个顺序写的操作。子进程备份RDB是一个顺序写的过程如果主进程的所有写入请求都随时记录到RDB文件中那么理论更新的key可能在任何位置出现就会变为随机写性能低。其次如果主进程一直在写入更新key的话那么这次RDB备份一直都在写主进程写入的新值永远不会停止。
RDB相关配置
以下是一些RDB的相关参数配置 save指定 RDB 持久化操作的条件。当 Redis 的数据发生变化并且经过指定的时间seconds和变化次数changes后Redis 会自动执行一次 RDB 操作。例如save 3600 10000 表示如果 Redis 的数据在一个小时内发生了至少 10000 次修改那么 Redis 将执行一次 RDB 操作。 stop-writes-on-bgsave-error指定在 RDB 持久化过程中如果出现错误是否停止写入操作。如果设置为 yes当 Redis 在执行 RDB 操作时遇到错误时Redis 将停止接受写入操作如果设置为 noRedis 将继续接受写入操作。 rdbcompression指定是否对 RDB 文件进行压缩。如果设置为 yesRedis 会在生成 RDB 文件时对其进行压缩从而减少磁盘占用空间如果设置为 noRedis 不会对生成的 RDB 文件进行压缩。 rdbchecksum指定是否对 RDB 文件进行校验和计算。如果设置为 yes在保存 RDB 文件时Redis 会计算一个 CRC64 校验和并将其追加到 RDB 文件的末尾在加载 RDB 文件时Redis 会对文件进行校验和验证以确保文件没有受到损坏或篡改。 replica-serve-stale-data这是 Redis 4.0 中新增的一个配置项用于指定复制节点在与主节点断开连接后是否继续向客户端提旧数据。当设置为 yes 时在复制节点与主节点断开连接后该节点将继续向客户端提供旧数据直到重新连接上主节点并且同步完全新的数据为止当设置为 no 时复制节点会立即停止向客户端提供数据并且等待重新连接上主节点并同步数据。需要注意的是当 replica-serve-stale-data 设置为 yes 时可能会存在一定的数据不一致性问题因此建议仅在特定场景下使用。 repl-diskless-sync这是 Redis 2.8 中引入的一个配置项用于指定复制节点在进行初次全量同步即从主节点获取全部数据时是否采用无盘同步方式。当设置为 yes 时复制节点将通过网络直接获取主节点的数据并且不会将数据存储到本地磁盘中当设置为 no 时复制节点将先将主节点的数据保存到本地磁盘中然后再进行同步操作。采用无盘同步方式可以避免磁盘 IO 操作对系统性能的影响但同时也会增加网络负载和内存占用。因此应该根据具体的场景和需求选择合适的同步方式。
AOF原理
AOF持久化是按照Redis的写命令顺序将写命令追加到磁盘文件的末尾。AOF是一种基于日志的持久化方式它保存了Redis服务器所有写入操作的日志记录以保证数据的持久性、可靠性和完整性。
AOF持久化技术的核心思想是将Redis服务器执行的所有写命令追加到一个文件中。当Redis服务器重新启动时可以通过重新执行AOF文件来恢复服务器的状态。
AOF有个比较好的优势是可以恢复误操作。
举个例子如果你不小心执行了 FLUSHALL 命令导致数据被误删了 但只要 AOF 文件未被重写那么只要停止服务器移除 AOF 文件末尾的 FLUSHALL 命令并重启 Redis 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
AOF持久化配置
Redis的AOF持久化配置频率可通过appendfsync 参数进行控制。该参数有以下三个选项
always每次有数据修改都立即写入磁盘是最安全的选项。everysec每秒钟写入一次性能和安全之间做了一个平衡。no从不主动写入完全依靠操作系统自身的缓存机制来决定何时将数据写入磁盘。
默认情况下Redis的appendfsync参数设置为everysec。如果需要提高持久化安全性可以将其改为always如果更关注性能则可以将其改为no。但是需要注意的是使用no可能会导致数据丢失的风险建议在应用场景允许的情况下谨慎使用。
AOF文件解读
一个简单的AOF文件示例如下 其中
*号表示参数个数后面紧跟着参数的长度和值。$号表示参数长度后面紧跟着参数的值。
实际上AOF文件中保存的所有命令都遵循相同的格式即以*开头表示参数个数$开头表示参数长度其后紧跟着参数的值。
AOF文件修复
服务器可能在程序正在对 AOF 文件进行写入时停机造成AOF 文件损坏。
发生这种情况时可以使用 Redis 自带的 redis-check-aof 程序对 AOF 文件进行修复命令如下:
$ redis-check-aof –fixAOF重写
Redis的AOF重写机制指的是将AOF文件中的冗余命令删除以减小AOF文件的大小并提高读写性能的过程。
Redis的AOF重写机制采用了类似于复制的方式首先将内存中的数据快照保存到一个临时文件中然后遍历这个临时文件只保留最终状态的命令生成新的AOF文件。
具体来说Redis执行AOF重写可以分为以下几个步骤
开始AOF重写过程向客户端返回一个提示信息。创建一个临时文件并将当前数据库中的键值对写入到临时文件中。在创建的临时文件中将所有的写命令都转换成Redis内部的表示格式即使用一系列的Redis命令来表示一个操作例如使用SET命令来表示对某个键进行赋值操作。对临时文件进行压缩去掉多余的空格和换行符等减小文件体积。将压缩后的内容写入到新的AOF文件中。停止写入命令到旧的AOF文件并将新的AOF文件的文件名替换为旧的AOF文件的文件名。结束AOF重写过程并向客户端发送完成提示信息。
通过AOF重写机制Redis可以在不停止服务的情况下减小AOF文件的大小提高读写性能同时也可以保证数据的一致性。
Redis提供了手动触发AOF重写的命令 BGREWRITEAOF 。可以在Redis的客户端中执行该命令来启动AOF重写过程。Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令到了 Redis 2.4 则可以自动触发 AOF 重写。
具体操作步骤如下 打开redis-cli命令行工具连接到Redis服务。 执行BGREWRITEAOF命令启动AOF重写过程。 $ redis-cli
127.0.0.1:6379 BGREWRITEAOFRedis会返回一个后台任务的ID表示AOF重写任务已经开始。 127.0.0.1:6379 BGREWRITEAOF
Background append only file rewriting started by pid 1234可以使用 INFO PERSISTENCE 命令查看当前AOF文件的大小和重写过程的状态等待重写完成即可。 127.0.0.1:6379 INFO PERSISTENCE
# Persistence
aof_enabled:1
aof_rewrite_in_progress:1
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:0
aof_current_rewrite_time_sec:14
aof_last_bgrewrite_status:ok
aof_last_write_status:ok需要注意的是执行BGREWRITEAOF命令可能会占用较多的CPU和内存资源因此在生产环境中需要谨慎使用并确保有足够的系统资源支持。
同时即使手动触发AOF重写Redis也会在满足一定条件时自动触发AOF重写以保证AOF文件的大小和性能。
需要注意的是
在版本号大于等于 2.4 的 Redis 中BGSAVE 执行的过程中不可以执行 BGREWRITEAOF 。反过来说在 BGREWRITEAOF 执行的过程中也不可以执行 BGSAVE。目的是防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。
AOF缓冲区与AOF重写缓存区
在Redis中尽管「AOF缓冲区」和「AOF重写缓冲区」的名称相似但它们实际上是两个不同的概念。
AOF缓冲区是一个用于暂存需要写入AOF文件的命令的缓冲区。在Redis处理客户端发来的写命令时如果开启了AOF持久化功能则该命令将被先写入到AOF缓冲区。AOF缓冲区中的内容通过配置的规则持久化到磁盘上。持久化规则可以通过配置项appendfsync来调整。
AOF重写缓冲区是一个用于执行AOF文件的重写操作的缓冲区。AOF重写操作是一种将现有AOF文件重写成最小化的新AOF文件的操作。AOF重写操作的目的是减少AOF文件的大小同时加快恢复速度。AOF重写缓存区在AOF重写时开始启用Redis服务器主进程在执行完写命令之后会同时将这个写命令追加到AOF缓冲区和AOF重写缓冲区。
示意图如下 AOF缓冲区可以替代AOF重写缓冲区吗
AOF缓冲区不可以替代AOF重写缓冲区。
原因是AOF重写缓冲区记录的是从重写开始后的所有需要重写的命令而AOF缓冲区可能只记录了部分的命令如果写回的话AOF缓存区的数据就会失效被丢失因而只会保存一部分的命令而AOF重写缓存区不会。
AOF缓冲区主要是Redis用来解决主进程执行命令速度与磁盘写入速度不同步所设置的通过AOF缓冲区可以有效地避免频繁对硬盘进行读写进而提升性能。Redis在AOF持久化的时候会先把命令写入到AOF缓冲区然后通过写回策略来写入硬盘AOF文件。
AOF相关配置
在 Redis 的配置文件 redis.conf 中可以通过以下配置项来设置 AOF 相关参数 appendonly该配置项用于开启或关闭 AOF默认为关闭。若开启了 AOFRedis 会在每次执行写命令时将命令追加到 AOF 文件末尾。 appendfilename用于设置 AOF 文件名默认为 appendonly.aof。 appendfsync该配置项用于设置 AOF 的同步机制。有三种可选值 always表示每个写命令都要同步到磁盘安全性最高但是性能较差。everysec表示每秒同步一次是默认选项既能保证数据安全又具有较好的性能。no表示不进行同步而是由操作系统决定何时将缓冲区中的数据同步到磁盘上性能最好但是安全性较低。 auto-aof-rewrite-percentage和auto-aof-rewrite-min-size这两个配置项用于设置 AOF 重写规则。当 AOF 文件大小超过 auto-aof-rewrite-min-size 设置的值并且 AOF 文件增长率达到 auto-aof-rewrite-percentage 所定义的百分比时Redis 会启动 AOF 重写操作。 auto-aof-rewrite-percentage默认值为100以及auto-aof-rewrite-min-size默认值为64mb也就是说默认Redis会记录上次重写时的AOF大小默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。 aof-use-rdb-preambleRedis 4版本新特性混合持久化。AOF重写期间是否开启增量式同步该配置项在AOF重写期间是否使用RDB文件内容。默认是no如果设置为yes在AOF文件头加入一个RDB文件的内容可以尽可能的减小AOF文件大小同时也方便恢复数据。
写后日志
我们比较熟悉的是数据库的写前日志Write Ahead LogWAL也就是说在实际写数据前先把修改的数据记到日志文件中以便故障时进行恢复。
不过AOF 日志却正好相反它是写后日志“写后”的意思是 Redis 是先执行命令把数据写入内存然后才记录日志。
为什么要这样设计
其实为了避免额外的检查开销Redis 在向 AOF 里面记录日志的时候并不会先去对这些命令进行语法检查。所以如果先记日志再执行命令的话日志中就有可能记录了错误的命令Redis 在使用日志恢复数据时就可能会出错。
而写后日志这种方式就是先让系统执行命令只有命令能执行成功才会被记录到日志中否则系统就会直接向客户端报错。所以Redis 使用写后日志这一方式的一大好处是可以避免出现记录错误命令的情况。
除此之外AOF 写后日志还有一个好处它是在命令执行后才记录日志所以并不会阻塞当前的写操作。
不过写后日志也有两个潜在的风险
首先如果刚执行完一个命令还没有来得及记日志就宕机了那么这个命令和相应的数据就有丢失的风险。如果此时 Redis 是用作缓存还可以从后端数据库重新读入数据进行恢复但是如果 Redis 是直接用作数据库的话此时因为命令没有记入日志所以就无法用日志进行恢复了。其次AOF 虽然避免了对当前命令的阻塞但可能会给下一个操作带来阻塞风险。这是因为AOF 日志也是在主线程中执行的如果在把日志文件写入磁盘时磁盘写压力大就会导致写盘很慢进而导致后续的操作也无法执行了。
混合持久化
在过去 Redis 用户通常会因为 RDB 持久化和 AOF 持久化之间不同的优缺点而陷入两难的选择当中
RDB 持久化能够快速地储存和恢复数据但是在服务器停机时可能会丢失大量数据。AOF 持久化能够有效地提高数据的安全性但是在储存和恢复数据方面却要耗费大量的时间。
为了让用户能够同时拥有上述两种持久化的优点 Redis 4.0 推出了一个“鱼和熊掌兼得”的持久化方案 —— RDB-AOF 混合持久化。
这种持久化能够通过 AOF 重写操作创建出一个同时包含 RDB 数据和 AOF 数据的 AOF 文件 其中 RDB 数据位于 AOF 文件的开头 它们储存了服务器开始执行重写操作时的数据库状态。至于那些在重写操作执行之后执行的 Redis 命令 则会继续以 AOF 格式追加到 AOF 文件的末尾 也即是 RDB 数据之后。
也就是说当开启混合持久化之后AOF文件中的内容前半部分是二进制的RDB内容后面跟着AOF增加的数据AOF位于两次RDB之间。
格式会类似下面这样
二进制RDBAOF
二进制RDB在目前版本中 RDB-AOF 混合持久化功能默认是处于关闭状态的 为了启用该功能 用户不仅需要开启 AOF 持久化功能 还需要将 aof-use-rdb-preamble 选项的值设置为 true。
appendonly yes
aof-use-rdb-preamble yes如何选择合适的持久化方式
当你想选择适合你的应用程序的持久化方式时你需要考虑以下两个因素 数据的实时性和一致性如果对数据的实时性和一致性有很高的要求则AOF可能是更好的选择。 如果对数据的实时性和一致性要求不太高并且希望能快速地加载数据并减少磁盘空间的使用那么RDB可能更适合你的应用程序。因为RDB文件是二进制格式的结构非常紧凑所以在Redis重启时可以迅速地加载数据。 Redis的性能需求如果对Redis的性能有很高的要求那么关闭持久化功能也是一个选择。因为持久化功能可能会影响Redis的性能但是一般不建议这么做。
本篇文章到这就结束了最后我们来做个小总结
我们要意识到Redis的持久化机制扮演着至关重要的角色。RDB和AOF两种主要的持久化方式各有其优势和使用场景。
RDB通过提供特定时间点的数据快照对于灾难恢复是非常有效的而AOF则通过记录每个写入操作提供了更好的数据持久性保证。然而它们也有各自的局限性这就需要根据实际需求来权衡选用哪种持久化方式。
最后不可忽视的是在选择合适的持久化策略时我们还应考虑如何平衡内存使用、磁盘使用、性能与持久性等多个因素。只有对Redis持久化的深入理解我们才能充分利用其强大的功能以满足各种业务需求。
希望这篇文章能够给你带来收获和思考谢谢。