深入理解redis持久化
持久化方式:
快照(RDB)方式,默认方式,文件以二进制方式保存到RDB文件。
文件追加(AOF)方式,文件以协议文本的方式write到AOF文件。
作用,重启后的数据恢复。当两种方式都启用时,redis会优先载入AOF文件,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
注意优先是指载入AOF文件就不再加载RDB了,不管AOF是不是空文件。
RDB配置:
################################ SNAPSHOTTING #################################
# Save the DB on disk:
# 设置sedis进行数据库镜像的频率。
# 900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)。
# 300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)。
# 60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)。
save
save
save stop-writes-on-bgsave-error yes
# 在进行镜像备份时,是否进行压缩。yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间。
rdbcompression yes
# 一个CRC64的校验就被放在了文件末尾,当存储或者加载rbd文件的时候会有一个10%左右的性能下降,为了达到性能的最大化,你可以关掉这个配置项。
rdbchecksum yes
# 快照的文件名
dbfilename dump.rdb
# 存放快照的目录
dir ./
RDB原理:
fork一个子进程,在子进程中循环所有的数据,将数据写到一个临时文件,通过原子性的rename系统调用重命名为dump.rdb。
写操作在一个新的进程中完成,所以rdb文件不会损坏。
在子进程写操作执行的过程中父进程接受到新命令不会同步给子进程。需要等到下一次的写入才能把新命令写入到RDB文件中。
RDB文件对主从同步的作用:
第一次Slave向Master同步的实现是:
Slave向Master发出同步请求,Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的命令转发给Slave,初次同步完成。
第二次以及以后的同步实现是:
Master将变量的快照直接实时依次发送给各个Slave。但不管什么原因导致Slave和Master断开重连都会重复以上两个步骤的过程。
Redis的主从复制是建立在内存快照的持久化基础上的,只要有Slave就一定会有内存快照发生。
RDB持久化之Redis关闭时的数据保存(总结自参考的第三篇文章,可以看原文,结合代码的):
正常关闭redis,在关闭前会执行save命令,所以在关闭前还未达到持久化条件时的数据也会被持久化了。对于kill也属于正常关闭,只有kill -9 属于异常关闭。
RDB持久化在满足save条件,手动save,正常关闭时数据都会被持久化,只有异常关闭才会造成数据丢失。
注意当RDB持久化关闭后,手动save依然可以持久化数据,只是不能触发自动save,并且正常关闭也不触发save,所以不能说是禁止snapshot,是禁止自动snapshot。
AOF配置:
############################## APPEND ONLY MODE ###############################
# 是否开启AOF,默认关闭(no)
appendonly yes
# 指定 AOF 文件名
appendfilename appendonly.aof
# Redis支持三种不同的刷写模式:
# appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。
# appendfsync no #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。 #在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes
no-appendfsync-on-rewrite yes
#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
auto-aof-rewrite-percentage
#当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。
auto-aof-rewrite-min-size 64mb
在使用AOF持久化方式时,Redis会将每一个收到的写命令都通过Write函数追加到文件中
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写,这些写入操作以 Redis 协议的格式保存。
如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
压缩aof的持久化文件:bgrewriteaof
收到此命令后Redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,
最后替换原来的文件,以此来实现控制AOF文件的增长。
由于是模拟快照的过程,因此在重写AOF文件时并没有读取旧的AOF文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的AOF文件。
总结:aof方式是一直追加文件,设置的fsync的时间是追加的时间,期间新命令一直在内存缓冲区中,触发了fsync条件才执行追加。而bgrewriteaof命令是重写aof文件,只有调用了bgrewriteaof的时候才会产生fork。
AOF重写原理:
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:
- Redis 执行 fork() ,现在同时拥有父进程和子进程。
- 子进程开始将新 AOF 文件的内容写入到临时文件。
- 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
- 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
- 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
- 注意:在将内存缓存中的数据追加到新AOF文件末尾和rename时,主进程是阻塞的。
AOF文件损坏修复:
服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:
- 为现有的 AOF 文件创建一个备份。
使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复:
$ redis-check-aof –fix
- (可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
- 重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。
RDB数据恢复的优势:
RDB的启动时间会更短,因为RDB文件非常紧凑,RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。
RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作,所以在CPU消耗上要远小于AOF日志的加载。
RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作(AOF方式在子进程重写文件的时候,父进程仍然需要向现有的AOF文件追加,并且同时还得把命令写入重写缓冲区),所以RDB持久化方式可以最大化redis的性能.
fork会使内存增大2倍:
在进行快照的时候(save),fork出来进行dump操作的子进程会占用与父进程一样的内存,真正的copy-on-write,对性能的影响和内存的耗用都是比较大的。比如机器8G内存,Redis已经使用了6G内存,这时save的话会再生成6G,变成12G,大于系统的8G。这时候会发生交换;要是虚拟内存不够则会崩溃,导致数据丢失。
通常的设计思路是利用Replication机制来弥补aof、snapshot性能上的不足,达到了数据可持久化。即Master上Snapshot和AOF都不做,来保证Master的读写性能,而Slave上则同时开启Snapshot和AOF来进行持久化,保证数据的安全性。
上边的说法有待确认:
fork后,父子进程共享相同的内存,直到父进程或者子进程对内存进行了写入之后,对被写内存的共享才会结束,所以fork时内存不是增大两倍,而是不变,只有父进程中收到修改命令的内存才会结束共享。
RDB到AOF的切换(在参考的第三篇文章中的代码示例中讲了两种切换的方法,必须看):
在 Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :
为最新的 dump.rdb 文件创建一个备份。
将备份放到一个安全的地方。
执行以下两条命令:
redis-cli config set appendonly yes
redis-cli config set save “”
确保写命令会被正确地追加到 AOF 文件的末尾。
执行的第一条命令开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。
执行的第二条命令用于关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能。 重要:别忘了在 redis.conf 中打开 AOF 功能! 否则的话, 服务器重启之后, 之前通过 CONFIG SET 设置的配置就会被遗忘, 程序会按原来的配置来启动服务器。
参考:
redis中文网对持久化介绍:http://www.redis.cn/topics/persistence.html
redis设计与实现中讲解AOF一章: http://redisbook.readthedocs.org/en/latest/internal/aof.html
一篇对持久化的实践的文章,包含测试代码,代码中的问题很有意义:http://www.chawenti.com/articles/14593.html
深入理解redis持久化的更多相关文章
- 一篇文章彻底理解Redis持久化:RDB和AOF
为什么需要持久化? Redis对数据的操作都是基于内存的,当遇到了进程退出.服务器宕机等意外情况,如果没有持久化机制,那么Redis中的数据将会丢失无法恢复.有了持久化机制,Redis在下次重启时可以 ...
- 5分钟彻底理解Redis持久化
Redis持久化 RDB快照 在默认情况下,Redis将内存数据库快照保存到dump.rdb的二进制文件中. 可以对Redis进行设置,让它在"N秒内数据集至少有N个改动", 这一 ...
- 10分钟彻底理解Redis持久化和主从复制
在这篇文章,我们一起了解 Redis 使用中非常重要的两个机制:Reids 持久化和主从复制. 什么是 Redis 持久化? Redis 作为一个键值对内存数据库(NoSQL),数据都存储在内存当中, ...
- 读完这篇,让你真正理解Redis持久化
什么叫持久化? 用一句话可以将持久化概括为:将数据(如内存中的对象)保存到可永久保存的存储设备中. 持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中. XML 数据文件中等等. 也 ...
- 理解Redis持久化
本文首发于:https://mp.weixin.qq.com/s/WVUGWuNrGoyY_7aDf7NNmA 微信公众号:后端技术指南针 0.前言 通俗讲持久化就是将内存中的数据写入非易失介质中,比 ...
- 源码级别理解 Redis 持久化机制
文章首发于公众号"蘑菇睡不着",欢迎来访~ 前言 大家都知道 Redis 是一个内存数据库,数据都存储在内存中,这也是 Redis 非常快的原因之一.虽然速度提上来了,但是如果数据 ...
- 【redis持久化】redis持久化理解
1.以下内容仅为个人理解和总结,仅供参考,万万不可全盘真信,内容会进行实时改进和修正 2.redis持久化: 参考链接1.https://redis.io/topics/persistence -- ...
- 深入理解Redis的持久化机制和原理
Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能.持久存储.适应高并发应用场景等优势.它虽然起步较晚,但发展却十分迅速. 近日,Redis的作者在博客中写到, ...
- 【大厂面试06期】谈一谈你对Redis持久化的理解?
Redis持久化是面试中经常会问到的问题,这里主要通过对以下几个问题进行分析,帮助大家了解Redis持久化的实现原理. 1.Redis持久化是什么? 2.Redis持久化有哪些策略?各自的实现原理是怎 ...
随机推荐
- Loadrunner代理录制设置
使用LR代理录制原理 启用LR代理服务器监听设置好的端口号是否有请求信息发送给服务器,有请求时,代理服务器接收带请求,并转发给对应的系统服务器,LR从而获取到请求的信息与数据,生成脚本. 使用代理的前 ...
- java实现批量下载百度图片搜索到的图片
就是写的个小程序,用于记录一下,方便后续查看,首先感谢下面这个博客,从这篇文章衍生的吧,大家可以学习下: http://www.cnblogs.com/lichenwei/p/4610298.html ...
- 如何安装虚拟机VMware
虚拟机可以帮我们在一台电脑上面来模拟出多台电脑,而且可以装不同的系统.下面就教大家怎么装VMware虚拟机 1.下载Vmware安装包,建议下载VMware10 这个有中文版的,其他版本的都是英文的哦 ...
- 【Windows编程】系列第八篇:通用对话框
上一篇我们学习了菜单的基本编程,本篇来了解一下通用对话框的使用.Windows系统之所以是目前最流行的桌面系统,也是因为Windows有一套标准化,统一友好的交互界面,比如菜单.工具栏.状态栏以及各个 ...
- 数据处理之PostgreSQL过程语言学习
前段时间,公司更换新的PostgreSQL数据集市的系统过程中,自己下载了postgresqlAPI的pdf文件研究了一下PostgreSQL数据集市.发现使用PostgreSQL过程语言可以大大加快 ...
- Android(Linux)线路规程的使用
一般来说,车载导航主机都需要外接若干个UART的外设,如支持HFP的蓝牙模块.与原车通信的CAN解码盒模块.u-blox的GPS模块和DVD机芯等.早年使用Telechips TCC8902+ ...
- jdbc java数据库连接 2)jdbc接口核心的API
JDBC接口核心的API java.sql.* 和 javax.sql.*(java2.0以后更新的扩展) |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接 ...
- B树、B-树、B+树、B*树
B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right) 2.所有结点存储一个关键字 3.非叶子节点的左指针指向小于其关键字的字数,右指针指向大于其关键字的字数: 如: B树的 ...
- Spring源码分析——BeanFactory体系之抽象类、类分析(二)
上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...
- jS字符串大小写转换实现方式
toLocaleUpperCase 方法:将字符转换为大写 stringVar.tolocaleUpperCase( ) 必选的 stringVar 引用是一个 String 对象,值或文字. //转 ...