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

Redis的主从复制

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

在Slave启动并连接到Master之后,它将主动发送一条SYNC命令。此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。

如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。

redis 复制在 master 这一端是非阻塞的,也就是说在和 slave 同步数据的时候,master 仍然可以执行客户端的操作命令而不受其影响。这点都不能保证,要你干嘛?
redis 复制在 slave 这一端也是非阻塞的。在配置文件里面有 slave-serve-stale-data 这一项,如果它为 yes ,slave 在执行同步时,它可以使用老版本的数据来处理查询请求,如果是 no ,slave 将返回一个错误。在完成同步后,slave 需要删除老数据,加载新数据,在这个阶段,slave 会阻止连接进来。

但是,我们可以很明显的看到,RDB有他的不足,就是一旦Redis出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到 Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。 但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制:AOF日志,稍后分析。



3. Rdb快照原理


Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。这种方法是非常好理解的,但是一个持续写入的数据库如何生成快照呢?

Redis借助了fork命令的copy on write机制(私有内存非共享内存)。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。

我们可以通过Redis的save指令来配置RDB快照生成的时机,比如你可以配置当10分钟以内有100次写入就生成快照,也可以配置当1小时内有 1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。

在redis中配置:

1、save 900 1 #当900秒内有一条Keys数据被改变时,生成RDB;

2、save 300 10 #当300秒内有10条Keys数据被改变时,生成RDB;

3、save 60 10000 #当60秒内有10000条Keys数据被改变时,生成RDB;

4. Redis的AOF日志

AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个 的Redis标准命令。当然,并不是发送到Redis的所有命令都要记录到AOF日志里面,只有那些会导致数据发生修改的命令才会追加到AOF文件。

那么每一条修改数据的命令都生成一条日志,那么AOF文件是不是会很大?

答案是肯定的,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite(使用Redis提供了bgrewriteaof命令就可以)。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件(这个过程和RDB类似,但是是将数据拆分成一条一条写命令的形式的)。在写入新文件的过程中,所有的写操作日志还是会写到原来老的
AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的 AOF文件取代老的AOF文件。(这样的操作,老的AOF可以恢复内存,如果产生新的AOF,老的就不存在了,可用新的AOF文件恢复内存,这样同时解决了AOF不断增长的问题。)AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的5个流程。

那么写AOF的操作安全性又有多高呢?

实际上这是可以设置的,在Redis中对AOF调用write(2)写入后,何时再调用fsync将其写到磁盘上,通过appendfsync选项来控制,下面 appendfsync的三个设置项,安全强度逐渐变强。

1)appendfsync no

当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。

2)appendfsync everysec

当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多 长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。

结论就是,在绝大多数情况下,Redis会每隔一秒进行一 次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。

3)appendfsync always

置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,

所以其性能也会受到影响。

Redis数据恢复:

RDB的启动时间会更短,原因有两个:

一、RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。

二、RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作,所以在CPU消耗上要远小于AOF日志的加载。


5. Redis的Rdb文件

在slave server执行sync命令,请求同步,如下返回rdb文件,为二进制文件,






6. Redis的AOF文件

默认关闭,打开AOF设置,如下
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: