Redis深度历险-Redis持久化

本文大部分内容引自《Redis深度历险:核心原理和应用实践》,感谢作者!!!

Redis持久化的方式

1、快照方式持久化,将内存中数据的二进制序列化形式备份到磁盘上,数据在存储上非常紧凑

2、AOF日志,记录内存数据修改的指令记录文本,在长期运行后AOF日志的体积将会变得无比庞大,数据库重启时加载AOF日志进行指令重放,这个时间就会很漫长。所以要定期进行AOF重写,给AOF日志进行瘦身

快照原理

Redis在服务器处理请求的时候还需要进行内存快照,内存快照要求Redis必须进行文件IO操作,但是文件IO操作不能使用多路复用API。但是Redis是单线程的,Redis得处理掉这个问题

fork(多进程)备份

1、Redis在持久化的时候会调用glibc的函数fork产生一个子进程,快照的持久化交给子进程来处理,父进程来处理客户端请求

2、子进程刚产生时和父进程共享内存里面的代码段和数据段,这是Linux操作系统的机制,为了节约内存资源所以让父子进程共享代码段和数据段。在进程分离的一瞬间,内存的增长几乎没有明显变化

pid = os.fork()
if pid > 0:
    handle_client_requests() #父进程继续处理客户端请求
if pid == 0:
    handle_snapshot_write() #子进程处理快照写磁盘
if pid < 0:
    #fork error

3、子进程做数据持久化,它不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘中。但是父进程不一样,它必须持续服务客户端请求,然后对内存数据结构进行不间断的修改

4、这个时候就会使用操作系统的COW机制来进行数据段页面的分离。数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据

5、随着父进程修改操作的持续进行,越来越多的共享页面被分离出来,内存就会持续增长。但是也不会超过原有数据内存的2倍大小。另外一点Redis实例里冷数据占的比例往往是比较高的,所以很少会出现所有的页面都会被分离,被分离的往往只有其中一部分页面。每个页面的大小只有4K,一个Redis实例里面一般都会有成千上万的页面。子进程因为数据没有变化,它能看到的内存里的数据在进程产生的一瞬间就凝固了,再也不会改变,这也是为什么Redis的持久化叫“快照”的原因。接下来子进程就可以非常安心的遍历数据了进行序列化写磁盘了

AOF原理

什么是AOF

AOF日志存储的是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录

AOF重放

1、假设AOF日志记录了自Redis实例创建以来所有的修改性指令序列,那么就可以通过对一个空的Redis实例顺序执行所有的指令,也就是“重放”,来恢复Redis当前实例的内存数据结构的状态

2、Redis会在收到客户端修改指令后,先进行参数校验,如果没问题,就立即将该指令文本存储到AOF日志中,也就是先存到磁盘,然后再执行指令。这样即使遇到突发宕机,已经存储到AOF日志的指令进行重放一下就可以恢复到宕机前的状态

3、Redis在长期运行的过程中,AOF的日志会越变越长。如果实例宕机重启,重放整个AOF日志会非常耗时,导致长时间Redis无法对外提供服务。所以需要对AOF日志瘦身。注意:AOF日志在Redis重启之后会被重放,重放期间Redis实例不对外提供服务

AOF重写

AOF日志瘦身

使用bgrewriteaof对AOF日志进行瘦身,开辟一个子进程对内存进行遍历转换成一系列的Redis操作指令,序列化到一个新的AOF日志文件中。序列化完毕之后再将操作期间发生的增量AOF日直追驾到这个新的AOF日志文件中,追加完毕之后就立即代替旧的AOF日志文件

fsync

1、AOF日志是以文件的形式存在的,当程序对AOF日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内存缓存中,然后内核会异步将脏数据刷回到磁盘的。这就意味着如果机器突然宕机,AOF日志内容可能还没有来得及完全刷到磁盘中,这个时候就会出现日志丢失

2、Linux的glibc提供了fsync(int fd)函数可以将指定文件的内容强制从内核缓存刷到磁盘。只要Redis进程实时调用fsync函数就可以保证aof日志不丢失。但是fsync是一个磁盘IO操作,它很慢!如果Redis执行一条指令就要fsync一次,那么Redis高性能的地位就不保了

3、所以在生产环境的服务器中,Redis通常是每隔1s左右执行一次fsync操作,周期1s是可以配置的。这是在数据安全性和性能之间做了一个折中,在保持高性能的同时,尽可能使得数据少丢失。Redis同样也提供了另外两种策略,一个是永不fsync——让操作系统来决定合适同步磁盘,很不安全,另一个是来一个指令就fsync 一次——非常慢。但是在生产环境基本不会使用,了解一下即可

Redis运维考虑

快照是通过开启子进程的方式进行的,它是一个比较耗资源的操作。

1、遍历整个内存,大块写磁盘会加重系统负载

2、AOF的fsync是一个耗时的IO操作,它会降低Redis性能,同时也会增加系统IO负担

3、通常Redis的主节点是不会进行持久化操作,持久化操作主要在从节点进行。从节点是备份节点,没有来自客户端请求的压力,它的操作系统资源往往比较充沛。但是如果出现网络分区,从节点长期连不上主节点,就会出现数据不一致的问题,特别是在网络分区出现的情况下又不小心主节点宕机了,那么数据就会丢失,所以在生产环境要做好实时监控工作,保证网络畅通或者能快速修复。另外还应该再增加一个从节点以降低网络分区的概率,只要有一个从节点数据同步正常,数据也就不会轻易丢失

Redis4.0混合持久化

1、重启Redis时,很少使用rdb来恢复内存状态,因为会丢失大量数据。通常使用AOF日志重放,但是重放AOF日志性能相对rdb来说要慢很多,这样在Redis实例很大的情况下,启动需要花费很长的时间

2、Redis4.0为了解决这个问题,带来了一个新的持久化选项——混合持久化。将rdb文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF日志,通常这部分AOF日志很小

3、于是在Redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此大幅得到提升

操作系统COW机制

https://www.xuebuyuan.com/944121.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值