redis集群下一些问题和原理

目前六个节点,三主三从

测试目标如下:

down掉一个主节点,看是否slave能否升为master

  • down掉一个主节点,如果其有备份节点则slave会向其他master发起FAILOVER_AUTH_REQUEST消息发起竞选。
  • master收到之后回复FAILOVER_AUTH_ACK消息告知自己是否同意改slave成为新的master。
    slave B升为master后,再把之前的master A恢复,会如何
  • 当slave收到超过半数的master的同意回复时,该slave梳理替代A成为新的master。
  • 此时它会以最新的epoch通过PONG消息广播自己成为master的信息,让集群中的其他节点尽快的更新拓扑信息。
  • 当之前的master A恢复可用后,它首先认为自己是master,但逐渐通过Gossip协议得知slave B已经替代自己的事实后,就降级为B的slave
    同时断掉master和slave(如果是五主五从情况呢)
    同时断掉,因为master管理的哈希槽没有分配,则会造成整个集群fail不可用
    新增或删除一对master和slave,哈希槽如何分配
    新增一个master:
  1. redis-trib.rb add-node 要增加的节点ip:port 集群中的任意节点ip:port
    分配哈希槽:
  2. redis-trib.rb reshard 要增加的节点ip:port
    How many slots do you want to move (from 1 to 16384)? 1000
    //想要移动多少个hash slot?(分配给新节点)

What is the receiving node ID? 8326ff0be199fa0d4db74f0ebcc58f27e65991b4
//接受的节点ID是什么?(新加节点的ID)

Please enter all the source node IDs.

Type 'all' to use all the nodes as source nodes for the hash slots.
//如果从所有节点移动,输入all

Type 'done' once you entered all the source nodes IDs.
//输入指定节点ID,done结尾

删除一个master:

  1. 首先要移除master上的slots
    redis-trib.rb reshard 要移除的节点ip:port
    How many slots do you want to move (from 1 to 16384)? 4000
    What is the receiving node ID? 30ca062e743081eb94a7270a154a4fd01eb06d6b //接收的节点id
    Please enter all the source node IDs.
    Type 'all' to use all the nodes as source nodes for the hash slots.
    Type 'done' once you entered all the source nodes IDs.
    Source node #1:c2015e7550c5f9a65167000303f524728d921998 //要删除的节点id
    Source node #2:done
    //done表示结束
    注,如果此master有slave,在移除master的slots后,slave会副本迁移成为别人的slave

  2. redis-trib.rb del-node 要删除的节点ip:port 节点的id

  • 注,每移除master的slots,集群都会保存移除后的状态(就算这个节点删除)。
  • 如果用redis-trib.rb check 这个节点 查询集群的话,会显示当时保存的状态,
    但如果对其做reshard或其他操作,会报不知道这个node的错误
    移除一个哈希槽或者有哈希槽没有分配,会发生什么情况
    集群会处于fail不可用状态
    一个master多个slave,如何配置,并且master挂掉之后,选举优先级
  • 可以通过redis-trib.rb add-node --slave slave地址:port master地址:port 增加从节点
  • 如果master有多个slave,当master挂掉之后,选举的优先级:
    优先级最重要的决定因素是slave最后一次同步master信息的时间,越新表示这个slave数据越新,竞选优先级越高
    创建集群时是否能显示的指定某台机器是master,某台机器是slave
    可以指定master:
    redis-trib.rb create --replicas 0 ip:port ip:port ip:port
    --replicas 0表示没有slave
    --replicas 1表示至少一个slave,集群至少需要6个节点
    --replicas 2表示至少两个slave,集群至少需要9个节点

然后创建slave指向master:
redis-trib.rb add-node --slave slave地址:port master地址:port
slave机器是否能读写

  • 默认情况下,只有master能读写。
  • 即使将读写请求直接发送到slave上,也会重定向到master进行操作。
  • 不过,redis-cluster有READONLY命令,在slave上执行此命令后,可以在slave上进行 读,不会重定向。(但是写也要重定向)
  • 如果要取消READONLY模式,则在slave上执行READWRITE命令恢复默认。
    集群环境下,客户端如jedisCluster需要配置所有master和slave的ip还是有个类似公共入口
  • 在jedisCluster初始化的时候,有一个set放了所有节点ip和端口。
  • 然后jedisCluster会获取节点对应的slots和集群信息。
    此时,遍历set,但是源码中在for循环时有个break,也就是只取了第一个节点。
  • 也就是jedisCluster默认会取第一个节点获取集群节点信息和对应的slots,此时如果第一个节点挂掉致,则抛出异常,在catch{}中没有代码,也就是继续用下一个节点来获取信息
  • 参考:https://blog.csdn.net/javaloveiphone/article/details/53187314
    image

集群下,客户端读写时,jedisCluster是如何选择在哪一个节点上操作的?

  • 在初始化集群的时候,会获取集群节点和对应的slots信息放入JedisClusterInfoCache中
  • 在set或者get的时候,会使用JedisClusterCRC16对key进行hash计算,然后从缓存中判断属于哪一个节点(master),然后连接此节点进行操作
    对key进行CRC16(key)计算,获取对应的slots image 从缓存中获取此key对应的slots在哪一个节点上,然后返回connection image

集群下,客户端读写时,如果数据不在当前节点上,是如何处理的?客户端主动转发,还是需要人工切换节点
如果是通过redis-cli -h 127.0.0.1 -p 6379这种连接的,当put或get时,如果不在本节点上,会返回一个(error) MOVED 6935 172.17.0.1:7011
如果是通过redis-cli -c -h 127.0.0.1 -p 6379加上-c参数连接时,当put或get时,如果不在本节点上,会自动重定向到正确节点,并且进行put或get操作,Redirected to slot [6935] located at 172.17.0.1:7011
redis集群总线是什么,有什么作用

  • 每个redis集群节点都需要2个TCP连接:
    其中一个用于和客户端交互,如:6379。
    另一个是集群总线端口,用于集群节点之间通信,如:16379
    一般集群总线端口是客户端端口+偏移量10000
  • 集群总线端口是使用使用二进制协议即Gossip的节点到节点通信通道

redis集群中的主从复制原理
全量同步:
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:

  • 从服务器连接主服务器,发送SYNC命令;
  • 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
  • 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
  • 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
  • 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
  • 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
    image

增量同步:

  • Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
  • 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

Redis主从同步策略:

  • 主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。

redis策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。

redis-cluster的单点保护是什么?
如果master A有一个slave,master B有两个slave。
A的slave挂掉后,A就成为单机,如果A再次挂掉则将造成集群不可用。
此时redis-cluster会将B的某个slave进行副本迁移,让其变成A的slave
如A有A1这个slave,B有B1,B2两个slave

image

假设A1发生宕机,结构变成下面这样:

image

此时A变成单点,如果A在挂掉,则集群不可用,所以redis-cluster会将B1进行副本迁移,变成A的slave,结构如下:

image

集群中只需要保持2master+1*个节点,就可以保持任意节点宕机时,故障转移后继续高可用

spring在redis集群下可以只配置一个IP还是必须多个IP,原理是怎么样的?
在使用redis-trib.rb创建集群的时候,怎么样设置集群密码?
在优化redis工具包代码时,使用动态代理优化代码,减少各种判断和try{}catch{}?

posted @ 2019-05-17 14:20  望着月亮哭泣的猪  阅读(208)  评论(0)    收藏  举报