Redis的持久化机制

  1. 云栖社区>
  2. 博客>
  3. 正文

Redis的持久化机制

徐胖子 2016-12-22 19:15:00 浏览1156
展开阅读全文

1 持久化


redis需要经常将内存中的数据同步到磁盘来保证持久化。 支持两种持久化方式:快照Append-onlyfile。


2 快照


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


#900秒内若超过1个key被修改,则发起快照保存
save 900 1

#300秒内若超过10个key被修改,则发起快照保存
save 300 10

#60秒内若超过1W个key被修改,则发起快照保存
save 60 10000

 

快照保存过程

1 redis调用fork,现在有了子进程和父进程。

2 父进程继续处理client请求,子进程负责将内存内容写入临时文件。由于os的实时复制机制(copyOnWrite)父子进程会共享相同的物理页面,当父进程处理写请求时,操作系统会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程地址空间内的数据是fork时刻整个数据库的一个快照。

3 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。


client也可使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有client的请求,这种方式会阻塞所有client请求。所以不推荐使用。

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


3 AOF


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


aof比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过 write 函数追加到文件中,默认是appendonly.aof文件。当redis重启时,会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于os会在内核中缓存write 做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。不过可通过配置文件告诉 redis通过fsync函数,强制OS写入到磁盘的时机。有三种方式如下


#启用aof持久化方式
appendonly yes

#每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中(默认)
appendfsync everysec

#收到写命令就立即写入磁盘,最慢,但是保证完全的持久化
#appendfsync always

#完全依赖os,性能最好,持久化没保证
#appendfsync no 


aof方式也同时带来了另一个问题。持久化文件会变的越来越大。例如调用incr test命令100次,文件中必须保存全部的 100 条命令,99条都是多余的,因为要恢复数据库的状态其实文件中保存一条 set test 100 就够了。为了压缩aof持久化文件,redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。具体过程如下

1 redis调用fork,现在有父子两个进程

2 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令

3 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。就能保证若子进程重写失败的话并不会出问题。

4 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件

5 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加

 

需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

 

原贴地址:http://weibo.com/cdhongwan


网友评论

登录后评论
0/500
评论
徐胖子
+ 关注