Redis如何实现持久化

2017-12-12 23:32:52 来源: devezhang 0

阅读文本大概需要 3.3 分钟。

redis持久性方案及其原理细节介绍,深入理解redis。

1. 

redis持久性分为两种:RDB(Redis datebase)和AOF(append only file),同时,RDB和AOF可同时使用,但BGSAVE和BGWRITEAOF不会同时执行,在redis服务器启动用于恢复数据时将会优先使用AOF。

持久的功能是用于恢复,但持久本身不能取代备份,还应该制定备份策略,对redis进行数据库备份,保证数据的完整性。

2. 

RDB:此方式基于快照实现,该持久化方式是在redis内部有一个定时器,每隔固定时间去检查当前数据发生改变的次数与时间是否满足配置的持久性触发的条件,如果满足则通过操作系统启动一个fork函数调用来创建出一个字进程,这个子进程默认会与父进程共享相同的地址空间,这时就可以通过子进程来遍历整个内存来进行存储操作,而主进程则仍然可以提供服务,当有写入时由操作系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。

该持久化的主要缺点是定时快照只是代表一段时间内的内存映像,所以系统重启会丢失上次快照与重启之间所有的数据。

编辑/etc/redis.conf可查看相应的配置参数及其意义。

3. 

AOF:redis主进程通过fork创建子进程,子进程根据redis内存中的数据库重构后将此存储于临时文件中,父进程继承客服端的请求,并会把这些请求中的操作继续追加至原来的AOF文件,额外的这些新的写请求还会被放置于一个缓冲队列中,父进程把缓冲中的命令写到临时文件中,子进程重写完成会通知父进程,父进程用临时文件替换原来的AOF老文件。

AOF方式实际类似mysql的基于语句的binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中,也就是说这个log文件就是Redis的持久化数据。

AOF的方式的主要缺点是追加log文件可能导致体积过大,当系统重启恢复数据时如果是aof的方式则加载数据会非常慢,几十G的数据可能需要几小 时才能加载完,当然这个耗时并不是因为磁盘文件读取速度慢,而是由于读取的所有命令都要在内存中执行一遍。

另外由于每条命令都要写log,所以使用aof 的方式,Redis的读写性能也会有所下降。

AOF对日志文件的写入操作时采用追加的模式进行,因此写入的过程中如果发生断电,机器宕机等情况发生,也不会对已存在数据文件造成破坏。

4. 

Redis持久化磁盘IO方式及其带来的问题

有Redis线上运维经验的人发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持久化的fork系统调用造成内存占用加倍而导致的。

这种观点是不准确的,因为fork用的copy-on-write机制是基于操作系统页这个单位的,也就是只有有写入的脏页会被复制,但是一般你的系统不会在短时间内所有的页都发生了写入而导致复制,那么是什么原因导致Redis崩溃的呢?

其实根本原因是Redis的持久化使用了Buffer IO造成的,所谓Buffer IO是指Redis对持久化文件的写入和读取操作都会使用物理内存的Page Cache,而大多数数据库系统会使用Direct IO来绕过这层Page Cache并自行维护一个数据的Cache。

但是当Redis的持久化文件过大(尤其是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内存中作为操作系统对该文件的一层Cache,而这层Cache的数据与Redis内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会做 Page Cache的剔除工作,但内核很可能认为某块Page Cache更重要,而让你的进程开始Swap ,这时你的系统就会开始出现不稳定或者崩溃了。通常的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了。

已收藏取消收藏 收藏
登录发表你的评论
0条评论
author_pic devezhang
签名:一名不羁的码农,我的世界不只有 Coding!记录编程、认知、思想!
总篇数20
粉丝3
关注

文章热度排行

用户名
用户名不能为空
密码(不少于6位)
密码不能为空

注 册

用户名
用户名不能为空
图形验证码
图形码不能为空
手机验证码
无须填写,可跳过此步
验证码不能为空
密码(不少于6位)
密码不能为空

同意使用条款,并已阅读"跟帖评论自律管理承诺书"

请勾选