redis的持久化方式:RDB和AOF




   数据持久化通俗讲就是把数据保存到磁盘上,保证不会因为断电等因素丢失数据。

   

       Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。有字符串,链表,集 合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务 器。

      Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。


      redis支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是Append-only file(缩写aof)的方式。

 


1.Snapshotting(RDB)


    默认redis是会以快照的形式将数据持久化到磁盘的(一个二进 制文件,dump.rdb,这个文件名字可以指定),在配置文件中的格式是:save N M表示在N秒之内,redis至少发生M次修改则redis抓快照到磁盘。当然我们也可以手动执行save或者bgsave(异步)做快照。


    下面是默认的快照保存配置

save 900 1  #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000


工作原理:

1.当redis需要做持久化时,redis会fork一个子进程


2. 父进程继续处理client请求,子进程负责将内存内容写入到临时RDB文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间(地址空间(address space)表示任何一个计算机实体所占用的内存大小)内的数 据是fork时刻整个数据库的一个快照。


3.当子进程完成写临时文件后,将原来的RDB替换掉,这样的好处就是可以copy-on-writeCopy-on-write 写时复制      在对数据进行修改的时候,不会直接在原来的数据位置上进行操作,而是重新找个位置修改,这样的好处是一旦系统突然断电,重启之后不需要做Fsck.


      client 也可以使用save或者bgsave命令通知redis做一次快照持久化。

      save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有 client的请求,这种方式会阻塞所有client请求。所以不推荐使用。

     

      另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不 是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。


     另外由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。如果应用要求不能丢失任何修改的话,可以采用aof持久化方式。




2.Append-only file(AOF)


     AOF定义:以日志的形式记录每个操作,将Redis执行过的所有指令全部记录下来(读操作不记录),只许追加文件但不可以修改文件,Redis启动时会读取AOF配置文件重构数据。

换句话说,就是Redis重启就会根据日志内容从头到尾执行一次来完成数据的恢复工作。


      AOF比快照方式有更好的持久化性,是由于在使用AOF持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。

     

     当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。

    不过我们可以通过配置文件告诉redis我们想要 通过fsync函数强制os写入到磁盘的时机。


 有三种方式如下(默认是:每秒fsync一次)

appendonly yes              //启用aof持久化方式
# appendfsync always      //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec     //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
# appendfsync no    //完全依赖os,性能最好,持久化没保证



Tip:


  一.RDB与AOF同时开启  默认先加载AOF的配置文件


  二.相同数据集,AOF文件要远大于RDB文件,恢复速度慢于RDB


  三.AOF运行效率慢于RDB,但是同步策略效率好,不同步效率和RDB相同

1.表示是否开启AOF持久化:


  appendonly yes(默认no,关闭) 


2.AOF持久化配置文件的名称:


  appendfilename "appendonly.aof"


3.AOF持久化策略(默认每秒):


  appendfsync always (同步持久化,每次发生数据变更会被立即记录到磁盘,性能差但数据完整性比较好)


  appendfsync everysec (异步操作,每秒记录,如果一秒钟内宕机,有数据丢失)


  appendfsync no  (不同步)


4.AOF配置文件损坏修复方法:


  进入redis安装路径 执行 redis-check-aof --fix AOF配置文件名称


5.AOF的Rewrite(重写) :


  定义:AOF采用文件追加的方式持久化数据,所以文件会越来越大,为了避免这种情况发生,增加了重写机制

当AOF文件的大小超过了配置所设置的阙值时,Redis就会启动AOF文件压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof


原理:当AOF增长过大时,会fork出一条新的进程将文件重写(也是先写临时文件最后rename),遍历新进程的内存数据,每条记录有一条set语句。


重写AOF文件并没有操作旧的AOF文件,而是将整个内存中的数据内容用命令的方式重写了一个新的aof文件(有点类似快照)


触发机制:Redis会记录上次重写时的AOF文件大小,默认配置时当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发


  auto-aof-rewrite-percentage 100  (一倍)

   auto-aof-rewrite-min-size 64mb

6.RDB与AOF的选择:

做备份:当数据量大,且对恢复速度有要求,并且数据的一致性要求不高的话,可以只使用RDB

只做缓存:不用开启任何的持久化方式


两者都开启的建议:RDB数据不实时,同时使用两者时服务器只会找AOF文件,可不可以只使用AOF?作者建议不要,因为RDB更适合备份数据库(AOF在不断变化,不好备份)

快速重启,而且不会又AOF可能潜在的BUG,留作万一的手段。






运维上的想法

其实快照和aof一样,都使用了Copy-on-write技术。多次试验发现每次做数据dump的时候,内存都会扩大一倍,这个时候会有三种情况:

一:物理内存足以满足,这个时候dump非常快,性能最好

二:物理内存+虚拟内存可以满足,这个时候dump速度会比较慢,磁盘swap繁忙,服务性能也会下降。所幸的是经过一段比较长的时候数据dump完成了,然后内存恢复正常。这个情况系统稳定性差。

三: 物理内存+虚拟内存不能满足,这个时候dump一直死着,时间久了机器挂掉。这个情况就是灾难!


如果数据要做持久化又想保证稳定性,建议留空一半的物理内存。如果觉得无法接受还是有办法,下面讲:

     快照和aof虽然都使用Copy-on-write,但有个不同点,快照你无法预测redis什么时候做dump,aof可以通过bgrewriteaof命令控制dump的时机。

根据这点我可以在一个服务器上开启多个redis节点(利用多CPU),使用aof的持久化方式。


      例 如在24G内存的服务器上开启3个节点,每天用bgrewriteaof定期重新整理数据,每个节点dump的时间都不一样,这 样理论上每个节点可以消耗6G内存,一共使用18G内存,另外6G内存在单个节点dump时用到,内存一下多利用了6G! 当然节点开的越多内存的利用率也越高。如果带宽不是问题,节点数建议 = CPU数。

本文转自写个博客骗钱博客51CTO博客,原文链接http://blog.51cto.com/dadonggg/1955928如需转载请自行联系原作者


菜鸟东哥

上一篇:java多线程下载和断点续传


下一篇:自动化运维工具 puppet安装部署