Redis系列五:redis主从复制(replication)、哨兵(sentinel)、集群(cluster)

1、Redis主从复制

主从复制:主节点负责写数据,从节点负责读数据,主节点按期把数据同步到从节点保证数据的一致性node

1. 主从复制的相关操做

  1. 配置主从复制方式1、新增redis6380.conf, 加入 slaveof 192.168.152.128 6379, 在6379启动完后再启6380,完成配置;
  2. 配置主从复制方式2、redis-server --slaveof 192.168.152.128 6379 临时生效
  3. 查看状态:info replication
  4. 断开主从复制:在slave节点,执行6380:>slaveof no one
  5. 断开后再变成主从复制:6380:> slaveof 192.168.152.128 6379
  6. 数据较重要的节点,主从复制时使用密码验证: requirepass
  7. 从节点建议用只读模式slave-read-only=yes, 若从节点修改数据,主从数据不一致 

传输延迟:主从通常部署在不一样机器上,复制时存在网络延时问题,redis提供repl-disable-tcp-nodelay参数决定是否关闭TCP_NODELAY,默认为关闭
参数关闭时:不管大小都会及时发布到从节点,占带宽,适用于主从网络好的场景,
参数启用时:主节点合并全部数据成TCP包节省带宽,默认为40毫秒发一次,取决于内核,主从的同步延迟40毫秒,适用于网络环境复杂或带宽紧张,如跨机房redis

2. Redis主从拓扑

a)一主一从:用于主节点故障转移从节点,当主节点的“写”命令并发高且须要持久化,能够只在从节点开启AOF(主节点不须要),这样即保证了数据的安全性,也避免持久化对主节点的影响 算法

 

b)一主多从:针对“读”较多的场景,“读”由多个从节点来分担,但节点越多,主节点同步到多节点的次数也越多,影响带宽,也加剧主节点的稳定数据库

 

c)树状主从:一主多从的缺点(主节点推送次数多压力大)可用些方案解决,主节点只推送一次数据到从节点B,再由从节点B推送到C,减轻主节点推送的压力。安全

3. 主从复制原理

 

4. 数据同步

redis 2.8版本以上使用psync命令完成同步,过程分“全量”与“部分”复制
全量复制:通常用于初次复制场景(第一次创建SLAVE后全量)
部分复制:网络出现问题,从节点再次链接主节点时,主节点补发缺乏的数据,每次数据增量同步
心跳:主从有长链接心跳,主节点默认每10S向从节点发ping命令,repl-ping-slave-period控制发送频率网络

5. 主从的缺点

a)主从复制,若主节点出现问题,则不能提供服务,须要人工修改配置将从变主
b)主从复制主节点的写能力单机,能力有限
c)单机节点的存储能力也有限并发

6.主从故障如何故障转移

a)主节点(master)故障,从节点slave-1端执行 slaveof no one后变成新主节点;
b)其它的节点成为新主节点的从节点,并重新节点复制数据;
c)须要人工干预,没法实现高可用。tcp

2、Redis哨兵机制(Sentinel)

1. 为何要有哨兵机制?

       哨兵机制的出现是为了解决主从复制的缺点的分布式

2. 哨兵机制(sentinel)的高可用

  原理:当主节点出现故障时,由Redis Sentinel自动完成故障发现和转移,并通知应用方,实现高可用性。函数

其实整个过程只须要一个哨兵节点来完成,首先使用Raft算法(选举算法)实现选举机制,选出一个哨兵节点来完成转移和通知

3. 哨兵的定时监控任务

任务1:每一个哨兵节点每10秒会向主节点和从节点发送info命令获取最拓扑结构图,哨兵配置时只要配置对主节点的监控便可,经过向主节点发送info,获取从节点的信息,并当有新的从节点加入时能够立刻感知到

任务2:每一个哨兵节点每隔2秒会向redis数据节点的指定频道上发送该哨兵节点对于主节点的判断以及当前哨兵节点的信息,同时每一个哨兵节点也会订阅该频道,来了解其它哨兵节点的信息及对主节点的判断,其实就是经过消息publish和subscribe来完成的

 任务3:每隔1秒每一个哨兵会向主节点、从节点及其他哨兵节点发送一次ping命令作一次心跳检测,这个也是哨兵用来判断节点是否正常的重要依据

客观下线:当主观下线的节点是主节点时,此时该哨兵3节点会经过指令sentinel is-masterdown-by-addr寻求其它哨兵节点对主节点的判断,当超过quorum(选举)个数,此时哨兵节点则认为该主节点确实有问题,这样就客观下线了,大部分哨兵节点都赞成下线操做,也就说是客观下线

 

4. 领导者哨兵选举流程

a)每一个在线的哨兵节点均可以成为领导者,当它确认(好比哨兵3)主节点下线时,会向其它哨兵发is-master-down-by-addr命令,征求判断并要求将本身设置为领导者,由领导者处理故障转移;
b)当其它哨兵收到此命令时,能够赞成或者拒绝它成为领导者;
c)若是哨兵3发现本身在选举的票数大于等于num(sentinels)/2+1时,将成为领导者,若是没有超过,继续选举…………

 

5. 故障转移机制

a)由Sentinel节点按期监控发现主节点是否出现了故障

sentinel会向master发送心跳PING来确认master是否存活,若是master在“必定时间范围”内不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地(单方面地)认为这个master已经不可用了

 

 

 b) 当主节点出现故障,此时3个Sentinel节点共同选举了Sentinel3节点为领导,负载处理主节点的故障转移

 

 c) 由Sentinel3领导者节点执行故障转移,过程和主从复制同样,可是自动执行

 

 流程:

    1. 将slave-1脱离原从节点,升级主节点,

         2. 将从节点slave-2指向新的主节点

         3. 通知客户端主节点已更换

         4. 将原主节点(oldMaster)变成从节点,指向新的主节点

 d) 故障转移后的redis sentinel的拓扑结构图

6. 哨兵机制-故障转移详细流程-确认主节点

a) 过滤掉不健康的(下线或断线),没有回复过哨兵ping响应的从节点

b) 选择salve-priority从节点优先级最高(redis.conf)的

c) 选择复制偏移量最大,指复制最完整的从节点

7. 实战:如何安装和部署哨兵

以3个Sentinel节点、2个从节点、1个主节点为例进行安装部署

1. 前提:先搭好一主两从redis的主从复制,和以前的主从复制搭建同样,搭建方式以下:

  A)主节点6379节点(/usr/local/bin/conf/redis6379.conf):

    修改 requirepass 12345678,注释掉#bind 127.0.0.1

  B) 从节点redis6380.conf和redis6381.conf: 配置都同样

 

    修改 requirepass 12345678 ,注释掉#bind 127.0.0.1, 

    加上访问主节点的密码masterauth 12345678 ,加上slaveof 192.168.152.128 6379

    注意当主从起来后,主节点可读写,从节点只可读不可写

2. redis sentinel哨兵机制核心配置(也是3个节点):

       /usr/local/bin/conf/sentinel_26379.conf  

       /usr/local/bin/conf/sentinel_26380.conf

       /usr/local/bin/conf/sentinel_26381.conf

将三个文件的端口改为: 26379   26380   26381

而后:sentinel monitor mymaster 192.168.152.128 6379 2  //监听主节点6379

      sentinel auth-pass mymaster 12345678     //链接主节点时的密码

三个配置除端口外,其它同样。

3. 哨兵其它的配置:只要修改每一个sentinel.conf的这段配置便可:

sentinel monitor mymaster 192.168.152.128 6379 2  

//监控主节点的IP地址端口,sentinel监控的master的名字叫作mymaster,2表明,当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了

sentinel auth-pass mymaster 12345678  //sentinel连主节点的密码

sentinel config-epoch mymaster 2  //故障转移时最多能够有2从节点同时对新主节点进行数据同步

sentinel leader-epoch mymaster 2

sentinel failover-timeout mymasterA 180000 //故障转移超时时间180s,                            

a,若是转移超时失败,下次转移时时间为以前的2倍;

b,从节点变主节点时,从节点执行slaveof no one命令一直失败的话,当时间超过180S时,则故障转移失败

c,从节点复制新主节点时间超过180S转移失败

sentinel down-after-milliseconds mymasterA 300000//sentinel节点按期向主节点ping命令,当超过了300S时间后没有回复,可能就认定为此主节点出现故障了……

sentinel parallel-syncs mymasterA 1 //故障转移后,1表明每一个从节点按顺序排队一个一个复制主节点数据,若是为3,指3个从节点同时并发复制主节点数据,不会影响阻塞,但存在网络和IO开销

4. 启动redis服务和sentinel服务:

a)先把以前安装的redis里面的标绿色的文件都拷贝到 usr/local/bin目录下,而后再再bin目录下新建一个conf文件夹存放配置好的redis主从配置文件和哨兵配置文件

b)启动主从复制服务,先启动主再启动从

主:./redis-server conf/redis6379.conf &

从:

  ./redis-server conf/redis6380.conf &

  ./redis-server conf/redis6381.conf &      

 

c)启动sentinel服务:

       ./redis-sentinel conf/sentinel_26379.conf &

       ./redis-sentinel conf/sentinel_26380.conf &

     

 ./redis-sentinel conf/sentinel_26381.conf &

到此服务所有启动完毕

 

链接到6379的redis的服务,可看到6379就是主节点,他有6380和6381两个从节点

5. 测试:kill -9 6379  杀掉6379的redis服务

能够看到杀掉6379之后6380变为了主节点,6381变为了6380的从节点

从新启动6379之后变为6380的从节点

看日志是分配6380 是6381的主节点,当6379服务再启动时,已变成从节点

假设6380升级为主节点:进入6380>info replication     能够看到role:master

打开sentinel_26379.conf等三个配置,sentinel monitor mymaster 192.168.152.128 6380 2

打开redis6379.conf等三个配置, slaveof 192.168.152.128 6380,也变成了6380

注意:生产环境建议让redis Sentinel部署到不一样的物理机上。

8.部署建议

a,sentinel节点应部署在多台物理机(线上环境)

b,至少三个且奇数个sentinel节点

c,经过以上咱们知道,3个sentinel可同时监控一个主节点或多个主节点

    监听N个主节点较多时,若是sentinel出现异常,会对多个主节点有影响,同时还会形成sentinel节点产生过多的网络链接,

    通常线上建议仍是, 3个sentinel监听一个主节点

3、redis集群

Redis集群的概念:

  RedisCluster是redis的分布式解决方案,在3.0版本后推出的方案,有效地解决了Redis分布式的需求,当一个服务挂了能够快速的切换到另一个服务,当遇到单机内存、并发等瓶颈时,可以使用此方案来解决这些问题。

一、分布式数据库

 1)分布式数据库把整个数据按分区规则映射到多个节点,即把数据划分到多个节点上,每一个节点负责总体数据的一个子集。好比咱们库有900

2)分区规则

常见的分区规则哈希分区和顺序分区,redis集群使用了哈希分区,顺序分区暂用不到,不作具体说明;

   rediscluster采用了哈希分区的“虚拟槽分区”方式(哈希分区分节点取余、一致性哈希分区和虚拟槽分区),其它两种也不作介绍,有兴趣能够百度了解一下

3) 虚拟槽分区(槽:slot)

   RedisCluster采用此分区,全部的键根据哈希函数(CRC16[key]&16383)映射到0-16383槽内,共16384个槽位,每一个节点维护部分槽及槽所映射的键值数据

   哈希函数: Hash()=CRC16[key]&16383 按位与

   槽与节点的关系以下

redis用虚拟槽分区缘由:解耦数据与节点关系,节点自身维护槽映射关系,分布式存储

4)redisCluster的缺陷

a,键的批量操做支持有限,好比mset, mget,若是多个键映射在不一样的槽,就不支持了 

b,键事务支持有限,当多个key分布在不一样节点时没法使用事务,同一节点是支持事务

c,键是数据分区的最小粒度,不能将一个很大的键值对映射到不一样的节点

d,不支持多数据库,只有0,select 0

e,复制结构只支持单层结构,不支持树型结构。

 

二、集群节点之间的通讯

 1) 节点之间采用Gossip协议进行通讯,Gossip协议就是指节点彼此之间不断通讯交换信息

 

当主从角色变化或新增节点,彼此经过ping/pong进行通讯知道所有节点的最新状态并达到集群同步

 2)Gossip协议

Gossip协议的主要职责就是信息交换,信息交换的载体就是节点之间彼此发送的Gossip消息,经常使用的Gossip消息有ping消息、pong消息、meet消息、fail消息

 

meet消息:用于通知新节点加入,消息发送者通知接收者加入到当前集群,meet消息通讯完后,接收节点会加入到集群中,并进行周期性ping pong交换

ping消息:集群内交换最频繁的消息,集群内每一个节点每秒向其它节点发ping消息,用于检测节点是在在线和状态信息,ping消息发送封装自身节点和其余节点的状态数据;

pong消息,当接收到ping meet消息时,做为响应消息返回给发送方,用来确认正常通讯,pong消息也封闭了自身状态数据;

fail消息:当节点断定集群内的另外一节点下线时,会向集群内广播一个fail消息,

3) 消息解析流程

全部消息格式为:消息头、消息体,消息头包含发送节点自身状态数据(好比节点ID、槽映射、节点角色、是否下线等),接收节点根据消息头能够获取到发送节点的相关数据。

消息解析流程:

 

 

 

4) 选择节点并发送ping消息:

  Gossip协议信息的交换机制具备自然的分布式特性,但ping pong发送的频率很高,能够实时获得其它节点的状态数据,但频率高会加剧带宽和计算能力,所以每次都会有目的性地选择一些节点; 可是节点选择过少又会影响故障判断的速度,redis集群的Gossip协议兼顾了这二者的优缺点,看下图:

 

不难看出:节点选择的流程能够看出消息交换成本主要体如今发送消息的节点数量和每一个消息携带的数据量

流程说明:

A,选择发送消息的节点数量:集群内每一个节点维护定时任务默认为每秒执行10次,每秒会随机选取5个节点,找出最久没有通讯的节点发送ping消息,用来保证信息交换的随机性,每100毫秒都会扫描本地节点列表,若是发现节点最近一次接受pong消息的时间大于cluster-node-timeout/2 则马上发送ping消息,这样作目的是防止该节点信息太长时间没更新,当咱们宽带资源紧张时,在可redis.conf将cluster-node-timeout 15000  改为30秒,但不能过分加大

B,消息数据:节点自身信息和其余节点信息

三、redis集群扩容

这也是分布式存储最多见的需求,当咱们存储不够用时,要考虑扩容

扩容步骤以下:

A. 准备好新节点

B. 加入集群,迁移槽和数据

1) 同目录下新增redis6382.conf、redis6392.conf两个redis节点

启动两个新redis节点

./redis-server clusterconf/redis6382.conf &  (新主节点)

./redis-server clusterconf/redis6392.conf &   (新从节点)

2) 新增主节点

 ./redis-trib.rb add-node 192.168.152.128:6382 192.168.152.128:6379  

6379是原存在的主节点,6382是新的主节点

 

3),添加从节点

redis-trib.rb add-node --slave --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2 192.168.152.128:6392 192.168.152.128:6379  

    --slave,表示添加的是从节点

    --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2表示主节点6382的master_id

    192.168.152.128:6392,新从节点

    192.168.152.128:6379集群原存在的旧节点

 

4) redis-trib.rb reshard 192.168.152.128:6382   //为新主节点从新分配solt

How many slots do you want to move (from 1 to 16384)? 1000 //设置slot数1000

What is the receiving node ID? 464bc7590400441fafb63f2 //新节点node id

Source node #1:all //表示所有节点从新洗牌

新增完毕!

四、集群缩减节点

集群同时也支持节点下线掉,下线的流程以下:

流程说明:

A,肯定下线节点是否存在槽slot,若是有,须要先把槽迁移到其余节点,保证整个集群槽节点映射的完整性;

B,当下线的节点没有槽或自己是从节点时,就能够通知集群内其它节点(或者叫忘记节点),当下线节点被忘记后正常关闭。

删除节点也分两种:

一种是主节点6382,一种是从节点6392。

在从节点6392中,没有分配哈希槽,执行

./redis-trib.rb del-node 192.168.1.111:6392 7668541151b4c37d2d9 有两个参数ip:port  和节点的id。 从节点6392从集群中删除了。

主节点6382删除步骤:

1)./redis-trib.rb reshard 192.168.1.111:6382

  问咱们有多少个哈希槽要移走,由于咱们这个节点上刚分配了1000 个因此咱们这里输入1000

2)最后

./redis-trib.rb del-node 192.168.1.111:6382 3e50c6398c75e0088a41f908071c2c2eda1dc900

此时节点下线完成……

五、故障转移

redis集群实现了高可用,当集群内少许节点出现故障时,经过故障转移能够保证集群正常对外提供服务。

当集群里某个节点出现了问题,redis集群内的节点经过ping pong消息发现节点是否健康,是否有故障,其实主要环节也包括了 主观下线和客观下线;

主观下线:指某个节点认为另外一个节点不可用,即下线状态,固然这个状态不是最终的故障断定,只能表明这个节点自身的意见,也有可能存在误判;

 

 

下线流程:

A,节点a发送ping消息给节点b ,若是通讯正常将接收到pong消息,节点a更新最近一次与节点b的通讯时间;

B,若是节点a与节点b通讯出现问题则断开链接,下次会进行重连,若是一直通讯失败,则它们的最后通讯时间将没法更新;

节点a内的定时任务检测到与节点b最后通讯时间超过cluster_note-timeout时,更新本地对节点b的状态为主观下线(pfail)

客观下线:指真正的下线,集群内多个节点都认为该节点不可用,达成共识,将它下线,若是下线的节点为主节点,还要对它进行故障转移

假如节点a标记节点b为主观下线,一段时间后节点a经过消息把节点b的状态发到其它节点,当节点c接受到消息并解析出消息体时,会发现节点b的pfail状态时,会触发客观下线流程;

当下线为主节点时,此时redis集群为统计持有槽的主节点投票数是否达到一半,当下线报告统计数大于一半时,被标记为客观下线状态。

故障恢复:

故障主节点下线后,若是下线节点的是主节点,则须要在它的从节点中选一个替换它,保证集群的高可用;转移过程以下:

 

1,资格检查:检查该从节点是否有资格替换故障主节点,若是此从节点与主节点断开过通讯,那么当前从节点不具体故障转移;

2,准备选举时间:当从节点符合故障转移资格后,更新触发故障选举时间,只有到达该时间后才能执行后续流程;

3,发起选举:当到达故障选举时间时,进行选举;

4,选举投票:只有持有槽的主节点才有票,会处理故障选举消息,投票过程实际上是一个领导者选举(选举从节点为领导者)的过程,每一个主节点只能投一张票给从节点,当从节点收集到足够的选票(大于N/2+1)后,触发替换主节点操做,撤销原故障主节点的槽,委派给本身,并广播本身的委派消息,通知集群内全部节点。

相关文章
相关标签/搜索