在介绍 Redis 集群架构之前,我们先简单介绍下 Redis 单实例的架构。从最开始的一主N从,到读写分离,再到 Sentinel 哨兵机制,单实例的 Redis 缓存足以应对大多数的使用场景,也能实现主从故障迁移。但是,在某些场景下,单实例 Redis 缓存会存在的以下几个问题:
(1)写并发: Redis 单实例读写分离可以解决读操作的负载均衡,但对于写操作,仍然是全部落在了 Master 节点上面,在海量数据高并发场景,一个节点写数据容易出现瓶颈,造成 Master 节点的压力上升。
(2)海量数据的存储压力:单实例 Redis 本质上只有一台 Master 作为存储。如果面对海量数据的存储,一台 Redis 的服务器就应付不过来了,而且数据量太大意味着持久化成本高,严重时可能会阻塞服务器,造成服务请求成功率下降,降低服务的稳定性。
针对以上的问题,Redis 集群提供了较为完善的方案,解决了存储能力受到单机限制,写操作无法负载均衡的问题。
Redis 3.0 加入了 Redis 的集群模式,实现了数据的分布式存储,对数据进行分片,将不同的数据存储在不同的 Master 节点上面,从而解决了海量数据的存储问题。
Redis 集群采用去中心化的思想,没有中心节点的说法,对于客户端来说,整个集群可以看成一个整体,可以连接任意一个节点进行操作,就像操作单一 Redis 实例一样,不需要任何代理中间件,当客户端操作的 key 没有分配到该节点(当前连接的节点)上时,Redis 会返回转向指令,指向正确的节点。
Redis 也内置了高可用机制,支持 N 个 Master 节点,每个 Master 节点都可以挂载多个 Slave 节点。当 Master 节点挂掉时,集群会提升它的某个 Slave 节点作为新的 Master 节点。如下图:
如上图所示,Redis 集群可以看成由多个主从复制架构组合起来的,每一个主从架构可以看成一个节点(其中,只有 Master 节点具有处理请求的能力,Slave 节点主要是用于节点的高可用)。
(1)解决了写操作无法负载均衡的问题
(2)解决存储能力受到单机限制的问题
(3)实现了较为完善的高可用方案
(1)使用场景并不那么普遍
(2)需要的服务器资源较多
如果 Redis 集群中任意一个节点挂了,而且该节点没有从节点(如果有从节点,可以设置为新的主节点),那么这个集群就挂了。
因为集群内置了 16384 个 Slot(哈希槽),并且把所有的物理节点映射到了这 16384 [0-16383] 个 Slot 上,或者说把这些 Slot 均等的分配给了各个节点。
当需要在 Redis 集群存放一个数据(key-value)时,Redis 会先对这个 key 计算 CRC16 值,然后将得到一个结果与 16384 进行求余,这个余数会对应 [0-16383] 其中一个槽,进而决定 key-value 存储到哪个节点中。所以一旦某个节点挂了,该节点对应的所有 Slot 就无法使用,那么就会导致集群无法正常工作。
如果 Redis 集群有三个节点,Slot 分布如下 :
节点A覆盖 0-5460
节点B覆盖 5461-10922
节点C覆盖 10923-16383
注意:每个节点有 5460 个哈希槽(Slot)
如果此时向 Redis 集群中新增了一个节点:
节占A覆盖 1365-5460
节占B覆盖 6827-10922
节点c覆盖 12288-16383
节点D覆盖 0-1364
注意:每个节点有 4095 个哈希槽,所以每个 Redis 集群理论上最多可以有 16384 个节点。
Redis 的哨兵模式基本已经可以实现高可用、读写分离,但是在这种模式每台 Redis 服务器都存储相同的数据,很浪费内存资源。所以,在 Redis3.0 上加入了群集模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点存储着不同的内容。
根据官方推荐,集群部署至少要 3 台以上的 Master 节点,最好使用 3 主 3 从六个节点的模式。
Redis 集群是由多个 Redis 服务器组成的分布式网络服务集群,集群之中有多个 Master 主节点,每一个 Master 节点都可读可写,节点之间会相互通信,两两相连,Redis 集群无中心节点。
在 Redis 集群中,可以给每个一个 Master 节点添加 Slave 节点,Master 节点和 Slave 节点直接尊循主从复制的特性,当用户需要处理更多读请求的时候, 添加 Slave 节点可以扩展系统的读性能。
Redis 群集的 Master 节点内置了类似哨兵的节点故障检测和自动故障转移功能,当群集中的某个 Master 节点下线时,群集中的其他在线 Master 节点会注意到这一点,并且对已经下线的 Master 节点进行故障转移。
Redis 集群进行故障转移的方法和哨兵模式进行故障转移的方法基本一样。不同的是,在集群里面故障转移是由集群中其他在线的 Master 节点负责进行的,所以群集不必另外配置哨兵。
下面配置的 Redis 示例将创建三个 Redis 节点,每个节点分为一个 Master 和一个 Slave。环境信息如下:
127.0.0.1:6379 Master 127.0.0.1:6378 Master 127.0.0.1:6377 Master 127.0.0.1:26379 Slave 127.0.0.1:26378 Slave 127.0.0.1:26377 Slave
Redis 集群配置分为三个步骤,分别如下:
第一步:将6个 Redis 配置为 3 个 主从复制模式,不知道怎样配置主从复制,请参考“Redis 主从复制”。
第二步:将所有 Redis 中的 dump.rdb 文件删除,或者清理 Redis 中的数据。
第三步:将三个 Master 配置成集群模式,注意,Slave 不需要配置为集群模式。
第四步:使用 redis-cli --cluster create 命令创建 Redis 集群。
下面开始配置 Redis 集群,详细配置如下:
下面是一个 Master 节点的集群配置,集群配置总共有三相配置,分别是 cluster-enabled、cluster-config-file 和 cluster-node-timeout,配置如下:
################################ REDIS CLUSTER ############################### # Normal Redis instances can't be part of a Redis Cluster; only nodes that are # started as cluster nodes can. In order to start a Redis instance as a # cluster node enable the cluster support uncommenting the following: # # cluster-enabled yes cluster-enabled yes # Every cluster node has a cluster configuration file. This file is not # intended to be edited by hand. It is created and updated by Redis nodes. # Every Redis Cluster node requires a different cluster configuration file. # Make sure that instances running in the same system do not have # overlapping cluster configuration file names. # # cluster-config-file nodes-6379.conf cluster-config-file nodes-6379.conf # Cluster node timeout is the amount of milliseconds a node must be unreachable # for it to be considered in failure state. # Most other internal time limits are multiple of the node timeout. # # cluster-node-timeout 15000 cluster-node-timeout 15000
cluster-enabled yes cluster-config-file nodes-6378.conf cluster-node-timeout 15000
cluster-enabled yes cluster-config-file nodes-6377.conf cluster-node-timeout 15000
启动集群之前,我们先将三个 Redis 主从模式启动起来(注意,这里可以通过编写批处理脚本,一次就启动好了)。然后,在 DOS 中执行如下命令去创建集群,如下:
C:\Users\Administrator> redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6378 127.0.0.1:6377 >>> Performing hash slots allocation on 3 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 M: dad34b2df666bb44b3d1f3807eb0030a529c2ec7 127.0.0.1:6379 slots:[0-5460] (5461 slots) master M: e47001b66c6d20afd76833c0e136c97c60afad32 127.0.0.1:6378 slots:[5461-10922] (5462 slots) master M: 39c486df6dbb5f7ffb550c07a1e5710842d993d2 127.0.0.1:6377 slots:[10923-16383] (5461 slots) master Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join ..... >>> Performing Cluster Check (using node 127.0.0.1:6379) M: dad34b2df666bb44b3d1f3807eb0030a529c2ec7 127.0.0.1:6379 slots:[0-5460] (5461 slots) master M: e47001b66c6d20afd76833c0e136c97c60afad32 127.0.0.1:6378 slots:[5461-10922] (5462 slots) master M: 39c486df6dbb5f7ffb550c07a1e5710842d993d2 127.0.0.1:6377 slots:[10923-16383] (5461 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
从上面日志可知,创建了三个节点,节点信息如下:
Master0 的 Slots 范围为 0 - 5460
Master1 的 Slots 范围为 5461 - 10922
Master2 的 Slots 范围为 10923 - 16383
我们可以通过 redis-cli 工具连接到 Redis,查看 Redis 集群信息,如下:
C:\Users\Administrator> redis-cli # 查看集群节点信息 127.0.0.1:6379> cluster nodes e47001b66c6d20afd76833c0e136c97c60afad32 127.0.0.1:6378@16378 master - 0 1681192504330 2 connected 5461-10922 39c486df6dbb5f7ffb550c07a1e5710842d993d2 127.0.0.1:6377@16377 master - 0 1681192503000 3 connected 10923-16383 dad34b2df666bb44b3d1f3807eb0030a529c2ec7 127.0.0.1:6379@16379 myself,master - 0 1681192503000 1 connected 0-5460 # 集群信息,状态为 ok,即运行正常 127.0.0.1:6379> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:3 cluster_size:3 cluster_current_epoch:3 cluster_my_epoch:1 cluster_stats_messages_ping_sent:1264 cluster_stats_messages_pong_sent:1198 cluster_stats_messages_sent:2462 cluster_stats_messages_ping_received:1196 cluster_stats_messages_pong_received:1264 cluster_stats_messages_meet_received:2 cluster_stats_messages_received:2462 127.0.0.1:6379>
使用 Redis 客户端工具 redis-cli 连接到 Redis 集群,然后相集群写入数据,以及从集群获取数据,如下:
C:\Users\Administrator> redis-cli -c 127.0.0.1:6379> set name www.hxstrive.com -> Redirected to slot [5798] located at 127.0.0.1:6378 OK 127.0.0.1:6378> get name "www.hxstrive.com"
其中,-c 选项用来启用 Redis 集群模式(遵循 -ASK 和 -MOVED 重定向)。