您的位置:首页 > 数据库 > Redis

Redis如何实现持久化

2016-10-11 13:52 323 查看
Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到硬盘中来保证持久化。

 

Redis支持两种持久化方式.

1. snapshotting(快照)

也是默认方式.(把数据做一个备份,将数据存储到文件)

快照是默认的持久化方式,这种方式是将内存中数据以快照的方式写到二进制文件中,默认的文件名称为dump.rdb.可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key键修改就自动做快照.

 

数据快照的原理是将整个Redis内存中的所有的数据遍历一遍存储到一个扩展名为rdb的数据文件中,通过save命令

可以调用这个过程。数据快照配置如下:

Save 900 1

Save 300 10

Save 60 10000

以上在redis.conf中的配置指出在多长时间内,有多少次更新操作,就将数据同步到数据文件中,这个可以多个条件进行配合,上面的含义是900秒后有一个key发生改变就执行save,300秒后有10个key发生改变就执行save,60秒有10000个key发生改变就执行save.

 2. Append-onlyfile(缩写aof)的方式        

aof方式:由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。aof比快照方式有更好的持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。      

当然由于os会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机。

Appendfsync no/always/everysec

no:表示等操作系统进行数据缓存同步到磁盘。性能最好,持久化没有保障。

Always:表示每次更新操作后手动调用fsync()将数据写到磁盘.每次收到写命令就立即强制写入磁盘,最慢的,但是保障完全的持久化。

Everysec:表示每秒同步一次.每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中。

 

Snapshot的问题

Redis有两种存储方式,默认是snapshot方式,实现方法是定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久化之后如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。

AOF的问题

aof即append only mode,在写入内存数据的同时将操作命令保存到日志文件,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建时间会非常长,这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型,所有的优势都是建立在对内存复杂数据结构高效的原子操作上,这样就看出aof是一个非常不协调的部分。其实aof目的主要是数据可靠性及高可用性.

bgRewriteAOF功能

为了定时减小AOF文件的大小,Redis2.4以后增加了自动的bgrewriteaof的功能,Redis会选择一个自认为负载低的情况下执行bgrewriteaof,这个重写AOF文件的过程是很影响性能的。解决方案:Master关闭Save功能,关闭AOF日志功能,以求达到性能最佳。Slave开启Save并开启AOF日志功能,并开启bgrewriteaof功能,不对外提供服务,这样Slave的负载总体上会高于Master负载,但是Master性能达到最好。而且基本上不会出现数据丢失的情况。

 

可以利用Redis的主从复制功能来实现性能和持久化的双赢局面。

 

在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。

接下来根据配置分为2种情况:

1.      Master使用快照功能实现持久化

Slave向Master发出同步请求,Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的命令转发给Slave,初次同步完成。第二次以及以后的同步实现是:Master将变量的快照直接实时依次发送给各个Slave。不管什么原因导致Slave和Master断开重连都会重复以上过程。Redis的主从复制是建立在内存快照的持久化基础上,只要有Slave就一定会有内存快照发生。

2.      Master关闭Save功能,关闭AOF日志功能,以求达到性能最佳。Slave开启Save并开启AOF日志功能,并开启bgrewriteaof功能,不对外提供服务

 

Bgrewriterof内部实现:

1.Redis通过fork一个子进程,遍历数据,写入新临时文件

2.父进程继续处理client请求,子进程继续写临时文件。

3.父进程把新写入的AOF写在缓冲区。

4.子进程写完退出,父进程接收退出消息,将缓冲区AOF写入临时文件。

5.临时文件重命名成appendonly.aof,原来文件被覆盖,整个过程完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: