Redis持久化详解

 【关闭文件、AOF 刷盘、释放内存这三个任务都有各自的任务队列】所以不是单线程

Redis有两种持久化方案:

  • RDB持久化

  • AOF持久化

  • 基于Redis集群解决单机Redis存在的问题

【Redis是单进程的】

【也有人做分布式section】

【主从集群中多个从就是做负载均衡的】

单机的Redis存在四大问题:

RDB持久化

【执行 bgsave 过程中,Redis 依然可以继续处理操作命令的,也就是数据是能被修改的,关键的技术就在于写时复制技术(Copy-On-Write, COW)。

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录。【全量拷贝】

1.执行时机

RDB持久化在四种情况下会执行:

  • 执行save命令

  • 执行bgsave命令

  • Redis停机时

  • 触发RDB条件时

1)save命令

执行下面的命令,可以立即执行一次RDB:

redis-cli中执行save

save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞。只有在数据迁移时可能用到。

2)bgsave命令

下面的命令可以异步执行RDB:

bgsave

这个命令执行后会开启独立进程完成RDB,主进程可以持续处理用户请求,不受影响。

3)停机时

Redis停机时会执行一次save命令,实现RDB持久化。

4)触发RDB条件

Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:

 # 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
 save 900 1  
 save 300 10  
 save 60 10000 

RDB的其它配置也可以在redis.conf文件中设置:

 # 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
 rdbcompression yes
 ​
 # RDB文件名称
 dbfilename dump.rdb  
 ​
 # 文件保存的路径目录
 dir ./ 

2.RDB原理

bgsave开始时会fork主进程得到子进程【此时主进程是阻塞的,所以要加快fork的速度】,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write(写时复制技术):内存大时还是很耗时,还需要大量磁盘IO,对性能影响大。

  • 当主进程执行读操作时,访问共享内存;

  • 当主进程执行写操作时,则会拷贝一份数据(数据副本),执行写操作。fork会把共享内存标记为read-only,以后主进程读操作时也往副本,页表变了。

【所有进程都没法操作物理内存,所以由操作系统给每个进程分配一个虚拟内存,操作系统还会维护虚拟内存和物理内存之间的映射关系表(页表),从而实现读写。fork的过程就是对页表做拷贝】

【redis一般预留空间,防止被副本翻倍消耗完】

3.小结

RDB方式bgsave的基本流程?

  • fork主进程得到一个子进程,共享内存空间

  • 子进程读取内存数据并写入新的RDB文件

  • 用新RDB文件替换旧的RDB文件

RDB会在什么时候执行?save 60 1000代表什么含义?

  • 默认是服务停止时

  • 代表60秒内至少执行1000次修改则触发RDB

  • 宕机数据会丢失

RDB的缺点?

  • RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险

  • fork子进程、压缩、写出RDB文件都比较耗时

AOF持久化

【大大提高数据的安全性,弥补RDB】

1.AOF原理

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。【不像RDB每次都从头开始写文件,累加】

【先写到Redis,再把命令写到AOF文件,将来恢复只需要重新执行命令】

2.AOF配置

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

 # 是否开启AOF功能,默认是no
 appendonly yes
 # AOF文件的名称
 appendfilename "appendonly.aof"

AOF的命令记录的频率也可以通过redis.conf文件来配:

 # 表示每执行一次写命令,立即记录到AOF文件,先操作内存再写到磁盘(性能最差)
 appendfsync always 
 # 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
 appendfsync everysec 
 # 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
 appendfsync no

三种刷盘策略对比:

3.AOF文件重写

【AOF执行rewrite的缓冲区。无法设置容量上限】

因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令(后台子进程 bgrewriteaof来完成),可以让AOF文件执行重写功能,用最少的命令达到相同效果。

【子进程带有主进程的数据副本,这里使用子进程而不是线程,防止共享数据更改(只读)(主进程修改了会发生「写时复制」,所以用副本保证数据安全)时使用锁降低性能】

【aof文件压缩后看不懂,此时再加命令会接着写,不过不会反压缩回来】

set num 123 和 set num 666都是对num的操作,第二次会覆盖第一次的值,因此第一个命令记录下来没有意义。【读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」】

所以重写命令后,AOF文件内容就是:mset name jack num 666

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

 # AOF文件比上次文件 增长超过多少百分比则触发重写
 auto-aof-rewrite-percentage 100
 # AOF文件体积最小多大以上才触发重写 
 auto-aof-rewrite-min-size 64mb 

RDB与AOF对比

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

【一般两者一起用】

【RDB相当于备份,异地容灾,机房毁了,aof也废了】

【aof写磁盘多,好在是异步的】

混合

前部分是rdb,当同步过程新来的就会进行aof降低数据丢失率。

  • 兼容性差,如果开启混合持久化,那么此混合持久化 AOF 文件,就不能用在 Redis 4.0 之前版本了。

混合持久化是在AOF持久化的基础上,定期进行RDB持久化。具体实现方式是在AOF重写时,将RDB文件以二进制压缩格式写入到AOF文件的开头,之后的数据再以AOF格式追加到文件的末尾。这样,在Redis重启时,可以优先加载RDB部分的数据,快速恢复大部分数据,然后再通过AOF部分的命令来更新内存中的数据,以保证数据的完整性。

总结

Redis的持久化虽然可以保证数据安全,但也会带来很多额外的开销,因此持久化请遵循下列建议:

  • 用来做缓存的Redis实例尽量不要开启持久化功能【提高查询效率的不需要持久化,查询时再写一遍就好。对于安全性要求高的,比如分布式锁、库存、验订单的流水需要持久化(可以专门放在一个redis实例)】

  • 建议关闭RDB持久化功能,使用AOF持久化【可以混合。rdb会丢失数据】

  • 利用脚本定期在slave节点做RDB,实现数据备份

  • 设置合理的rewrite阈值,避免频繁的bgrewrite

  • 配置no-appendfsync-on-rewrite = yes,禁止在rewrite期间做aof,避免因AOF引起的阻塞【主从同步时还是要fork(大量磁盘IO),rewrite也有磁盘IO且时间长,aof刷盘也需要读写磁盘。rewrite占用磁盘高会影响aof刷盘】fsync刷盘

  • 部署有关建议:

    • Redis实例的物理机要预留足够内存,应对fork和rewrite【fork可能翻倍,写时复制】

    • 单个Redis实例内存上限不要太大,例如4G或8G。可以加快fork的速度、减少主从同步、数据迁移压力

    • 不要与CPU密集型应用部署在一起【fork等CPU要求高。es也高】

    • 不要与高硬盘负载应用一起部署。例如:数据库、消息队列


  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值