Redis系列之主从复制

Posted 老程不秃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis系列之主从复制相关的知识,希望对你有一定的参考价值。

主从复制

基本介绍

Redis支持主从复制功能,可以通过执行slaveof(Redis5版本以后改成replicaof)或者在配置文件中设置slaveof(Redis5版本以后改成replicaof)来开启复制功能。

  • 一主两丛

  • 一主多从

主从基本配置

主Redis配置

主Redis配置基本不用修改,重点部分在从Redis配置

从Redis配置

1、复制一份redis.conf文件

2、相关配置修改

# salve的端口号
port 6380 

#把pid进程号写入pidfile配置的文件
pidfile /var/run/redis_6380.pid 

logfile "6380.log"  

#指定数据存放目录
dir /usr/local/redis‐5.0.3/data/6380 

#需要注释掉bind
#bind127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)
复制代码

3、配置主从复制

#从本机master6379的redis实例复制数据,Redis5.0之前使用slaveof
replicaof 192.168.0.60 6379

#配置从节点只读
replica‐read‐only yes
复制代码

4、启动从节点

redis‐server redis.conf
复制代码

5、连接从节点

redis‐cli ‐p 6380
复制代码

6、测试在6379实例上写数据,6380实例是否能及时同步新修改数据

docker run  --name redis-6381 -v /Users/yujiale/docker/redis/conf/redis6381.conf:/etc/redis/redis.conf -v /Users/yujiale/docker/redis/conf/sentinel6381.conf:/etc/redis/sentine.conf -v /Users/yujiale/docker/redis/data6381:/data --network localNetwork --ip 172.172.0.14 -p 16381:6379 -d redis:6.2.6 redis-server /etc/redis/redis.conf --appendonly yes
复制代码

主从配置的作用

读写分离

  • 一主多从,主从同步
  • 主负责写,从负责读
  • 提升Redis的性能和吞吐量
  • 主从的数据一致性问题

数据容灾

  • 从机是主机的备份
  • 主机宕机,从机可读不可写
  • 默认情况下主机宕机后,从机不可为主机利用
  • 哨兵可以实现主从切换,做到高可用

Redis主从工作原理

主从复制之全量复制

只有第一次从Redis连接主Redis时发生的是全量复制,如果是短点续传可能是全量复制,也可能是部分复制。

  • 流程图

1、与主Redis建立Socker长连接

slaver与master建立socket连接

slaver关联文件事件处理器

  • 该处理器接收RDB文件(全量复制)、接收Master传播来的写命令(增量复制)

  • 主服务器accept从服务器Socket连接后,创建相应的客户端状态。相当于从服务器是主服务器的Client端。

  • 发送ping命令

    • Slaver向Master发送ping命令

      • 1、检测socket的读写状态

      • 2、检测Master能否正常处理

    • Master的响应:

      • 1、发送“pong” ,说明正常

      • 2、返回错误,说明Master不正常

      • 3、timeout,说明网络超时

  • 权限验证

主从正常连接后,进行权限验证

主未设置密码(requirepass=“”),从也不用设置密码(masterauth=“”)

主设置密码(requirepass!=""),从需要设置密码(masterauth=主的requirepass的值)

或者从通过auth命令向主发送密码

2、主Redis接收到PSYNC命令

主Redis接收到PSYNC命令后执行bgsave命令会生成最新的rdb快照,

3、主Redis把rdb快照发送给从Redis

主Redis发送rdb快照给从Redis时,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中存储到relp buffer缓存中

  • 同步快照阶段:Master创建并发送快照RDB给Slave,Slave载入并解析快照。Master同时将此阶段所产生的新的写命令存储到缓冲区。

4、从节点接收到rdb快照

从节点接收到rdb快照后清空老数据,并加载rdb文件

5、主Redis发送buffer缓存文件到从Redis

同步写缓冲阶段:Master向Slave同步存储在缓冲区的写操作命令。

6、从节点接收buffer缓存文件

从节点接收buffer缓存文件,并加载buffer缓存文件到内存中

7、主Redis通过Socker长连接连续把命令发送到从节点

从Redis接收到主Redis发送过来的命令,执行当前命令

总述

如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个PSYNC命令给master请求复制数据。master收到PSYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

主从复制之部分复制

大体流程跟全量复制差不多,就不过多讲解

简述

当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。主从复制(部分复制,断点续传)流程图:

主从复制之增量同步

  • Redis增量同步主要指Slave完成初始化后开始正常工作时,Master发生的写操作同步到Slave的过程。

  • 通常情况下,Master每执行一个写命令就会向Slave发送相同的写命令,然后Slave接收并执行。

主从复制之心跳检测

1.检测主从的连接状态

检测主从服务器的网络连接状态通过向主服务器发送INFO replication命令,可以列出从服务器列表,可以看出从最后一次向主发送命令距离现在过了多少秒。lag的值应该在0或1之间跳动,如果超过1则说明主从之间的连接有故障。

2.辅助实现min-slaves

Redis可以通过配置防止主服务器在不安全的情况下执行写命令min-slaves-to-write 3(min-replicas-to-write 3)min-slaves-max-lag 10(min-replicas-max-lag 10)上面的配置表示:从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器将拒绝执行写命令。这里的延迟值就是上面INFOreplication命令的lag值。

3.检测命令丢失

如果因为网络故障,主服务器传播给从服务器的写命令在半路丢失,那么当从服务器向主服务器发送REPLCONF ACK命令时,主服务器将发觉从服务器当前的复制偏移量少于自己的复制偏移量,然后主服务器就会根据从服务器提交的复制偏移量,在复制积压缓冲区里面找到从服务器缺少的数据,并将这些数据重新发送给从服务器。(补发)网络不断增量同步:网断了,再次连接时

如何判断全量复制还是部分复制

客户端发送saveof后主节点会判断是否第一次复制,如果是则进行全量复制,如果不是通过runid offset偏移量进行判断是否一致,如果一致则进行部分复制,否则进行全量复制。

redis系列之主从复制与哨兵机制

1. 绪言

  在现实应用环境中,出于数据容量、容灾、性能等因素的考虑,往往不会只使用一台服务器,而是使用集群的方式。Redis 中也有类似的维持一主多从的方式提高 Redis 集群的高可用性的方案,而其中不可避免的则是如何保证主从实例间的数据一致性,复制(Replication)是其解决办法。本篇介绍redis的主从复制及哨兵机制。

2. redis主从复制

2.1 主从拓扑

  Redis 支持简单且易用的主从复制(master-slave replication)功能, 这一功能可以让从服务器(slave server)成为主服务器(master server)的精确复制品,实现了数据的备份。一个主服务器可以有多个从服务器,而且不仅主服务器可以有从服务器, 从服务器也可以有自己的从服务器, 多个从服务器之间可以构成一个图状结构。
下图为redis多种主从模式的拓扑结构:
1)一主一从:

  这一拓扑结构主要用于主节点故障转移从节点,当主节点的“写”命令并发高且需要持久化,可以只在从节点开启AOF(主节点不需要),这样即保证了数据的安全性,也避免持久化对主节点的影响
2)一主多从:

  这一结构主要针对“读”较多的场景,“读”由多个从节点来分担,但节点越多,主节点同步到多节点的次数也越多,影响带宽,也加重主节点的稳定。
3)树状主从

  这一拓扑结构是对一主多从的补充,主节点只推送一次数据到slave1和slave2,再由从slave2推送到slave3和 slave4,减轻主节点推送的压力。

2.2 配置

  我在virtualBox上配置了4服务器,机器名分别为chb、chb1、chb2、chb3,ip地址如图所示,且都已经安装配置好了redis数据库。我们要将chb设为主服务器,其他三台配置为从服务器,该如何配置呢?

  Redis主从服务器配置有一条规律叫做“配主不配从”,也就是说,进行主从服务器配置时,对于主服务器,我们不需要进行配置,只要配置从服务器即可。所以,在上图的4台机器中,我们只需要对chb1、chb2、chb3进行配置即可。出于安全考虑,在配置前,我们在系统根目录下新建一个myredis目录,并将redis的配置文件(redis.conf)拷贝一份到该目录下,本篇主从复制操作我们主要基于该配置文件进行(当然你也可以直接在安装目录配置下进行,非硬性要求)。对从服务器(chb1、chb2、chb3)刚拷贝好的配置文件添加如下配置:

slaveof 192.168.56.100 6379

  也就是:slaveof 主服务器ip 端口号。

  然后修改配置中的bind属性,bind属性默认绑定127.0.0.1,如果redis主服务器绑定了127.0.0.1,那么跨服务器IP的访问就会失败,从服务器用IP和端口访问主的时候,主服务器发现本机6379端口绑在了127.0.0.1上,也就是只能本机才能访问,外部请求会被过滤,这是Linux的网络安全策略管理的。所以我们要进行修改(注:为方便下面的哨兵部分内容测试,4台服务器都要修改):

bind 0.0.0.0

  这是在测试环境上的配置,如果在生产环境中,就要绑定主服务器的实际ip和端口。

  然后如下图所示,我们分别启动了4台服务器上的redis:


  然后,可以通过info replication命令查看主从信息:

  可以看到,chb(主服务器)上有了3台从服务器,在从服务器(chb1、chb2、chb3)上可以看到从属于chb。
上面使用的是在配置文件中进行主从服务器配置,还有一种方法就是通过命令行的方式配置,这种方式直接在从服务器上运行命令slaveof 192.168.56.100 6379就可以了(当然,也要去配置文件中修改bind属性)。通过命令行的方式修改是一次性的,也就是说,当redis服务关闭后,下次重启就无效了。

2.3 功能

  主从复制有什么作用呢?
  第一:容灾恢复。当主服务器发生故障时,从服务器还有数据备份,亦可转换为主服务器使用。
  我们尝试分别在主从服务器上分别进行数据操作:

  我们现在chb主服务器上新建了k1、k2,然后分别在三台从服务器上获取k1、k2的值,发现时可以成功获取的。证明从服务器可以成功复制主服务器上的数据,而且复制的是主服务器上的所有数据,可不单单是主从关系建立之后才新建的数据。
  第二:读写分离。对于读占比较高的场景,可以通过把一部分流量分摊导出从服务器 来减轻主主服务器压力,同时需要主要只对主节点执行写操作。

  如上图所示,只能在主服务器上进行写操作,在从服务器上的写操作都失败了,这就实现了读写分离。

3. 哨兵(sentinel)

  上面说到容灾恢复是提到主服务器出现故障(宕机)或者关机时,从服务器可以转换成主服务器来用,从服务器怎么结束之前的主从关系,转换为主服务器呢?

slaveof no one

  如上图所示,我们先把chb主服务器上的redis服务关闭,然后在chb1上执行slaveof no one
命令,可以看到,chb1已经变成了master,chb2和chb3还是从属于之前的chb。如果我们现在想要chb2和chb3从属于chb1,就需要重新进行配置。
但是,在实际生产环境中,不可能时时刻刻都人为得进行监控主服务器是否正常工作,所以,主服务器如果发生故障,最好让服务器自动完成主从转换,并修改其他从服务器的从属。这就涉及到redis的哨兵(sentinel)了。

3.1 Sentinel的主要任务

  Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
  1)监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  2)提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  3)自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
  Redis Sentinel 是一个分布式系统, 我们可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

3.2 配置sentinel

  在chb、chb1、chb2三台服务器/myredis目录下新建一个名为sentinel.conf的文件,并在文件中输入一下内容:

#哨兵端口 
port 26379
#2表示在sentinel集群中最少需要有两个节点检测到redis主节点出故障就进行主从切换
sentinel monitor mymaster
192.168.56.100 6379 2

#如果3s内mymaster无响应,则认为mymaster宕机了
sentinel down-after-milliseconds mymaster 3000
#如果10秒后,mysater仍没活过来,则启动failover
sentinel failover
-timeout mymaster 10000

#后台执行
daemonize yes
#指定工作目录
dir
"/myredis"

protected-mode no
#制定日志文件
logfile
"/myredis/sentinel.log"
#redis主节点密码,本篇中并未对主服务器设置密码,故省略 #sentinel auth
-pass mymaster 123456

  第一行配置指示 Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的 IP 地址为 192.168.56.100 , 端口号为 6379 , 而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。

  不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效, 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持, 才能发起一次自动故障迁移。换句话说, 在只有少数(minority) Sentinel 进程正常运作的情况下, Sentinel 是不能执行自动故障迁移的。
  上述配置中各个选项的功能如下:
down-after-milliseconds 选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN,指的是单个 Sentinel 实例对服务器做出的下线判断 )。
  不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ,指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断), 这时自动故障迁移才会执行。将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。
  parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长。

3.3 启动 Sentinel

  对于 redis-sentinel 程序, 你可以用以下命令来启动 Sentinel 系统:

redis-sentinel /path/to/sentinel.conf

  对于 redis-server 程序, 你可以用以下命令来启动一个运行在 Sentinel 模式下的 Redis 服务器:

redis-server /path/to/sentinel.conf --sentinel

  两种方法都可以启动一个 Sentinel 实例。

  启动sentinel后,还要一次启动个服务器的redis服务,然后我们再次查看主从关系如下图所示:



  同时,我们也可以在日志文件/myreids/sentinel.log中查看到信息:

2057:X 01 Dec 2018 10:43:57.026 * +slave slave 192.168.56.101:6379 192.168.56.101 6379 @ mymaster 192.168.56.100 6379
2057:X 01 Dec 2018 10:44:17.115 * +slave slave 192.168.56.102:6379 192.168.56.102 6379 @ mymaster 192.168.56.100 6379
2057:X 01 Dec 2018 10:44:37.166 * +slave slave 192.168.56.103:6379 192.168.56.103 6379 @ mymaster 192.168.56.100 6379

  哨兵日志说明主从关系已建立。

  然后我们关闭chb(主服务器)上的reids服务,然后在查看主从关系:

  从上图中可以看到,主从关系已经发生了改变,关闭主服务器chb后,chb3变成了主服务器,且chb1和chb2也纷纷开始从属于chb3。那么,如果此时chb又开机上线了,是否会再次变成主服务器呢?

从上图看出,chb就算继续上线,chb3也还是主机,chb1、chb2和新上线的chb都会从属于chb3。

以上是关于Redis系列之主从复制的主要内容,如果未能解决你的问题,请参考以下文章

缓存加速——Redis服务之主从复制哨兵模式群集模式

redis系列之主从复制与哨兵机制

Redis系列之主从复制

Redis系列深入浅出Redis主从复制之读写分离一篇搞懂Redis复制

Redis系列深入浅出Redis主从复制之哨兵模式实践

Spring之redis主从复制(非哨兵模式)