一篇主要针对Redis的内存淘汰机制以及Redis容易引发的三大问题:缓存击穿、缓存穿透以及缓存雪崩进行了详细的讲解以及提供了业界常用的解决方案。本篇主要讲讲Redis的持久化机制,Redis受开发者欢迎的一大原因就是因为可持久化的特性。我们如何保证Redis宕机之后重启可以将数据进行恢复?所以一般情况下我们需要定时进行持久化将内存中的数据写入到硬盘中。而Redis中支持两种不同的持久化机制:RDB持久化以及AOF持久化。
快照持久化是一次全量备份,备份的是内存数据的二进制序列化格式。而AOF持久化是增量备份,记录的是内存数据修改的指令记录文本。所以AOF持久化生成的日志会随着运行时间变长而变得越来越臃肿,每次重启Redis都需要加载AOF日志进行指令重放,所以需要定期重写AOF日志进行瘦身操作。
快照持久化(RDB)
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,子进程负责将数据集写入临时文件由于os的写时复制机制父子进程会共享相同的物理界面,当父进程处理写请求时os会为父进程创建页面副本,所以紫禁城地址空间的数据实际上就是一个快照,写入成功后,再替换之前的文件,用二进制压缩存储。RDB是Redis默认的持久化方式,会在对应的目录下生产一个dump.rdb文件,重启会通过加载dump.rdb文件恢复数据。Redis使用操作系统的多进程COW机制实现RDB持久化。
优点:
- 只有一个备份文件dump.rdb,方便持久化备份;
- 容灾性好,一个文件可以保存到其他存储介质;
- 性能最大化,fork出子进程来完成写操作,让主进程继续处理命令,所以是IO最大化(使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能) ;
- 如果数据集偏大,RDB的启动效率会比AOF更高。
缺点:
- 数据安全性低。
- 如果当数据集较大时,可能会导致整个服务器停止服务。
RDB持久化是 Redis 默认采用的持久化方式,可以在 redis.conf 配置文件中进行配置Redis在N秒内如果超过M个key被修改就自动做快照:
- save 900 1:在15分钟内,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
- save 300 10:在5分钟内,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
- save 60 10000:在1分钟之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
AOF持久化
AOF持久化是以日志的形式记录每一个增删操作,会将所有增删操作通过write函数追加到文件中。AOF的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启会通过执行文件中保存的写命令在内存中重建整个数据库的内容。与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。 默认情况下 Redis 没有开启 AOF持久化,可以通过设置 appendonly 参数开启:
- appendonly yes
Redis通过fork出子进程,子进程根据内存中的快照,往临时文件中写入重建数据库状态的指令,父进程继续处理请求,当子进程将快照内容写入到临时文件中则发信号通知父进程将缓存中的写操作也写入到临时文件中,最后使用临时文件替代旧备份文件并进行重命名。AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof。在 Redis 的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:
- appendfsync always:每次有数据修改发生时都会写入AOF文件
- appendfsync everysec:每秒钟同步一次,将多个写命令同步到硬盘
- appendfsync no:让操作系统决定何时进行同步
用户可以使用appendfsync everysec选项 ,让 Redis 每秒同步一次 AOF 文件,这样Redis性能几乎不会受到影响,而且这样即使出现宕机,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis 还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。
优点:
- 数据安全性更高,AOF持久化可以配置appendfsync属性
- 通过append模式写文件,即使中途服务器宕机,可以通过redis-check-aof工具解决数据一致性问题。
- AOF机制的rewrite模式。
缺点:
- AOF文件比RDB文件大,且恢复速度慢;
- 数据集大的时候,比RDB启动效率低。
- 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。
对于Redis的两种持久化机制的选择,主要还是得针对特定的系统讨论,看是可以牺牲一定的性能使用AOF持久化换取缓存一致性,还是在增删操作频繁时关闭备份,等到Redis空闲手动save做RDB持久化备份。所以其实最佳方案应该是采用混合持久化方案,开启混合持久化后,AOF重写日志时会将RDB持久化的内容写到AOF文件开头,于是在Redis重启时,可以先加载RDB的内容,再对增量的AOF日志进行重放,提升Redis重启的效率。
原文连接:https://segmentfault.com/a/1190000020653415