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备份。
Redis集群设计 
 
总体架构 
 

 

集群节点属性 集群中每个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。

重定向与resharding 
 

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状态。

posted @ 2018-08-30 11:05  隔壁w王叔叔  阅读(239)  评论(0)    收藏  举报