Redis的主从同步机制可以确保redis的master和slave之间的数据同步。按照同步内容的多少可以分为全同步和部分同步;按照同步的时机可以分为slave刚启动时的初始化同步和正常运行过程中的数据修改同步;本文将对这两种机制的流程进行分析。

全备份过程中,在slave启动时,会向其master发送一条SYNC消息,master收到slave的这条消息之后,将可能启动后台进程进行备份,备份完成之后就将备份的数据发送给slave,初始时的全同步机制是这样的:

(1)slave启动后向master发送同步指令SYNC,master接收到SYNC指令之后将调用该命令的处理函数syncCommand()进行同步处理;

(2)在函数syncCommand中,将调用函数rdbSaveBackground启动一个备份进程用于数据同步,如果已经有一个备份进程在运行了,就不会再重新启动了。

(3)备份进程将执行函数rdbSave()完成将redis的全部数据保存为rdb文件。

(4)在redis的时间事件函数serverCron(redis的时间处理函数是指它会定时被redis进行操作的函数)中,将对备份后的数据进行处理,在serverCron函数中将会检查备份进程是否已经执行完毕,如果备份进程已经完成备份,则调用函数backgroundSaveDoneHandler完成后续处理。

(5)在函数backgroundSaveDoneHandler中,首先更新master的各种状态,例如,备份成功还是失败,备份的时间等等。然后调用函数updateSlavesWaitingBgsave,将备份的rdb数据发送给等待的slave。

(6)在函数updateSlavesWaitingBgsave中,将遍历所有的等待此次备份的slave,将备份的rdb文件发送给每一个slave。另外,这里并不是立即就把数据发送过去,而是将为每个等待的slave注册写事件,并注册写事件的响应函数sendBulkToSlave,即当slave对应的socket能够发送数据时就调用函数sendBulkToSlave(),实际发送rdb文件的操作都在函数sendBulkToSlave中完成。

(7)sendBulkToSlave函数将把备份的rdb文件发送给slave。

上述函数调用过程如下图1所示:

图1 redis全备份时master部分的的函数调用过程

二、数据修改操作的同步

Redis的正常部署中一般都是一个master用于写操作,若干个slave用于读操作,另外定期的数据备份操作也是单独选址一个slave完成,这样可以最大程度发挥出redis的性能。在部署完成,各master\slave程序启动之后,首先进行第一阶段初始化时的全同步操作,全同步操作完成之后,后续所有写操作都是在master上进行,所有读操作都是在slave上进行,因此用户的写操作需要及时扩散到所有的slave以便保持数据最大程度上的同步。Redis的master-slave进程在正常运行期间更新操作(包括写、删除、更改操作)的同步方式如下:

(1)master接收到一条用户的操作后,将调用函数call函数来执行具体的操作函数(此过程可参考另一文档《redis命令执行流程分析》),在该函数中首先通过proc执行操作函数,然后将判断操作是否需要扩散到各slave,如果需要则调用函数propagate()来完成此操作。

(2)propagate()函数完成将一个操作记录到aof文件中或者扩散到其他slave中;在该函数中通过调用feedAppendOnlyFile()将操作记录到aof中,通过调用replicationFeedSlaves()将操作扩散到各slave中。

(3)函数feedAppendOnlyFile()中主要保存操作到aof文件,在该函数中首先将操作转换成redis内部的协议格式,并以字符串的形式存储,然后将字符串存储的操作追加到aof文件后。

(4)函数replicationFeedSlaves()主要将操作扩散到每一个slave中;在该函数中将遍历自己下面挂的每一个slave,以此对每个slave进行如下两步的处理:将slave的数据库切换到本操作所对应的数据库(如果slave的数据库id与当前操作的数据id不一致时才进行此操作);将命令和参数按照redis的协议格式写入到slave的回复缓存中。写入切换数据库的命令时将调用addReply,写入命令和参数时将调用addReplyMultiBulkLen和addReplyBulk,函数addReplyMultiBulkLen和addReplyBulk最终也将调用函数addReply。

(5)在函数addReply中将调用prepareClientToWrite()设置slave的socket写入事件处理函数sendReplyToClient(通过函数aeCreateFileEvent进行设置),这样一旦slave对应的socket发送缓存中有空间写入数据,即调用sendReplyToClient进行处理。

(6)函数sendReplyToClient()的主要功能是将slave中要发送的数据通过socket发出去。

图2、redis操作过程中数据同步的函数调用关系

图中的序号表示调用的先后关系,同级之间的序号才有意义。

redis如何实现主从数据的同步的更多相关文章

  1. mongo 主从数据不同步

    在从库上执行如下命令: repset:SECONDARY> rs.slaveOk()repset:SECONDARY> db.runCommand({"resync": ...

  2. redis持久化和主从同步

    redis持久化rdb与aof 简介 Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,Redis提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的 ...

  3. Redis Sentinel的Redis集群(主从&Sharding)高可用方案

    在不使用redis3.0之后版本的情况下,对于redis服务端一般是采用Sentinel哨兵模式,也就是一主多备的方式. 这里,先抛出三个问题, 问题1:单节点宕机数据丢失?问题2:多节点(节点间没有 ...

  4. redis持久化,主从及数据备份

    http://blog.csdn.net/lang_man_xing/article/details/38386113 现在在项目里已经大量使用redis了,为了提高redis的性能和可靠性我们需要知 ...

  5. 减少mysql主从数据同步延迟

    网上给出的解决办法: 基于局域网的master/slave机制在通常情况下已经可以满足'实时'备份的要求了.如果延迟比较大,就先确认以下几个因素:1. 网络延迟2. master负载3. slave负 ...

  6. Redis哨兵模式主从同步不可以绑定127.0.0.1或者0.0.0.0,不然无法进行主从同步

    Redis哨兵模式主从同步不可以绑定127.0.0.1或者0.0.0.0,不然无法进行主从同步,一定要绑定内网IP,而对于跨机房的问题,可以使用iptables进行nat转发来解决.

  7. canal整合springboot实现mysql数据实时同步到redis

    业务场景: 项目里需要频繁的查询mysql导致mysql的压力太大,此时考虑从内存型数据库redis里查询,但是管理平台里会较为频繁的修改增加mysql里的数据 问题来了: 如何才能保证mysql的数 ...

  8. mysql 主从数据同步配置

    一主一从,单向同步 master 数据库的数据变更单向同步到 slave 数据库 互为主从,双向同步 master 数据库的数据变更同步到 slave 数据库,slave 数据库的数据边同步到 mas ...

  9. redis持久化以及主从服务器的配置

    作者:silenceper 日期:2013-10-03 原文地址:http://silenceper.com/archives/959.html redis 与memcached 最大的一个区别就是R ...

随机推荐

  1. apscheduler 执行报错No handlers could be found for logger "apscheduler.executors.default

    执行报错如下: No handlers could be found for logger "apscheduler.executors.default 解决: 加入日志,查看具体报错,载根 ...

  2. GO语言开发之路

    Go语言开发之路 介绍 为什么学习Go语言? 开发环境准备 从零开始搭建Go语言开发环境 VS Code配置Go语言开发环境 基础 Go语言基础之变量和常量 Go语言基础之基本数据类型 Go语言基础之 ...

  3. 关于git clone远程仓库账户密码错误的问题

    这两天刚使用coding和git,但是在我第一次克隆coding上的项目的时候,提示输入账户和密码,当时我不知道这个账户和密码是指的哪个,就随便输入了,然后提示错误,,,,,, 之后每次克隆的时候都提 ...

  4. 对于模块加载:ES6、CommonJS、AMD、CMD的区别

    运行和编译的概念 编译包括编译和链接两步. 编译,把源代码翻译成机器能识别的代码或者某个中间状态的语言. 比如java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.还简单的作一些比如检查有 ...

  5. 2、HDFS交互式Shell

    管理模式 bin/hdfs dfsadmin ## run a hdfs admin client bin/hdfs dfsadmin -report ##报告信息 bin/hdfs dfsadmin ...

  6. go 学习 (五):goroutine 协程

    一.goroutine 基础 定义 使用者分配足够多的任务,系统能自动帮助使用者把任务分配到 CPU 上,让这些任务尽量并发运作,此机制在Go中称作 goroutine goroutine 是 Go语 ...

  7. siameseNet网络以及信号分类识别应用

    初学siameseNet网络,希望可以用于信号的识别分类应用.此文为不间断更新的笔记. siameseNet简介 全连接孪生网络(siamese network)是一种相似性度量方法,适用于类别数目多 ...

  8. 洛谷 P1821 [USACO07FEB]银牛派对Silver Cow Party 题解

    P1821 [USACO07FEB]银牛派对Silver Cow Party 题目描述 One cow from each of N farms (1 ≤ N ≤ 1000) conveniently ...

  9. SpringBoot中Example的动态条件查询

    一.无匹配器的情况: Person person = new Person(); person.setName("test"); Role role = new Role(); r ...

  10. 阿里云部署自己的web服务器

    阿里云部署自己的web服务器 [外链图片转存失败(img-GIKNTPPx-1564287221547)(https://upload-images.jianshu.io/upload_images/ ...