redis高可用 - 主从复制
工作需要,调研了一下redis的复制实现。在2.8版本之前和之后,复制方式有所不同。2.8之前的复制方式对于初次复制数据没有问题,对于断连接重新复制比较耗性能,因为都是全量复制。2.8之后对断线重连做了优化,采用差量复制。
旧版复制功能的实现
redis复制功能有同步和命令传播两种。
同步操作将从服务器的数据库状态更新至主服务器当前的数据库状态;
命令传播用于在主服务器数据库状态改变,主从服务器数据状态不一致时,让主从服务器数据库状态重新回到一致状态。
同步
客户端向从服务器发送SLAVEOF命令,从服务器开始向主服务器请求同步数据,通过向主服务器发送SYNC命令完成同步过程,下面罗列SYNC命令的执行步骤:
1.从服务器向主服务器发送SYNC命令;
2.主服务器收到SYNC命令后执行BGSAVE命令,在后台生成一个rdb文件,并使用一个缓冲区记录从此刻开始执行的所有写操作命令;
3.主服务器的BGSAVE命令执行完毕,主服务器会将生成的rdb文件发送给从服务器,从服务器接收并加载这个rdb文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态;
4.主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。
时间 | 主服务器 | 从服务器 |
t0 | 服务器启动 | 服务器启动 |
t1 | 执行SET K1 V1 | |
t2 | 执行SET K2 V2 | |
t3 | 执行SET K3 V3 | |
t4 | 向主服务器发送SYNC命令 | |
t5 |
接收从服务器发来的SYNC命令,执行BGSAVE命令,创建包含K1,K2,K3的rdb文件,并用缓冲区记录接下来执行的所有写操作 | |
t6 | 执行SET K4 V4,并将这个命令保存到缓冲区 | |
t7 | 执行SET K5 K5,并将这个命令保存到缓冲区 | |
t8 | BGSAVE命令执行完毕,向从服务器发送rdb文件 | |
t9 |
接收并加载rdb文件,使数据库更新到主服务器执行BGSAVE命令时的数据库状态 | |
t10 | 向从服务器发送缓冲区保存的写命令SET K4 V4和SET K5 V5 | |
t11 | 接收并执行主服务器发来的两个SET命令 | |
t12 | 同步完成,现在注册服务器状态一致 | 同步完成,现在注册服务器状态一致 |
命令传播
同步操作完成之后,主从服务器数据库状态达到一致,后续的状态就靠命令传播保持主从服务器状态一致。主服务器会将自己执行的写操作命令,原封不动地发送给从服务器,从服务器执行相同的写操作之后,主从服务器数据库状态重新达到一致。
旧版本复制功能的缺陷
在redis2.8之前,从服务器对主服务器的复制分为以下两种情况:
1.初次复制:从服务器没有复制过任何主服务器,或者从服务器要复制的主服务器和上次复制的主服务器不同;
2.断线重连重新复制:处于命令传播的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连重新连接上了主服务器,并重新从头开始全量复制主服务器。
对于初次复制而言,旧版复制功能可以较好的完成任务,但对于断线重连的情况,虽然可以让主从服务器重新回到一致,但是效率确是比较低下的。
SYNC操作是一个非常耗费资源的操作
每次执行SYNC命令时,主从服务器将执行以下动作:
1.主服务器执行BGSAVE生成rdb文件,此操作耗费主服务器大量的cpu,内存和磁盘io资源。
2.主服务器要将自己生成的rdb文件发送给从服务器,此操作会消耗主从服务器大量的网络资源,并对主服务器响应命令请求的时间产生影响。
3.接收到rdb文件的从服务器需要载入rdb文件,并且载入期间,从服务器因阻塞而无法处理命令请求。
新版复制功能的实现
为了解决旧版断线重连重复复制的低效问题,2.8版本开始使用PSYNC代替SYNC命令执行同步操作。PSYNC命令包括完整同步和部分同步:
1.完整同步用于处理初次复制的情况:PSYNC执行步骤和SYNC的执行步骤基本一样;
2.部分同步用于处理断线重连的复制情况:断线重连时,如果条件允许,主服务器可以将主从服务器断连接期间执行的写命令发送给从服务器,从服务器更具这些写命令更新数据库状态至主服务器当前的状态。
下表展示PSYNC命令解决断线重连的复制情况的例子:
时间 | 主服务器 | 从服务器 |
t1 | 主从服务器完成同步 | 主从服务器完成同步 |
t2 | 执行并传播SET K2 V2 | 执行主服务器传播来的SET K2 V2 |
t3 | 执行并传播SET K3 V3 | 执行主服务器传播来的SET K3 V3 |
… | ||
t20 | 执行并传播SET K20 V20 | 执行并传播SET K20 V20 |
t21 | 主从服务器断开连接 | 主从服务器断开连接 |
t22 | 执行SET K22 V22 | 断线,尝试重连 |
t23 | 执行SET K23 V23 | 断线,尝试重连 |
t24 | 主从服务器重新建立连接 | 主从服务器重新建立连接 |
t25 | 向主服务器发生PSYNC命令 | |
t26 | 向从服务器返回+CONTINUE回复,标识执行部分同步 | |
t27 | 接收主服务回复的+CONTINUE,准备部分同步 | |
t28 | 向从服务器发送SET K22 V22和SET K23 V23两个命令 | |
t29 | 接收并执行主服务器传来的两个命令 | |
t30 | 主从服务器再次完成同步,状态一致 | 主从服务器再次完成同步,状态一致 |
由此可见,PSYNC在执行部分同步的时候比执行SYNC命令所需要的资源少很多,速度也加快了。执行SYNC命令需要生成,传送,载入整个rdb文件,而PSYNC的部分同步只需将差量的写命令发送给从服务器便可。
部分重同步的实现
部分重同步由以下三部分组成:
1.主服务器的复制偏移量和从服务器的复制偏移量;
2.主服务器的复制积压缓冲区;
3.服务运行的id。
复制偏移量
执行复制的双方分别维护一个复制偏移量:
1.主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量加N;
2.从服务器每次收到主服务器传来的N个字节的数据时,就将自己的复制偏移量加N。
如果主从服务器数据库处于一致状态时,那么主从服务器的复制偏移量总是一致的,但是如果主从服务器偏移量不相同,说明主从服务器状态不一致。
复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度的先进先出队列,默认大小为1MB。
当主服务器进行命令传播时,他会做两个操作,1.将命令发送给从服务器,2.将命令写入到复制积压缓冲区,因此复制积压缓冲区里会保存一部分最近传播的写命令,并且会为队列中的每个字节记录相应的复制偏移量,如下表所示。
偏移量 | … | 10086 | 10087 | 10088 | 10089 | 10090 | 10091 | 10092 | 10093 | 10094 | 10095 | 10096 | … |
字节值 | … | ‘*’ | 3 | ‘\r’ | ‘\n’ | ‘$’ | 3 | ‘\r’ | ‘\n’ | ‘S’ | ‘E’ | ‘T’ | … |
当主从服务器重连成功后,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器根据这个偏移量决定对从服务器执行何种操作:
1.如果offset偏移量之后的数据仍然存在于复制积压缓冲区里面,那么主服务器会对从服务器进行部分同步操作;
2.如果offset偏移量之后的数据不在复制积压缓存区里面,那么主服务器对从服务器进行完整同步操作。
服务器运行id
每个redis服务器,无论主从服务,都会有自己的运行id。运行id在启动时生成,由40个随机的十六进制字符组成。
当从服务器对主服务器进行初次复制时,主服务器将自己运行的id传送给从服务器,从服务器将这个id保存。
当从服务器断线并重连上上一个主服务器时,从服务器将保存的id发送给主服务器:
如果从服务器保存的运行id和当前连接的主服务运行id相同,说明从服务器断线之前复制的就是这台主服务器,主服务器可以继续吃、执行部分同步操作;
如果从服务器保存的运行id和当前连接的主服务器运行id不一致,那么说明从服务器断线之前连接的主服务器不是当前连接的主服务器民主服务器对从服务器执行完整同步操作。
总结
新redis的复制机制在老的复制机制上加了个部分同步,解决断线重连时的全量复制数据的低性能情况。部分同步的机制依赖于复制偏移量,复制积压缓冲区,服务运行id。
复制偏移量是为了让从服务器知晓下次该从何处开始进行部分重同步;
复制积压缓冲区是为了主服务器找到上次复制的点,从该点开始给从服务器复制数据。如果找不到这个点,就要执行完整同步过程了;
服务运行id主要是为保证重连的主服务器是否为上次连接的主服务器,如果是才能执行部分重同步,否则就只能进行完整同步了。
本文参考黄健宏著的 redis设计与实现
redis高可用 - 主从复制的更多相关文章
- redis高可用、redis集群、redis缓存优化
今日内容概要 redis高可用 redis集群 redis缓存优化 内容详细 1.redis高可用 # 主从复制存在的问题: 1 主从复制,主节点发生故障,需要做故障转移,可以手动转移:让其中一个sl ...
- Redis高可用之主从复制实践(四)
0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...
- Redis高可用(持久化、主从复制、哨兵、集群)
Redis高可用(持久化.主从复制.哨兵.集群) 目录 Redis高可用(持久化.主从复制.哨兵.集群) 一.Redis高可用 1. Redis高可用概述 2. Redis高可用策略 二.Redis持 ...
- Redis高可用之主从复制原理演进分析
Redis高可用之主从复制原理演进分析 在很久之前写过一篇 Redis 主从复制原理的简略分析,基本是一个笔记类文章. 一.什么是主从复制 1.1 什么是主从复制 主从复制,从名字可以看出,至少需要 ...
- Redis 高可用集群
Redis 高可用集群 Redis 的集群主从模型是一种高可用的集群架构.本章主要内容有:高可用集群的搭建,Jedis连接集群,新增集群节点,删除集群节点,其他配置补充说明. 高可用集群搭建 集群(c ...
- Redis高可用方案----Redis主从+Sentinel+Haproxy
安装环境 这里使用三台服务器,每台服务器上开启一个redis-server和redis-sentinel服务,redis-server端口为6379,redis-sentinel的端口为26379. ...
- 9.Redis高可用-哨兵
9.Redis高可用-哨兵9.1 基本概念9.1.1 主从复制的问题9.1.2 高可用9.1.3 Redis Sentinel的高可用性9.2 安装和部署9.2.1 部署拓扑结构9.2.2 部署Red ...
- Redis高可用详解:持久化技术及方案选择
文章摘自:https://www.cnblogs.com/kismetv/p/9137897.html 前言 在上一篇文章中,介绍了Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关 ...
- Redis高可用集群-哨兵模式(Redis-Sentinel)搭建配置教程【Windows环境】
No cross,no crown . 不经历风雨,怎么见彩虹. Redis哨兵模式,用现在流行的话可以说就是一个"哨兵机器人",给"哨兵机器人"进行相应的配置 ...
随机推荐
- Web 漏洞分析与防御之点击劫持(三)
原文地址:Web 漏洞分析与防御之点击劫持(三) 博客地址:http://www.extlight.com 一.全称 点击劫持,顾名思义,用户点击某个按钮,却触发了不是用户真正意愿的事件. 二.原理 ...
- 搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门(转)
转自:http://www.ruanyifeng.com/blog/2012/08/blogging_with_jekyll.html 喜欢写Blog的人,会经历三个阶段. 第一阶段,刚接触Blog, ...
- golang回调函数的例子
package main import "fmt" type TestStruct struct { } func (object *TestStruct) test(msg st ...
- 杂项: Memcached
ylbtech-杂项: Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动 ...
- 软件官网与memcached介绍
常见官网 http://www.keepalived.org http://nginx.org/ documentation 模块说明 http://www.apache.org/ https://o ...
- 第七章 HTTP流量管理(二) URL 重写
URL 重定向功能: 浏览器中输入 http://<host_name>:31380/v1/service-A/XXXX 经过下面的重定向,实际调用的是serviceA的/v1/XXXX ...
- i2c驱动程序全面分析,从adapter驱动程序到设备驱动程序
开发板 :mini2440 内核版本:linux2.6.32.2 驱动程序参考:韦东山老师毕业班i2c 内容概括: 1.adapter client 简介 2.adapter 驱动框架 ...
- 使用wifi网卡笔记3---工具wpa_supplicant(STA模式)
1. wpa_supplicant介绍 supplicant是恳求者的意思,是wpa的发起者,是发送认证请求的设备(手机),手机--AP--认证服务器,可用于上述4种"认证/加密" ...
- ceph集群jewel版本 rbd 块map 报错-故障排查
测试信息如下: [root@ceph_1 ~]# ceph osd pool lsrbdchy_123swimmingpool #新建rbd 块: rbd create swimmingpool/ba ...
- python‘s second day for me
in not in 主要用来检测一些字符串是否存在,或者避免一些字符串 while True: comment = input('请输入你的评论') if '顾清秋' in comment: ...