彻底了解Redis持久化
本文转自杨奇龙老师的公众号(yangyidba),他长期关注于数据库技术以及性能优化,故障案例分析,数据库运维技术知识分享,个人成长和自我管理等主题
前言
大家都知道Redis一个内存数据库,它支持2种持久化方式:RDB(Snapshot 内存快照),AOF(append only file)。持久化功能将内存中的数据同步到磁盘来避免Redis发生异常导致数据丢失的情况。当Redis实例重启时,就可利用之前持久化的文件实现数据恢复。
接下来,本文详情两种持久化的运行机制和优缺点。
一 RDB
RDB是默认的持久化方式,按照肯定的策略周期性的将内存中的数据生成快照保存到磁盘。
每次快照持久化都是将内存数据完整写入到磁盘一次,并不 是增量的只同步脏数据。假如数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。
1.1 快照持久化过程
image
1.2 触发机制
1. save 命令
当用户端向Redis server发送save命令请求进行持久化时,因为Redis是用一个主线程来解决所有,save命令会阻塞Redis server解决其余用户端的请求,直到数据同步完成。
2. bgsave命令
与save命令不同,bgsave是异步执行的,当执行bgsave命令之后,Redis主进程会fork 一个子进程将数据保存到rdb文件中,同步完数据之后,对原有文件进行替换,而后通知主进程表示同步完成。
3. 自动触发
除了手动触发RDB持久化,Redis内部还存在自动触发机制,
在配置中集中配置
save m n的方式,表示 m秒内数据集存在n次修改时,系统自动触发bgsave 操作。
# 900s内至少达到一条写命令save 900 1# 300s内至少达至10条写命令save 300 10# 60s内至少达到10000条写命令save 60 10000从节点执行全量复制操作,主节点自动执行bgsave 生成RDB文件并发送给从节点
默认情况下执行 shutdown 命令时,假如没有开启AOF持久化功能,系统会自动执行bgsave命令。执行debug reload 命令重新加载Redis时,也会自动触发save操作。
1.3 相关参数
# 持久化 rdb文件遇到问题时,主进程能否接受写入,yes 表示中止写入,假如是no 表示redis继续提供服务。stop-writes-on-bgsave-error yes # 在进行快照镜像时,能否进行压缩。yes:压缩,但是需要少量cpu的消耗。no:不压缩,需要更多的磁盘空间。rdbcompression yes# 一个CRC64的校验就被放在了文件末尾,当存储或者者加载rbd文件的时候会有一个10%左右的性能下降,为了达到性能的最大化,你可以关掉这个配置项。rdbchecksum yes# 快照的文件名dbfilename dump.rdb# 存放快照的目录dir /var/lib/redis1.4 RDB的优缺点
优点
RDB文件小,非常适合定时备份,用于灾难恢复。
由于RDB文件中直接存储的是内存数据,而AOF文件中存储的是一条条命令,需要应用命令。Redis加载RDB文件的速度比AOF快很多。
缺点
RDB持久化方式不能做到实时/秒级持久化。实时持久化要全量刷内存到磁盘,成本太高。每秒fork子进程也会阻塞主进程,影响性能。
RDB文件是二进制文件,随着Redis不断迭代有多个rdb文件的版本,不支持跨版本兼容。老的Redis无法识别新的RDB文件格式。
二 AOF
AOF(Append-only file)针对RDB的缺点做了优化,在使用AOF持久化方式时,Redis会将每一个收到的写操作命令都通过Write函数追加到文件最后,相似于MySQL的binlog。当Redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
2.1 AOF持久化过程
image
1. 用户端发出 bgrewriteaof命令。
2. redis主进程fork子进程。
3. 父进程继续解决client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存到 AOF重写缓冲区。这样就能保证假如子进程重写失败的话并不会出问题。
4. 子进程根据内存快照,按照命令合并规则写入到新AOF文件中。
5. 当子进程把内存快照写入临时文件中后,子进程发信号通知父进程。而后父进程把缓存的写命令也写入到临时文件。
6. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
2.2 相关参数
# 能否开启AOF,默认关闭appendonly yes# 指定 AOF 文件名appendfilename appendonly.aof# Redis支持三种刷写模式:# appendfsync always #每次收到写命令就立即强制写入磁盘,相似MySQL的sync_binlog=1,是最安全的。但该模式下速度也是最慢的,一般不推荐使用。appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做平衡,推荐该方式。# appendfsync no #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不推荐。 #在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yesno-appendfsync-on-rewrite yes#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。auto-aof-rewrite-percentage 100#当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时因为文件尺寸较小导致频繁的重写。auto-aof-rewrite-min-size 64mb2.3 日志重写
AOF机制将用户端的每一个写操作都追加到aof文件末尾,比方将一个key屡次执行incr,set命令,会写入屡次命令到aof文件,aof文件会越来越大,部分核心业务每天的写入量有几十G的大小。
incr k1 1set k2 aset k2 bincr k1 2incr k1 3set k2 cdel k3...incr k1 100恢复Redis实例时,加载非常大的aof文件耗时会很长。为理解决这个问题,Redis 支持aof文件重写–把Redis进程内的数据转化为写命令同步到新AOF文件中的过程。通过重写,可以生成一个最小的命令集合。比方上面的几个命令可以合并为
incr k1 100set k2 c写入数据的规则
1. 进程内过期的数据不用在写入
2. 旧AOF文件含有的无效命令 del k1, set a 1, set a 2。重写使用进程内的数据直接生成,aof文件就保留最新的命令集合。
3. 多条命令可以合并为一个命令,为了防止单个命令过大造成用户端缓冲区溢出,对于list,set,hash,zset 等类型的操作,以64个元素为界拆分为多条。
触发机制
image
1. 手动触发 执行bgrewriteaof命令。
2. 根据配置自动触发
auto-aof-rewrite-min-size 表示运行AOF重写是文件最小的大小。默认64M,小于64M就会不自动重写了。
auto-aof-rewrite-percentage 表示(aof_current_size– aof_base_size) / aof_base_size 的比值。
aof文件重写之后当前文件大小增长多少就触发重写
自动触发时机 :
aof_current_size`\>`auto-aof-rewrite-min-size` && (`aof_current_size` - `aof_base_size`) / `aof_base_size` >= `auto-aof-rewrite-percentage三 RDB VS AOF 比照
具体使用哪种持久化方式 ,下面是来自官方的建议:
通常,假如你要想提供很高的数据保障性,那么建议你同时使用两种持久化方式。假如你可以接受灾难带来的几分钟的数据丢失,那么你可以仅使用RDB。很多客户仅使用了AOF,但是我们建议,既然RDB可以时不时的给数据做个完整的快照,并且提供更快的重启,所以最好还是也使用RDB。
生产上的实例大多不会是单点,而是主从,也有利用slave作为持久化方式,同时满足HA的需求。读者朋友可以分享一下各自遇到的和 redis 持久化相关的问题。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 彻底了解Redis持久化