Redis 复制原理及分析

1.测试

见master-slave测试帖

2 原理

第一次、Slave向Master同步的实现是:

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

################################ SNAPSHOTTING  #################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving at all commenting all the "save" lines.

save 900 1
save 300 10
save 60 10000

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文件,为二进制文件,

redis 127.0.0.1:6380> sync
"REDIS0002\xfe\x00\n\anumbers\x0f\x0f\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\xc0x03\x00\xff\x00\x03old\xc0\x01\x00\bkeywatch\xc0\x03\x00\x04name\x05kerry\x00\x0
3aaa\xc0o\x02\aletters\x02\x01c\x01b\t\x04car1\x19\x02\x04name\x05\x00AUDIO\x05p
rice\x03\x0030w\xff\t\x04car2\x19\x02\x04name\x05\x00AUDIO\x05price\x03\x0020w\x
ff\t\x04car3\x19\x02\x04name\x05\x00buick\x05price\x03\x0010w\xff\x00\x03key\x03
aaa\x00\x03num\xc0\x04\x00\x02a1\xc0\x01\x00\x02a2\xc0\x02\x00\x06keynew\xc0\x04
\x00\x02a3\xc0\x03\x02\bletters2\x03\x01c\x01d\x01e\x00\acompany\x03alu\x00\x0co
ldvalue=GET\x03old\xff"
redis 127.0.0.1:6380>

具体文件为redis目录下,如下所示:

6. Redis的AOF文件

默认关闭,打开AOF设置,如下

############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. If you can live
# with the idea that the latest records will be lost if something like a crash
# happens this is the preferred way to run Redis. If instead you care a lot
# about your data and don‘t want to that a single record can get lost you should
# enable the append only mode: when this mode is enabled Redis will append
# every write operation received in the file appendonly.aof. This file will
# be read on startup in order to rebuild the full dataset in memory.
#
# Note that you can have both the async dumps and the append only file if you
# like (you have to comment the "save" statements above to disable the dumps).
# Still if append only mode is enabled Redis will load the data from the
# log file at startup ignoring the dump.rdb file.
#
# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
# log file in background when it gets too big.

appendonly yes

windwos下无法生成,可能兼容性有问题。生成的aof文件与rdb文件在同目录下。

时间: 2024-08-21 07:25:28

Redis 复制原理及分析的相关文章

Redis复制原理

无论是在集群中还是主从结构中,redis新加入的节点和已有主(从)节点的消息同步都是通过sync命令的形式 下面来实践一下redis的同步机制, 新建主服务器于从服务器 主 从: 这是正常的主从结构,我们使用telnet工具来模拟一下从数据库,再看看它与主库的交互 连接主库,主库响应 向主库表明端口号 replconf listening-port 6381 +OK 发送SNYC命令 此时主库的反应,它认为自己建立了一个从库: 从库会将收到的内容写入到硬盘中,用以替换自己的RDB快照 初始化完成

浅析 Redis 复制

摘要 早期的 RDBMS 被设计为运行在单个CPU之上,读写操作都由经单个数据库实例完成,复制技术使得数据库的读写操作可以分散在运行于不同CPU之上的独立服务器上.Redis作为一个开源的.优秀的key-value缓存及持久化存储解决方案,也提供了复制功能,本文主要介绍Redis的复制原理及特性. Redis复制概论 数据库复制指的是发生在不同数据库实例之间,单向的信息传播的行为,通常由被复制方和复制方组成,被复制方和复制方之间建立网络连接,复制方式通常为被复制方主动将数据发送到复制方,复制方接

Redis 复制、Sentinel的搭建和原理说明(转)

Redis 复制.Sentinel的搭建和原理说明 转自:http://www.cnblogs.com/zhoujinyi/p/5570024.html. 背景: Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master

Redis 复制、Sentinel的搭建和原理说明

背景: Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换,更多的信息见前一篇说明.它的主要功能有以下几点: 1,不时地监控redis是否按照预期良好地运行; 2,如果发现某个redis节点运行

mysql复制原理及作用分析(2014-11-10)

复制原理 1. master将数据写到binlog中. 2. slave开启两个线程I/O thread和SQL thread. 3. slave的I/O thread线程连接到master,读取master上的binlog文件名称及binlog的position位置. 4. slave通过I/O thread接收master的变更信息,写入到relay log(中继日志)中. 5. 通过SQL thread读取Relay log信息进行重放到slave中. 复制解决了什么? 个人认为复制主要作

全面剖析Redis Cluster原理和应用

全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最核心的目标有三个: 性能:这是Redis赖以生存的看家本领,增加集群功能后当然不能对性能产生太大影响,所以Redis采取了P2P而非Proxy方式.异步复制.客户端重定向等设计,而牺牲了部分的一致性.使用性. 水平扩展:集群的最重要能力当然是扩展,文档中称可以线性扩展到1000结点. 可用性:在Cl

redis演练(6) redis复制(主备模式)

redis是一款面向分布式的Nosql产品,天生对主备模式有很好的支持,而且配置一套完整的主备模式,非常简单.针对redis,主备模式配置非常简单,但线上意义重大. 主要内容 1.CAP理论 2.简单redis的复制原理 3.redis replaction相关配置参数解析 4.配置星型模型主备模式 5.配置有向无欢模型主备模式 1.研磨redis的复制与集群概念 redis的复制与集群,刚开始我把两者闹了个误会,在不断深入学习过程中及时改正了. 简单区分一下. redis复制:可以理解为把re

Redis实现原理(1)--链表

链表是Redis中使用非常广泛的一种数据结构,很多地方如List结构底层就是用链表实现的. 链表的定义在头文件adlist.h 中,很常见的双向链表,结构如下: 1 // 链表节点 2 typedef struct listNode { 3 struct listNode *prev; //指向前一个节点 4 struct listNode *next; //指向后一个节点 5 void *value; //值域 6 } listNode; 7 // 链表遍历迭代指针 8 typedef str

Redis复制与可扩展集群搭建【转】

本文会讨论一下Redis的复制功能以及Redis复制机制本身的优缺点以及集群搭建问题. Redis复制流程概述 Redis的复制功能是完全建立在之前我们讨论过的基于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你的系统内存容量规划,原因可以参考我上一篇文章中提到的Redis磁盘IO问题. Redis复制流程在Slave和Master端各自是一套状态机流转,涉及的状态信息是: Slave 端: REDIS