欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 《Redis4.0数据持久化》

《Redis4.0数据持久化》

2025/2/7 15:27:33 来源:https://blog.csdn.net/weixin_39380632/article/details/145457081  浏览:    关键词:《Redis4.0数据持久化》

【redis持久化导读】Redis作为一款高性能的内存数据库,支持key-value键值对的形式存储数据,为业务层提供了高效的数据查询能力,但大家有思考过一个问题没?假如redis服务所在的主机突然挂了,那么之前缓存在内存的数据是不是全部丢失了?那redis如何做到重启服务后,能快速地恢复宕机前的内存数据。

      直接进入主题,目前redis为了实现数据的持久化,实现了两套基础能力,AOF和RDB机制,那笔者分别为您介绍这两套持久化机制的区别、优缺点以及适用场景。

1、AOF机制(Append Only File)

      AOF日志,其实就是写后日志,比如:业务方向redis服务发出一条指令。

set hello world

   redis-server收到这条指令,修改内存中"hello"对应的value值为"world",修改成功后,redis-server把这条指令写到本地日志文件中,相当于作落盘修改。

图片

     那服务器宕机了,重启服务,redis能从宕机前持久化到磁盘的日志文件中,把"set hello world"这条指令给读取出来,恢复宕机前内存的数据状态。但AOF文件备份redis指令并不是明文保存的哈,以"set hello world"为例。AOF日志文件的内容可能是这样的。

*3$3set$5hello$5world

   根据笔者前一篇文章《redis4.0 通信模块源码分析(一)》知道,redis在处理网络IO、执行指令都是在一个线程的主Loop中完成,如果在主线程执行完指令后,就进行指令的持久化会带来什么问题?

    a、阻塞主线程,影响主线程响应网络IO事件

    b、如果AOF日志文件过大,那持久化会存在很大的性能问题

    c、如果执行指令前一秒,服务器宕机了,那么当前指令还是没法同步到AOF日志

    好,那一个个来,针对问题a,redis想出了fork子进程bgrewriteaof,子进程拷贝当前redis主线程的内存数据,子进程在后台做持久化操作,那就很巧妙地避免了"阻塞主线程"的问题了。

     针对问题b,假设AOF文件很大,比如:随着redis运行的时间的递增,AOF文件大小到了10G,那么此时往10G大小的AOF文件末位追加指令,势必给磁盘带来很大的压力,redis采用了重写机制,何为重写机制?

     AOF 在重写时,Redis根据数据库的现状创建一个新的AOF 文件,即读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。比如,当读取键值对"hello": "world"之后,重写机制只会记录 set hello world这条命令;但是老的AOF文件,可能存在这种情况,键值"hello"对应的value被多次修改,最终才变成"world",那么老AOF文件会记录下和"hello"相关的所有改动,因为老的AOF文件就存在很多多余的指令,新的AOF文件只会保留一条指令,能让内存中的数据恢复到最新的状态。也就是AOF重写机制极大地降低AOF文件的大小。

     针对问题c,因为fork了后台子进程去做AOF重写,Redis 会先执行一个内存拷贝,用于重写;不阻塞主线程,那最新的写入的数据也会同步到AOF缓冲区中去,就算此时宕机了,那AOF缓冲区的数据也会刷到磁盘中去,不会造成数据的丢失。

图片

      AOF机制虽然能保证redis数据的一致性,但如果AOF文件中存储的指令较多,当我们想恢复redis主机的数据,redis需要逐一执行AOF日志文件中的记录,就会导致恢复redis主机数据变得特别耗时。那有没有其它的方案?既保证数据的完整性,又能快速恢复主机数据;答案就是内存快照

2、内存快照(RDB)

     所谓内存快照,就是指内存中的数据在某一个时刻的状态记录,就相当于我们日常生活中照相一样,抓拍住某一瞬间的人物、风景的画像。

     但内存快照是不是也存在一些问题?

     a、如果想给内存中的数据做个全量的快照,是不是很耗时?会阻塞主线程吗?

     b、我们在做内存快照时,快照不可能一瞬间就完成,也是个耗时的过程,那在保存快照这个时间段,内存的数据能被修改吗?

     c、从开始快照到快照完成,这个时间段内,假设有其它额外的修改,这些修改记录如何保存下来?因为不可能频繁地做内存快照。

      针对问题a,和AOF重写机制一样,redis也会启个后台子进程做内存快照,不影响当前网络IO主线程,redis提供了指令bgsave。执行bgsave,redis会启动一个子进程在后台做全量快照。

    针对问题b,假设在时刻t,redis执行了bgsave做全量快照,但在t+10s这个时间点,业务方发起请求修改了内存中某个键值对为pairNew,那此时被修改的键值对不是时刻t记录的键值对pair,那pairNew肯定是不能存到内存快照中去的,那redis也不可能在快照期间禁止业务方修改数据,redis想到了操作系统的一项技术Copy-On-Write。

    何为Copy-On-Write,假如内存中有键值对Pair,此时准备做内存快照,当业务方要修改Pair,那这份键值对Pair会被拷贝一份副本PairNew出来,业务方修改的是PairNew,快照用的依然是Pair。这样既不影响快照,也不影响业务方修改redis中的数据。

图片

      针对问题c,Redis 4.0 提出了一个混合使用 AOF日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。那么就算在两次快照之间发生了宕机,那么中间的改动可以通过AOF文件进行恢复。

图片

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com