知识点回顾
Redis主从架构
Redis主从架构的工作模式为提供多台Redis服务,选择其中的一台作为master节点向外提供读写服务,剩下的作为slave节点从master节点复制数据,只向外提供读服务。
Redis哨兵架构
Redis哨兵架构实现了对所有Redis节点的监控和Master的自动故障转移。
集群架构概述
一般情况下来说,上面两种方式结合起来使用已经可以满足大部分的Redis高可用场景,但它有一个很明显的缺点:只有一台Master节点向外提供写服务,其他的Slave节点只能提供读服务。所以,当写操作并发量很大的,无法缓解写操作的压力。针对这种场景,Redis在3.0版本中引入了Redis集群的部署架构。
Redis集群架构(Redis Cluster)是Redis 3.0开始引入的一种分布式存储架构,该架构由多个Redis节点组成,所有的数据分布在不同的节点中。
Redis集群架构中的节点可以分为主节点和从节点: (1)主节点负责读写请求和集群信息的维护。 (2)从节点只进行主节点数据和状态的复制。
集群架构特性
Redis集群是一个提供在多个Redis节点之间共享数据的程序集。它并不像Redis主从复制模式那样只提供一个Master节点提供写服务,而是会提供多个Master节点提供写服务,每个Master节点中存储的数据都不一样,这些数据通过数据分片的方式被自动分割到不同的Master节点上。
为了保证集群的高可用,每个Master节点下面还需要添加至少1个Slave节点,这样当某个Master节点发生故障后,可以从它的Slave节点中选举一个作为新的Master节点继续提供服务。这样就组成了下图中的结构模式:
Redis集群架构示意图
集群架构哈希槽
Redis集群中引入了哈希槽的概念,Redis集群有16384个哈希槽,进行set操作时,每个key会通过CRC16校验后再对16384取模来决定放置在哪个槽,搭建Redis集群时会先给集群中每个Master节点分配一部分哈希槽。比如当前集群有3个Master节点,master1节点包含05500号哈希槽,master2节点包含550111000号哈希槽,master3节点包含11001~16384号哈希槽,当我们执行“set key value”时,假如 CRC16(key) % 16384 = 777,那么这个key就会被分配到master1节点上,如下图:
Redis集群架构哈希槽示意图
集群架构通信
既然Redis集群中的数据是通过哈希槽的方式分开存储的,那么集群中每个节点都需要知道其他所有节点的状态信息,包括当前集群状态、集群中各节点负责的哈希槽、集群中各节点的master-slave状态、集群中各节点的存活状态等。Redis集群中,节点之间通过建立TCP连接,使用gossip协议来传播集群的信息。如下图:
Redis集群架构通信示意图
所谓gossip协议,指的是一种消息传播的机制,类似人们传递八卦消息似的,一传十,十传百,直至所有人都知道这条八卦内容。Redis集群中各节点之间传递消息就是基于gossip协议,最终达到所有节点都会知道整个集群完整的信息。gossip协议有4种常用的消息类型:PING、PONG、MEET、FAIL。
(1)PING:集群内每个节点每秒会向其他节点发送PING消息,用来检测其他节点是否正常工作,并交换彼此的状态信息。PING消息中会包括自身节点的状态数据和其他部分节点的状态数据。 (2)PONG:当接收到PING消息和MEET消息时,会向发送方回复PONG消息,PONG消息中包括自身节点的状态数据。节点也可以通过广播的方式发送自身的PONG消息来通知整个集群对自身状态的更新。 (3)MEET:Redis CLUSTER MEET 命令被用来连接不同的开启集群支持的 Redis 节点,以进入工作集群。其基本的思想是每个节点默认都是相互不信任的,并且被认为是未知的节点,以便万一因为系统管理错误或地址被修改,而不太可能将多个不同的集群节点混成一个集群。 (4)FAIL:当一个节点判定另一个节点下线时,会向集群内广播一个FAIL消息,其他节点接收到FAIL消息之后,把对应节点更新为下线状态。
集群重定向
Redis客户端可以向Redis集群中的任意master节点发送操作指令,可以向所有节点(包括slave节点)发送查询指令。当Redis节点接收到相关指令时,会先计算key落在哪个哈希槽上(对key进行CRC16校验后再对16384取模),如果key计算出的哈希槽恰好在自己节点上,那么就直接处理指令并返回结果,如果key计算出的哈希槽不在自己节点上,那么当前节点就会查看它内部维护的哈希槽与节点ID之间的映射关系,然后给客户端返回一个MOVED错误:MOVED [哈希槽] [节点IP:端口]。这个错误包含操作的key所属的哈希槽和能处理这个请求的Redis节点的IP和端口号,例如“MOVED 3999 127.0.0.1:6379”,客户端需要根据这个信息重新发送查询指令到给定的IP和端口的Redis节点。
Redis MOVED重定向示意图