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

Redis持久化原理深入探索

时间:2023-03-17 17:45:25 科技观察

Redis是一个内存数据库。为了保证数据的持久化,redis提供了RDB和AOF两种持久化方式。下面来看看这两种持久化方式的实现原理。RDB(默认)RDB是通过快照完成的。当满足某些条件时,redis会自动将内存中的数据持久化到磁盘中。触发快照的时机按照自定义配置的快照规则。(在redis.conf中配置,下面会详细介绍)执行save或bgsave命令执行flushall命令执行主从复制操作(第一次)原理图不会在快照的过程中,即在生成文件的过程中修改原来的rdb文件,直到生成snapshot,直接用新的替换旧的,随时保证rdb文件的完整性。我们可以通过定期备份rdb文件来备份redis数据。rdb是二进制压缩文件,占用空间小,利于传输###Snapshot设置规则save{多少秒}{数据变化了多少}例如:save1001:100秒内,进行快照如果至少有一个键被修改;save2004:在200秒内,如果至少修改了4个key,则进行快照。RDB的优缺点缺点:使用RDB进行持久化,当redis突然异常退出时,最后一次快照后的数据会丢失。但是,您可以根据组合设置自动快照,以减少数据丢失并确保在可接受的范围内。如果数据比较重要,可以使用AOF方式。优点:使用RDB方式可以最大化redis的性能。在快照过程中,我们可以看到主进程只需要fork一个子进程,其余的工作都由子进程完成。父进程不需要执行任何磁盘I/O操作。但是,如果数据集很大,fork子进程需要时间,会导致redis在一段时间内停止处理请求。AOF模式redis默认不开启AOF(appendonlyfile)。启动AOF后,redis每次接收到更改redis数据的命令,都会将命令写入硬盘中的AOF文件中。很明显,这个过程会降低redis的性能,但在大多数情况下是可以接受的。同时,使用性能更好的硬盘可以提高AOF性能。AOF配置方法#开启appendonly参数appendonlytrue#设置AOF文件的位置dir./#设置AOF文件名,默认为appendonly.aofappendfilenameappendonly.aof示意图RESP协议Redis客户端使用RESP协议与客户端通信雷迪斯服务器。该协议专为redis设计,但也可用于其他C-S项目。区间符号:linux中为\r\n,windows中为\n简单字符串以'+'开头错误,以'-'开头整数类型Integer,以':'开头大字符串以'$'开头的数组类型是Arrays,AOF以'*'开头的原理表示redis通过将所有写命令记录到AOF文件中来持久化数据。将命令记录到AOF文件的过程可以分为三个阶段:命令传播、缓存追加、文件写入和保存、命令传播。Redis将执行的命令、命令参数、命令参数格数发送给AOF程序。redis客户端执行命令时,通过连接将协议文本发送给redis。Redis收到协议文本后,根据内容选择合适的命令函数,将协议文本转换为Redis字符串对象,完成命令函数的执行。之后,将命令参数发送给AOF程序。cacheappendAOF程序收到命令参数后,会将其从字符串对象转换为协议内容,然后将协议内容追加到AOF缓存中。AOF缓存在redisServer结构体的aof_buf中,新的内容会追加到aof_buf的末尾。aof_buf保存所有尚未写入AOF文件的协议文本。文件写入和保存将AOF缓存内容写入AOF文件并保存到磁盘。flushAppendOnlyFile函数将在执行服务器的常规函数??或执行事件处理程序时执行。会有以下两个过程。WRITE:将AOF缓存中的内容写入AOF文件SAVE:调用fsync或fdatasync函数将AOF文件保存到磁盘AOF有三种保存方式AOF_FSYNC_NO:不保存。在这种模式下,每次调用flushAppendOnlyFile函数时,都会执行write而忽略save。只有在以下三种情况下才会触发save,redis关闭,aof功能关闭,系统写缓存刷新(可能缓存满了,或者定期进行维护操作)。在这三种情况下执行save操作都会导致redis的主线程被阻塞。AOF_FSYNC_EVERYSEC(默认):每秒保存一次。save每秒执行一次,但是save是由后台子线程完成的,不会导致redis主线程阻塞。AOF_FSYNC_ALWAYS:每次执行命令时保存。这种情况下,每条命令write和save都会被执行,save操作由主线程完成,会导致redis阻塞。安全性更高,性能更差,所以不推荐。AOF文件优化当AOF文件过大时,Redis可以在后台(子进程)重写AOF文件。重写后的新文件包含恢复当前数据集所需的最少命令集。重写并不是读写AOF文件,而是针对数据库中的当前key。优化前,sets11sets12sets13优化后,sets13AOF文件优化原理AOF重写是通过子进程实现的,因此,主线程继续工作,有可能修改新的数据,可能导致数据数据库中与改写后的数据不一致。Redis通过增加AOF重写缓存来解决这个问题。当fork退出子进程时,新命令不仅会追加到已有的AOF文件中,还会在缓存中添加一条数据。Rewrite过程分析(需要保证写操作绝对安全)Redis在创建新的AOF文件后,会继续往原AOF文件中添加命令。即使数据库突然崩溃,原来的AOF文件和文件内容也没有丢失。当创建新的AOF文件时,会直接替换旧的AOF文件,并在新的AOF文件中添加命令。当子进程在重写时,主进程会完成以下任务:处理请求,继续向AOF文件中添加新的命令,将命令添加到AOF重写缓存中。确保一致的数据行以避免数据丢失。子进程改写时,会向主进程发送完成信号。这时主进程会将重写缓存的内容添加到新的AOF文件中,使新的AOF文件、数据库和旧的AOF文件的内容完全一致。然后重命名新的AOF文件并覆盖原来的AOF文件。这样程序就完成了新旧AOF文件的替换。当处理完成后,主进程会继续接受请求。整个改写过程中,只有最后的缓存写入和重命名替换操作会导致主进程阻塞,其他时间不会影响redis的正常运行,最大限度地减少AOF改写对redis的性能影响。优化触发条件#当当前AOF文件超过上次重写时AOF文件的大小时,当前AOF文件将被重写。如果没有改写,以启动时AOF文件的大小为准。auto-aof-rewrite-percentage100#限制允许重写的最小AOF文件,即当文件小于该值时,不需要重写优化auto-aof-rewrite-min-size64mb