redis集群基础概念
一、概述
Redis3.0版本之后支持Cluster.
1.1、redis cluster的现状
目前redis支持的cluster特性:
1):节点自动发现
2):slave->master 选举,集群容错
3):Hot resharding:在线分片
4):进群管理:cluster xxx
5):基于配置(nodes-port.conf)的集群管理
6):ASK 转向/MOVED 转向机制.
1.2、redis cluster 架构
1)redis-cluster架构图

架构细节:
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
2) redis-cluster选举:容错

(1)集群选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
(2):什么时候整个集群不可用(cluster_state:fail),当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.
b:如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
本文引用于:https://www.cnblogs.com/yuanermen/p/5717885.html
文章简介:
1.安装redis集群详细教程
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Redis集群的概念:
RedisCluster是redis的分布式解决方案,在3.0版本后推出的方案,有效地解决了Redis分布式的需求,当一个服务挂了可以快速的切换到另外一个服务,当遇到单机内存、并发等瓶颈时,可使用此方案来解决这些问题
一、分布式数据库概念
1. 分布式数据库把整个数据按分区规则映射到多个节点,即把数据划分到多个节点上,每个节点负责整体数据的一个子集。比如我们库有900条用户数据,有3个redis节点,将900条分成3份,分别存入到3个redis节点

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,复制结构只支持单层结构,不支持树型结构。
本文引用:https://www.cnblogs.com/leeSmall/p/8414687.html
文章简介:
1.手动搭建redis集群,手动分区,分配槽位
2.自动安装redis集群,同上一篇博客
3.集群扩容,集群节点缩减
----------------------------------------------------------------------------------------------------------------------------------------------------
博客三:
Redis集群是一个distribute、fault-tolerant的Redis实现,主要设计目标是达到线性可扩展性、可用性、数据一致性。
线性拓展 官方推荐最大的节点数量为1000,由于Cluster架构中无Proxy层,Master与Slave之间使用异步replication。
数据一致性 客户端容忍一定程度的数据丢失,集群尽可能保存Client write操作的数据,保证数据一致性。
可用性 Redis集群通过partition来提供一定程度的可用性,当集群中的一部分节点失效或者无法进行通讯时,集群仍可以继续提供服务。这里有两点补充:
- 只要集群中大多数Master可达、且失效的Master至少有一个Slave可达,即集群非Fail状态,集群都是可用的,
- Redis集群的replicas migration机制可以将拥有多个Slave的Master的某个Slave,迁移到没有Slave的Master下,即Slave分布相对平衡,确保Master都有一定数量的Slave备份。

集群节点属性 集群中每个Master node负责存储数据、集群状态,包括slots与nodes对应关系。Master nodes能够自动发现其他nodes,检测failure节点,当某个Master节点失效时,集群能将核实的Slave提升为Master。下图是节点的关联信息,节点定时会将这些信息发送给其他节点:
1fc2412b7429e4ab5d8704fcd39520815ea2727b 10.9.42.37:6103 master - 0 1494082584680 9 connected 10923-13652
08e70bb3edd7d3cabda7a2ab220f2f3610db38cd 10.9.33.204:6202 slave ad1334bd09ee73fdeb7b8f16194550fc2bf3a038 0 1494082586686 8 connected
edaafc250f616e9e12c5182f0322445ea9a89085 10.9.33.204:6203 slave 1fc2412b7429e4ab5d8704fcd39520815ea2727b 0 1494082586184 9 connected
06cd6f24caf98a1c1df0862eadac2b05254f909d 10.9.33.204:6201 slave d458c22ccced2f29358b6e6814a206d08285374e 0 1494082584179 7 connected
3892b7fb410a4d6339364dbdda2ebc666ffee843 10.9.42.37:6203 slave 73f7d44c03ada58bf5adaeb340359e2c043ecfa0 0 1494082582679 12 connected
73f7d44c03ada58bf5adaeb340359e2c043ecfa0 10.9.33.204:6103 master - 0 1494082585181 3 connected 13653-16383
4004a64211bea5050a8f46b8436564d40380cd60 10.9.33.204:6101 master - 0 1494082583678 1 connected 2731-5460
d458c22ccced2f29358b6e6814a206d08285374e 10.9.42.37:6101 master - 0 1494082588189 7 connected 0-2730
f8868d59c0f3d935d3dbe35601506039520f7107 10.9.42.37:6201 slave 4004a64211bea5050a8f46b8436564d40380cd60 0 1494082587187 10 connected
45ba0d6fc3d48a43ff72e10bcc17d2d8b2592cdf 10.9.33.204:6102 master - 0 1494082583179 2 connected 8192-10922
007d7e17bfd26a3c1e21992bb5b656a92eb65686 10.9.42.37:6202 slave 45ba0d6fc3d48a43ff72e10bcc17d2d8b2592cdf 0 1494082588189 11 connected
ad1334bd09ee73fdeb7b8f16194550fc2bf3a038 10.9.42.37:6102 myself,master - 0 0 8 connected 5461-8191
从左至右分别是:节点ID、IP地址和端口,节点角色标志、最后发送ping时间、最后接收到pong时间、连接状态、节点负责处理的hash slot。集群可以自动识别出ip/port的变化,并通过Gossip(最终一致性,分布式服务数据同步算法)协议广播给其他节点知道。Gossip也称“病毒感染算法”、“谣言传播算法”(附录一)。
Keys分布模型 集群的键空间被分割为16384个slots(即hash槽),slot是数据映射的基本单位,即集群的最大节点数量是16384(官方推荐最大节点数量为1000个左右)。集群中的每个Master节点负责处理16384个hash槽其中的一部分,当集群处于“stable”状态时(无slots在节点间迁移),任意一个hash slot只会被单个node所服务。以下是键映射到hash槽的算法:
HASH_SLOT = CRC16(key) mod 16384
Redis集群是在多个Redis节点之间进行数据共享,它不支持“multi-key”操作(即执行的命令需要在多个Redis节点之间移动数据,比如Set类型的并集、交集等(除非这些key属于同一个node),即Cluster不能进行跨Nodes操作。如下:
10.9.42.37:6102> smembers set1
-> Redirected to slot [3037] located at 10.9.33.204:6101
1) "d"
2) "b"
3) "g"
4) "c"
5) "a"
6) "f"
7) "e"
(1.08s)
10.9.33.204:6101> smembers set2
-> Redirected to slot [15294] located at 10.9.33.204:6103
1) "b"
2) "c"
3) "f"
4) "g"
5) "h"
6) "i"
7) "a"
10.9.33.204:6103> sunion set1 set2
(error) CROSSSLOT Keys in request don't hash to the same slot
Redis为了兼容multi-key操作,提供了“hash tags”操作,每个key可以包含自定义的“tags”,在存储的时候根据tags计算此key应该映射到哪个node上。通过“hash tags”可以强制某些keys被保存到同一个节点上,便于进行“multi key”操作。基本上如果关键字包含“{...}”,那么在{和}之间的字符串被hash,然而可能有多个匹配的该算法由以下规则规定:如果key包含{,在{的右边有一个},并在第一次出现{与第一次出现}之间有一个或者多个字符串,那么就作为key进行hash。例如,.following和.followed就在同一个hash slot;foo{}整个字符被hash,foo{},,bar被hash。如下所示:
10.9.33.204:6103> set .following 1000
10.9.33.204:6101> set .followed 1000
10.9.33.204:6101> keys *
4) .following
6) .followed
特殊说明一点,在resharding期间,原来同一个slot的keys被迁移到不同的node中,multi-key操作可能不可用。
数据一致性保证 Redis集群尽可能保证数据的强一致性,但在特定条件下会丢失数据,原因有两点:异步replication机制以及network partition。
Master以及对应的Slaves之间使用异步的机制,在节点failover后,新的Master将会最终替代其他的replicas:
write命令提交到Master,Master执行完毕后向Client返回“OK”,但由于一部分replication,此时数据还没传播给Slave;如果此时Master不可达的时间超过阀值,此时集群将触发对应的slave选举为新的Master,此时没有replication同步到slave的数据将丢失。
在network partition时,总有一个窗口期(node timeout)可能会导致数据丢失:
由于网络分区,此时master不可达,且Client与Master处于一个分区,且此时集群处于“OK”。此时Failover机制,将其中一个Slave提升为新的Master,等待网络分区消除后,老的Master再次可达,此时节点被切换为Slave,而在这段期间,处于网络分区期间,Client仍然将write提交到老的Master,因为该Master被认为是仍然有效的。当老的Master再次加入集群,被切换成Slave后,这些数据将永远丢失。
集群可用性 上述谈到多次集群状态的概念,那集群什么时候处于“OK”,什么时候处于“FAIL”,节点什么时候可用等,详见下面的解释: 当NODE_TIMEOUT时,触发failover,此时集群仍然可用的前提是:“大分区”(相对发生网络分区的Client-Master小分区端而言)端必须持有大部份Masters,且每个不可达的Master至少有一个Slave也在“大分区”端,且集群在小部分Nodes失效后仍然可以恢复有效性。举个例子:
集群有N个Master,且每个Master都有一个Slave,那么集群的可用性只能容忍一个Master节点被分区隔离,也就是说只有一个Master处于小分区端,当第二个Master节点被分区隔离之前扔保持可用性的概率为1-(1 /(N*2-1)),这里的意思是:当第一个节点失效后,剩余N*2-1节点,此时没有Slave的Master失效的概率为1 /(N*2-1)。比如有10个节点,每个Master有一个Slave,当2个nodes被隔离或失效后,集群可用性的概率是:1/(10*2-1)=5.26%,此时集群不再可用。
为了避免上述情况发生,Redis Cluster提供了“replicas migration”机制,当Master节点发生failover后,集群会动态重新分配、平衡Slaves的分布,有效地提高了集群的可用性。
从节点选举逻辑
-
节点是已下线Master对应的Slave
-
FAIL状态的Master负责的hash slot 非空
-
主从节点之间的replication link断线的时长不能超过
NODE_TIMEOUT * REDIS_CLUSTER_SLAVE_VALIDITY_MULT
Nodes handshake Nodes通过端口发送Ping、Pong,除了Ping之外,节点会拒绝其他所有非本集群节点的packets,一个节点注册成为集群的新成员有2中方法:
-
通过“Cluster meet”指令引入,即将指定的node加入集群,集群将认为指定的node为“可信任”。
-
当其他nodes通过gossip引入了新的nodes,这些nodes也是被认为是“可信任的”。即:如果A信任B,B信任C,且B向A传播关于C的信息,那么A也信任C,并尝试连接C。
MOVED重定向 Client可以将请求发给任意一个Node,包含Slaves,Node解析命令,检查语法,multiple keys是否在同一个slot。如果当前node持有该slot,那么命令直接执行并返回,否则当前Node向Client返回“MOVED”错误。
10.9.33.204:6101> keys *
1) test9
10.9.33.204:6101> get test9
value9
10.9.33.204:6101> get test8
(error) MOVED 905 10.9.42.37:6101
905指test8对应的slot,10.9.42.37:6101指slot所在的Node的ip:port,Client根据返回信息,重定向至指定的Node。若此过程中集群发生变更(配置调整、failover、resharding等),原来返回到Client可能已失真,重新发送命令时,可能会再次发生MOVED错误。
Redis集群提供集群模式的客户端,在跳转时会自动进行节点转向,以下是常用的:
Shell终端:redis-cli -c -h 10.9.33.204 -p 6101,集群提示重定向至Key所在的Slot:
10.9.33.204:6101> keys *
1) test9
10.9.33.204:6101> get test8
-> Redirected to slot [905] located at 10.9.42.37:6101
value8
Java:JedisCluster,需要配置集群信息,其他API如Jedis差异不大
<bean id="jedisClusterRaw" class="redis.clients.jedis.JedisCluster">
<constructor-arg index="0">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg type="String" value="$"/>
<constructor-arg type="int" value="$"/>
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" ref="jedisPoolConfig" />
</bean>
private static String configLocation = "classpath*:config-spring.xml";
private static ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
private void testCluster() {
JedisCluster jedisCluster = ctx.getBean("jedisClusterRaw", JedisCluster.class);
String v = jedisCluster.get("test6");
System.out.println("v:" + v);
}
ASK重定向 ASK重定向与MOVED重定向非常相似,两者最大的区别在于在resharding期间,当前的Client发送的命令暂时与指定的Node交互,在迁移期间,slot原来的keys仍有可能在原来的节点上,所以Client的命令仍然先经过原来的节点,对于不存的节点,再到新的节点进行尝试获取,一旦完成slot的迁移,原来slot接收到Client命令请求,则节点向客户端返回MOVED转向。对比ASK重定向,MOVED重定向指hash slots已经永久地被另一个node接管,后续Client的命令都是与该Node交互。ASK是Redis集群非阻塞的表现,即Redis集群不会因slot resharding而导致整个集群不可用。
节点失效检测 跟大部份分布式框架一样,Redis Cluster节点间通过持续的心跳来保持信息同步,不过Redis Cluster节点信息同步是内部实现的,不依赖第三方组件,如zk。集群中的nodes持续交换ping、pong数据,消息协议使用Gossip,这两种packet数据结构一样,它们之间通过type字段区分。
节点定时向其他节点发送ping命令,它会随机选择存储的其他集群节点的其中三个进行信息“广播”,例如广播的信息包含一项是节点是否被标记为PFAIL/FAIL。PFAIL表示“可能已失效”,是尚未完全确认的失效状态(即可能是某个节点或少数Master认为其不可达);FAIL表示Node被集群大多数的Masters认定为失效(即大多数Master已认定为不可达,且不可达的时间已经超过配置的NODE_TIMEOUT)。
当节点收到其他节点广播的信息,它会记录被其他节点标记为失效的节点。举个例子,如果节点被某个节点标记为PFAIL,集群中大部份其他主节点也认为该节点进入了失效状态,那么该节点的状态会被标志为FAIL。当节点被标志为FAIL,这个节点已失效的信息会被广播至整个集群,所有集群中的节点都会将失效的节点标志为FAIL。
集群失效检测 当某个Master或者Slave不能被大多数Nodes可达时,用于故障迁移并将合适Slave提升为Master。当Slave提升未能成功,集群不能正常工作。即集群不能处理Client的命令的请求,当Client发出命令请求时,集群节点都将返回错误内容的respone。
集群正常工作时,负责处理16384个slots的节点中,全部节点均正常。反之,若集群中有一部分hash slot不能正常使用,集群亦将停止工作,即集群进入了FAIL状态。对于集群进入FAIL状态,会有以下两种情况:
-
至少有一个hash slot不可用。
-
集群中大部份Master都进入了PFAIL状态。

浙公网安备 33010602011771号