6.Redis持久化--主从同步

来源:互联网 发布:linux 查看启动的服务 编辑:程序博客网 时间:2024/06/06 04:31
6.Redis持久化--主从同步

持久化

redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化。
redis常用的两种持久化方式,一是Snapshotting(快照)也是默认方式;二是Append-only file(缩写aof)的方式。

(一)Snapshotting
快照是默认的持久化方式。
这种方式就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
可以通过配置设置自动做快照持久化的方式。
我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置:
save 900 1  #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000

快照保存过程:
1.redis调用fork,现在有了子进程和父进程。
2.父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,
  当父进程处理写请求时os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是fork时刻整个数据库的一个快照。
3. 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。

client也可以使用save或者bgsave命令通知redis做一次快照持久化。
save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有client的请求,这种方式会阻塞所有client请求。所以不推荐使用。
另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。
如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。


另外由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。

(二)Append-only file(AOF)
aof比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是appendonly.aof)。
当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
当然由于os会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。
不过我们可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机。
有三种方式如下(默认是:每秒fsync一次):
appendonly yes         #启用aof持久化方式
# appendfsync always   #每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec   #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
# appendfsync no       #完全依赖os,性能最好,持久化没保证

aof 的方式也同时带来了另一个问题,持久化文件会变的越来越大。
例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。
因为要恢复数据库的状态其实文件中保存一条set test 100就够了。
为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。

Redis AOF流程:
1.Redis Server启动,如果AOF机制打开那么初始化AOF状态,并且如果存在AOF文件,读取AOF文件。
2.随着Redis不断接收命令,每个写命令都被添加到AOF文件,AOF文件膨胀到需要rewrite时又或者接收到客户端的bgrewriteaof命令。
[可以配置当aof文件增加多少倍或者达到最小大小时进行整理。]
3.fork出一个子进程进行rewrite,而父进程继续接收client命令,父进程的写操作命令都会被额外添加到一个aof_rewrite_buf_blocks缓冲中。
4.当子进程rewrite结束后,父进程收到子进程退出信号,把aof_rewrite_buf_blocks的缓冲添加到rewrite后的文件中,然后切换AOF的文件fd。rewrite任务完成,继续第二个步骤。

关键点:
1.由于写操作通常是有缓冲的,所以有可能AOF操作并没有写到硬盘中,一般可以通过fsync()来强制输出到硬盘中。
而fsync()的频率可以通过配置文件中的flush策略来指定,可以选择每次事件循环写操作都强制fsync或者每秒fsync至少运行一次。

2.当rewrite子进程开始后,父进程接受到的命令会添加到aof_rewrite_buf_blocks中,使得rewrite成功后,将这些命令添加到新文件中。
在rewrite过程中,原来的AOF也可以选择是不是继续添加,由于存在性能上的问题,在rewrite过程中,如果fsync()继续执行,会导致IO性能受损影响Redis性能。
所以一般情况下rewrite期间禁止fsync()到旧AOF文件。这策略可以在配置文件中修改。


主从同步

Redis主从复制可以根据是否是全量分为全量同步和增量同步。

(一)全量同步(Master add Slave

 主redis负责接收写请求与读请求,并将写请求同步到从redis。从redis只可读。

 主/从redis同步数据,原理比较简单,步骤如下:

 1.从redis发送一个sync命令给主master (从redis可以对外接受读请求,也可以不接受)

 2.主master执行一个bgsave,生成最新的备份文件,这个过程中如果有新的写请求则将它写入到backlog

 3.当主master生成最新备份db文件后,主master将它发送到从redis服务器

 4. 从redis服务器接收完备份文件后,替换掉原从redis内存中的数据,然后ack给主master

 5.主master最后将接受sync请求并且开始做bgsave起到从redis发回ack后这段时间的所有数据backlog发回到从redis

 6.从redis解析backlog,并放入到内存当中

(一)增量同步

Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。


主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。

参考: http://blog.csdn.net/zhaozhenzuo/article/details/31797529

        http://blog.csdn.net/sk199048/article/details/50725369

==================================================================================================

redis内存陷阱

add slave 后者是调用bgsave命令时,redis内存会瞬间增大一倍?//TODO??

参考:http://www.iteye.com/topic/808293



0 0
原创粉丝点击