Redis集群简介在哨兵模式下,如果主从master宕机,则通过哨兵选举出新的master。在切换主从选举过程中,整个redis服务不可用。而且哨兵模式只有一个master节点对外提供服务,无法支持更高的并发。此外,主节点的内存设置不宜过大。否则持久化文件会过大,影响数据恢复或主从同步的效率。Redis集群是由一系列主从节点组组成的分布式服务器组,具有复制、高可用、分片等特点。Redis集群可以在没有哨兵哨兵的情况下完成节点移除和故障转移功能。每个节点都需要设置为集群模式。这种集群模式没有中心节点。客户端使用CRC16算法对key进行hash得到一个值来判断key存放在哪个主从服务上,所以即使是某个主从全宕机,redis集群也是部分可用的。方便横向扩展,可根据业务规模随时增减配置。根据官方文档,可以线性扩展到数万个节点(但官方建议不超过1000个节点)。redis集群的性能和高可用优于sentinel模式。Redis集群搭建1.修改redis.conf配置文件daemonizeyes后台启动cluster-enabledyes开启集群模式cluster-config-filenodes-6379.conf集群配置信息存储文件名cluster-node-timeout5000nodeofflinetimelimit,达到设置该值时,发起主从重选。protected-modeno关闭保护模式requirepassxxx设置本地密码masterauthxxx设置访问其他机器的密码无法搭建集群。使用修改后的配置文件启动redis服务。这里我用了三个,一个master一个搭建。因此,首先使用指定的配置文件redis-master.conf启动六个redis服务:src/redis-serverredis-master.conf3.搭建集群服务,最好检查每台机器的redis服务是否正常普通的。启动ps-ef|grepredis,可以看到redis服务进程后面有一个集群标识。正常启动的redis服务是没有这个标识的5.0版本。可以直接使用C语言客户端提供的指令搭建集群:src/redis-cli-axxx--clustercreate--cluster-replicas1192.168.0.67:6379192.168.0.68:6379192.168.0.69:6379192.168.0.70:6379192.168.0.71:6379192.168.0.72:6379-a表示创建集群的密码--cluster配置-cluster-replicas表示每个master有几个slave,上面一共有6个redis节点,所以三主一奴隶将被建造。在执行命令之前,如果你的redis环境之前设置了master-slave或者sentinel,数据不干净可能会报错。最好删除持久化文件,然后flushdb清理之前的脏数据,否则可能会出现如下错误:正常执行会返回一个集群分配计划,我们可以按照它的计划:然后节点开始通信搭建集群,最后我们会看到已经分配了16384个slot,并且可以看到在构建计划中有3个master,每个master都分配了slot。意思是存储的key经过crc16哈希算法后得到的值,在这个范围内,会存储到redis主从上。这就是redis的shardingcluster模式。至此,集群搭建完毕4、集群操作以集群方式连接redis客户端,通过clusterinfo查看集群信息,通过集群节点src/redis-cli-apassword-c查看节点信息集群模式连接我们设置setabc123,会看到一个value客户点会计算abc的slot为7638,然后重定向到对应的master-slavemaster写入数据下面看一下keyvalue计算在java客户端的jedisredis.clients.util.JedisClusterCRC16#getSlot(java.lang.String):最终计算结果会落在0-16383之间。当RedisCluster的客户端连接到集群时,也会得到一份集群的slot配置信息,缓存在客户端本地。这样,当客户端要查找某个key时,可以直接定位到目标节点。同时,由于客户端和服务端的槽位信息可能不一致,因此需要一种修正机制来实现槽位信息的校验和调整。中心化集群和分片集群的Redis节点之间使用gossip协议进行通信,各个节点之间会相互通信。八卦协议包含各种消息,包括ping、pong、meet、fail等等。ping:每个节点都会频繁的向其他节点发送ping,包括自己的状态和自己维护的集群元数据,通过ping交换元数据;pong:返回ping和meet,包括自身的状态等信息,也可用于信息的广播和更新;fail:一个节点判断另一个节点发生故障后,向其他节点发送fail,通知其他节点指定节点宕机。meet:节点向新加入的节点发送meet,让新节点加入集群,然后新节点开始与其他节点通信,而无需发送组成网络所需的所有CLUSTERMEET命令。发送CLUSTERMEET消息以便每个节点都可以到达每个其他节点只需要经过一个已知的节点链。由于八卦消息是在心跳包中交换的,因此将创建节点之间的丢失链接。gossip协议的优点是元数据的更新比较分散,而不是集中在一个地方,更新请求会依次发送到所有节点进行更新,有一定的延迟,减轻了压力;缺点是元数据更新有延迟,可能会导致集群的某些操作有些滞后。就是自己提供的服务的端口号+10000,比如6379,那么节点间通信就使用16379端口。每个节点每隔一段时间向其他几个节点发送ping消息,其他节点收到ping消息后返回pong消息。还有一个集中的。比如ZK集群的中心点就在于数据的更新和读取。时效性非常好。一旦元数据发生变化,会立即更新到中心化(master)存储中,其他节点读取后可立即感知;缺点是所有的元数据更新压力都集中在一个地方,可能导致元数据存储压力。Redis集群选举机制当slave发现自己的master变为FAIL状态时,会尝试发起选举,以期成为新的master。由于挂掉的master可能有多个slave,所以有一个多个slave竞争成为master节点的过程。过程如下:1.slave发现自己的master变成FAIL2.自己记录的集群currentEpoch(选举轮次标记)加1,向集群内其他节点广播信息3.其他节点收到信息,只有master响应,判断请求者的合法性,并发送结果4.尝试选举的slave收集master返回的结果,收到超过半数master统一后,成为新的大师5。广播Pong消息以通知其他集群节点。如果本次选举不成功,比如由A、B、C三个小主从组成的集群,A的master挂了,A的两个弟弟发起选举。结果B的master投票给A1,C的弟弟Master投票给A的弟弟A2,会发起第二次选举,选举轮次标记+1会继续上面的过程。实际上,从节点并不会在主节点一进入FAIL状态就尝试发起选举,而是有一定的延迟。一定的延迟确保我们等待FAIL状态在集群中传播。如果从节点立即尝试选举,其他主节点可能不知道它的FAIL状态,可能会拒绝投票。同时,下面公式中的随机数也可以有效防止slaves同时发起选举,导致平票。延迟计算公式:DELAY=500ms+random(0~500ms)+SLAVE_RANK*1000msSLAVE_RANK表示本slave从master复制的数据总量的rank。Rank越小,复制的数据越新。这样,拥有最新数据的slave会最先发起选举(理论上)。前面说过,这种分片集群模式集群可以部分提供服务。当redis.conf的配置cluster-require-full-coverage为no时,表示当一个小master-slave整体挂掉时集群也可以使用。也就是说,在0-16383这个slot中,落在master-slave对应的slot上的key是不能使用的,但是落在其他范围内的key还是可以使用的。
