Redis教程:主从复制
目录
1 主从配置方法
2 主从复制的作用
3 主从复制的机制
3.1 全量数据同步(full resyncchrozation)
3.2 增量同步
4 主从复制的实现
4.1 主从关系的建立
1 主从配置方法
- 配置文件: 在从服务器的配置文件中加入:slaveof ip port
- 启动命令: redis-server启动命令后加入 --slaveof ip port <本地端口:--port xxxx>
- 客户端命令: Redis服务器启动后,直接通过客户端执行命令:slaveof ip port,则该Redis实例成为从节点。
从模式:
# Redis使用后台模式
daemonize yes
# 关闭保护模式
#protected-mode no
# 注释以下内容开启远程访问
# bind 127.0.0.1
# 修改启动端口为6379
port 6380
# 修改pidfile指向路径(单机多服务建议修改)
pidfile /usr/local/redis-4.0.4/conf/redis_6380.pid
#数据库的存放位置(单机多服务建议修改)
dir /usr/local/redis-4.0.4/db/slave_xxx
#Slaveof命令可以将当前服务器转变为指定服务器的从属服务器(slave server)。
slaveof 192.168.235.128 6379
2 主从复制的作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
- 读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量;
- 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
3 主从复制的机制
Redis的主从复制功能除了支持一个Master节点对应多个Slave节点的同时进行复制外,还支持Slave节点向其它多个Slave节点进行复制。这样就使得架构师能够灵活组织业务缓存数据的传播,例如使用多个Slave作为数据读取服务的同时,专门使用一个Slave节点为流式分析工具服务。Redis的主从复制功能分为两种数据同步模式进行:全量数据同步和增量数据同步。
3.1 全量数据同步(full resyncchrozation)
先执行一次全同步 — 请求master BgSave出自己的一个RDB Snapshot文件发给slave,slave接收完毕后,清除掉自己的旧数据,然后将RDB载入内存。
上图简要说明了Redis中Master节点到Slave节点的全量数据同步过程。当Slave节点给定的replication id 和Master的replication id不一致时,或者Slave给定的上一次增量同步的offset的位置在Master的环形内存中(replication backlog)无法定位时(后文会提到),Master就会对Slave发起全量同步操作。这时无论您是否在Master打开了RDB快照功能,它和Slave节点的每一次全量同步操作过程都会更新/创建Master上的RDB文件。在Slave连接到Master,并完成第一次全量数据同步后,接下来Master到Slave的数据同步过程一般就是增量同步形式了(也称为部分同步)。增量同步过程不再主要依赖RDB文件,Master会将新产生的数据变化操作存放在replication backlog这个内存缓存区,这个内存区域是一个环形缓冲区,也就是说是一个FIFO的队列。
3.2 增量同步
进行增量同步 — master作为一个普通的client连入slave,将所有写操作转发给slave,没有特殊的同步协议。具体过程如下:
为什么在Master上新增的数据除了根据Master节点上RDB或者AOF的设置进行日志文件更新外,还会同时将数据变化写入一个环形内存结构(replication backlog),并以后者为依据进行Slave节点的增量更新呢?主要原因有以下几个:
由于网络环境的不稳定,网络抖动/延迟都可能造成Slave和Master暂时断开连接,这种情况要远远多于新的Slave连接到Master的情况。如果以上所有情况都使用全量更新,就会大大增加Master的负载压力——写RDB文件是有大量I/O过程的,虽然Linux Page Cahe特性会减少性能消耗。
另外在数据量达到一定规模的情况下,使用全量更新进行和Slave的第一次同步是一个不得已的选择——因为要尽快减少Slave节点和Master节点的数据差异。所以只能占用Master节点的资源和网络带宽资源。
使用内存记录数据增量操作,可以有效减少Master节点在这方面付出的I/O代价。而做成环形内存的原因,是为了保证在满足数据记录需求的情况下尽可能减少内存的占用量。这个环形内存的大小,可以通过repl-backlog-size参数进行设置。
Slave重连后会向Master发送之前接收到的Master replication id信息和上一次完成部分同步的offset的位置信息。如果Master能够确定这个replication id和自己的replication id(有两个)一致且能够在环形内存中找到这个offset的位置,Master就会发送从offset的位置开始向Slave发送增量数据。那么连接正常的各个Slave节点如何接受新数据呢?连接正常的Slave节点将会在Master节点将数据写入环形内存后,主动接收到来自Master的数据复制信息。
这里就有一个问题了,我们的replication backlog的size设置为多大合适?
redis为replication backlog设置的默认大小为1M(repl-backlog-size),但是这个值是可以调整的,如果主服务器需要执行大量的写命令,又或者主从服务器之间断线后重连的时间比较长,那么这个大小也许并不合适。如果replication backlog的大小设置不恰当,那么PSYNC命令的复制同步模式就不能正常发挥作用,因此,正确估算和设置replication backlog的size非常重要。
建议:repl-backlog-size = reconnect_time_second * write_size_per_second*2
- reconnect_time_second : 重连时间,以秒未单位
- write_size_per_second : 每秒写入的命令大小
4 主从复制的实现
下面这段是slava机器上的log
9322:S 22 Feb 21:58:19.363 * Connecting to MASTER 192.168.235.128:6379
9322:S 22 Feb 21:58:19.365 * MASTER <-> SLAVE sync started
9322:S 22 Feb 21:58:19.366 * Non blocking connect for SYNC fired the event.
9322:S 22 Feb 21:58:19.367 * Master replied to PING, replication can continue...
9322:S 22 Feb 21:58:19.369 * Trying a partial resynchronization (request ac9f4efccb61b7e1415c2dcef3cc9580cbab5a02:1).
9322:S 22 Feb 21:58:19.371 * Full resync from master: f6857e8cabdcfef6d8fc376013ec37c21c7bb0eb:23254
9322:S 22 Feb 21:58:19.372 * Discarding previously cached master state.
9322:S 22 Feb 21:58:19.432 * MASTER <-> SLAVE sync: receiving 205 bytes from master
9322:S 22 Feb 21:58:19.435 * MASTER <-> SLAVE sync: Flushing old data
9322:S 22 Feb 21:58:19.436 * MASTER <-> SLAVE sync: Loading DB in memory
9322:S 22 Feb 21:58:19.437 * MASTER <-> SLAVE sync: Finished with success
首先,在redis内部,所有的命令都维护在一张表格里:
struct redisCommand redisCommandTable[] = {{"get",getCommand,2,"r",0,NULL,1,1,1,0,0},{"set",setCommand,-3,"wm",0,NULL,1,1,1,0,0},{"setnx",setnxCommand,3,"wm",0,NULL,1,1,1,0,0},{"setex",setexCommand,4,"wm",0,NULL,1,1,1,0,0},........}
PS:当然所有的这些command,在启动的时候会调用populateCommandTable函数进行分析,然后把所有的redis command放在server.commands,它是一个字典。
dict commands; / Command table */
当我们在客户端执行slaveof 的,在客户端这一侧会调用replicaofCommand这个函数。
4.1 主从关系的建立
主从复制建立的方式有三种:
- 在redis.conf文件中配置slaveof 选项,然后指定该配置文件启动Redis生效。
- 在redis-server启动命令后加上--slaveof 启动生效。
- 直接使用 slaveof 命令在从节点执行生效。
无论是通过哪一种方式来建立主从复制,都是从节点来执行slaveof命令,那么从节点执行了这个命令到底做了什么,我们上源码伪码:
void replicaofCommand(client *c) {1、判断当前环境是否在集群模式下,因为集群模式下不行执行该命令。2、是否执行的是SLAVEOF NO ONE命令,该命令会断开主从的关系,设置当前节点为主节点服务器。3、设置从节点所属主节点的IP和port。调用了replicationSetMaster()函数。
}
其中replicationSetMaster()函数执行操作的也很简单,总结为两步:
- 清理之前所属的主节点的信息。
- 设置新的主节点IP和port等。 因为,当前从节点有可能之前从属于另外的一个主节点服务器,因此要清理所有关于之前主节点的缓存、关闭旧的连接等等。然后设置该从节点的新主节点,设置了IP和port,还设置了以下状态:
slaveof命令是一个异步命令,执行命令时,从节点保存主节点的信息,确立主从关系后就会立即返回,后续的复制流程在节点内部异步执行。那么,如何触发复制的执行呢?
周期性执行的函数:replicationCron()函数,该函数被服务器的时间事件的回调函数serverCron()所调用,而serverCron()函数在Redis服务器初始化时,被设置为时间事件的处理函数。
// void initServer(void) Redis服务器初始化
aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL)
replicationCron这个函数每秒才执行一次,以下代码执行到serverCron函数的实现:
/* Replication cron function -- used to reconnect to master,* detect transfer failures, start background RDB transfers and so forth. */run_with_period(1000) replicationCron();
主从关系建立后,从节点服务器的server.repl_state被设置为REPL_STATE_CONNECT,而replicationCron()函数会被每秒执行一次,该函数会发现我(从节点)现在有主节点了,而且我要的状态是要连接主节点(REPL_STATE_CONNECT)。
replicationCron()函数处理这以情况的代码如下:
/* Check if we should connect to a MASTER */
// 如果处于要必须连接主节点的状态,尝试连接
if (server.repl_state == REPL_STATE_CONNECT) {serverLog(LL_NOTICE,"Connecting to MASTER %s:%d",server.masterhost, server.masterport);// 以非阻塞的方式连接主节点if (connectWithMaster() == C_OK) {serverLog(LL_NOTICE,"MASTER <-> SLAVE sync started");}
}
replicationCron()函数根据从节点的状态,调用connectWithMaster()非阻塞连接主节点。connectWithMaster()函数执行的操作可以总结为:
根据IP和port非阻塞的方式连接主节点,得到主从节点进行通信的文件描述符fd,并保存到从节点服务server.repl_transfer_s中,并且将刚才的REPL_STATE_CONNECT状态设置为REPL_STATE_CONNECTING。 监听fd的可读和可写事件,并且设置事件发生的处理程序syncWithMaster()函数。 至此,主从网络建立就完成了,逐步进入了协商交互阶段,使用的是状态机处理的,
Redis教程:主从复制相关推荐
- linux redis客户端_你见过能把Redis的主从复制讲这么明白的吗?
概念 1.Conception(概念) Redis的复制也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 ...
- redis设置主从复制-slave Replication--解决报错:(error) READONLY You can't write against a read only slave.
我的个人博客:zhang0peter的个人博客 主节点按照我上篇文章的内容配好redis后就可以了:ubuntu, debian 安装redis,设置开机自动启动和密码,允许外网访问 在从节点安装好r ...
- Redis的主从复制与高可用搭建(哨兵模式)
前言 为什么要使用Redis 首先我们先介绍些redis的基本概念,redis是Nosql数据库,是一个key-value存储系统.虽然redis是key-value的存储系统,但是redis支持的v ...
- Redis:主从复制原理
1. 前言 Redis是一个高性能的K-V内存数据库.对于Redis来说,当访问读请求的并发量增加的时候,Redis主服务器会成为一个性能瓶颈.为了分担读压力,Redis支持主从复制,Redis的主从 ...
- Redis教程:NoSQL键值存储
课程大纲 Redis是使用ANSI C编写的具有可选持久性的开源,网络化,内存中键值数据存储.根据DB-Engines.com的月度排名,Redis是最受欢迎的键值存储. 它的名字意思是远程字典服务器 ...
- redis 持久化 + 主从复制+ 集群
2019独角兽企业重金招聘Python工程师标准>>> 一. Linux 下的 Redis 安装 && 启动 && 关闭 && 卸载 ...
- 今天来聊聊 Redis 的主从复制
作者 | 阿Q 来源 | 阿Q说代码 今天我们就从配置文件.设计原理.面试真题三个方面来聊一聊 Redis 的主从复制. 在 Redis 复制的基础上,使用和配置主从复制非常简单,能使得从 Redis ...
- 关于Redis配置主从复制踩到的坑,主机不显示从机的连接信息
关于Redis配置主从复制踩到的坑!!! 设置单机集群的时候,两台从机都显示连接到主机,但是主机显示连接到的从机数量为0: 主机信息: 从机80: 从机81: 查看从机log日志文件发现错误信息: M ...
- Redis系列-主从复制配置
Redis虽然有着卓越的性能,但我们仍然可以通过master/slave这种简单架构,进行读写分离,进一步挖掘redis的性能,提高系统的可用性. redis怎么进行主从复制呢?redis复制主要是通 ...
- 【重难点】【Redis 02】Redis 的持久化、Redis 的主从复制和集群、哨兵
[重难点][Redis 02]Redis 的持久化.Redis 的主从复制和集群.哨兵 文章目录 [重难点][Redis 02]Redis 的持久化.Redis 的主从复制和集群.哨兵 一.Redis ...
最新文章
- 9种不同的方法帮助你提高国内访问Github的速度!
- jvm十三:类加载器命名空间
- tomca7.0 mysql配置连接池_tomcat7.0+mysql连接池配置
- java发送加密报文_RSA加密---从后台到客户端实现报文加解密
- QML基础类型之double
- Memcached的配置,SSH项目中的整合(com.whalin),Memcached工具类,Memcached的代码调用
- Java将一段逗号分割的字符串转换成一个数组(亲测)
- 2修改字段名_DevExpress ASP.NET v18.2新功能详解(二)
- js 进阶篇 代码等级提升
- mysql网页化_页面化操作数据库
- 运行caffe自带的两个简单例子
- java 调用php文件上传_php上传文件,接口是java,go。
- php 计算数组的差值,数组计算差值及项的小计,该如何处理
- 如果第一次见面,投资人就能给创业者提出建设性的意见
- html中下拉日历控件,HTML5之日历控件
- 自制Flash电子相册
- 【Vue脚手架安装教程】
- 计算机金融学校排名2015,金融学院2015级各专业排名情况统计表
- 静态路由 动态路由 php,静态路由汇总(路由聚合)
- JAVA7-6 约分最简分式 (15 分)
热门文章
- express : 无法将“express”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。express: command not found
- 【数据结构笔记10】二叉树的先序、中序、后序遍历,中序遍历的堆栈/非递归遍历算法,层序遍历,确定一个二叉树,树的同构
- 加密算法使用(五):RSA使用全过程
- EIGRP MD5认证实例
- PyQt Graphics View 一个hello world例子
- 接收list参数_Python 犄角旮旯--List
- 【微软的VDI】Windows Server 2012 RDS存储相关
- 用html css设计网站,HTMLCSS构建和设计网站
- Kubernetes的client-go库介绍
- PHP异步调用实现方式