Redis 集群
Redis 集群
Redis集群具有水平伸缩的能力,通过Redis集群,可以:
-
数据集在多个节点上分片;
-
部分节点发生故障或者与其他节点断开连接之后,也可继续执行命令。
创建 Redis 集群
创建 Redis 集群
一个最小的集群配置如下模板文件 7000/redis.conf :
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
将端口号依次改为7001、7002、7003、7004、7005,并依次在对应的目录下面创建对应的配置文件。
并依次进入对应的子目录下面,执行如下命令:
redis-server ./redis.conf
...
[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1
...
每个节点启动的时候,都会被分配一个在集群上下文中具有唯一性的节点ID(Node ID)。
ip:port 可能会改变,但是唯一的节点标识符在在节点的整个生命周期永远不会改变。
当所有节点都已经启动运行后,可以通过如下命令创建集群:
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
...
yes
...
[OK] All 16384 slots covered
其中,选项含义如下:
create选项表示新创建一个集群;--cluster-replicas 1选项表示每个 主节点都有一个副本节点。- 其他的示例地址列表表示新创建的集群中的节点
执行该命令后,会生成一个配置,输入 yes 后,集群将会被初始化,所有的节点将会引导相互通信。
当数据库中 16384 个槽都有节点在处理时,集群处于上线状态,如果集群中有任何一个槽没有得到处理,集群都会处于下线状态。
集群交互
The redis-cli cluster support is very basic, so it always uses the fact that Redis Cluster nodes are able to redirect a client to the right node. A serious client is able to do better than that, and cache the map between hash slots and nodes addresses, to directly use the right connection to the right node. The map is refreshed only when something changed in the cluster configuration, for example after a failover or after the system administrator changed the cluster layout by adding or removing nodes.
与单机Redis实例相同,集群也可以使用 redis-cli 进行交互,如下所示:
$ redis-cli -c -p 7000
redis 127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
redis 127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
客户端向集群中的节点发送命令时,接收到命令的节点会计算出当前命令的key属于哪一个槽,并检查这个槽是否指派给了自己:
-
如果 key 所在的槽正好就指派给了当前节点,那么,当前节点就指向这个命令;
-
如果key 所在的槽并没有指派给当前节点,那么,当前节点就会向客户端返回一个 MOVED 错误,指引客户端转向(redirect)至正确的节点,并再次发送之前想执行的命令。
注意,集群中节点只能使用 0 号数据库(单机 Redis 服务有 16 个数据库,每个数据库的 id = [0, 15])。
添加新的节点
创建节点
使用 redis-cli 添加一个节点到集群中:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
其中,add-node 选项需要指明新节点的 ip:port 和一个已经存在的节点的 ip:port。
添加后,可以通过如下命令查询已经存在的节点:
redis 127.0.0.1:7006> cluster nodes
97a3a64667477371c4479320d683e4c8db5858b1 127.0.0.1:7000 master - 0 1385543179080 0 connected 0-5959 10922-11422
3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385543178575 0 connected 5960-10921
2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385543178072 3 connected
a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385543178575 0 connected
3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385543179583 0 connected
3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385543177568 3 connected 11423-16383
f093c80dde814da99c5cf72a7dd01590792b783b :0 myself,master - 0 0 0 connected
添加一个节点作为从节点
有两种方式,
方式一:随机选择一个主节点分配一个从节点
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave
方式二:给指定的主节点分配一个从节点
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
移除一个节点
从集群中移除一个节点:
redis-cli --cluster del-node 127.0.0.1:7000 `<node-id>`
Redis 集群数据分片
哈希槽(hash slot)
Redis Cluster 没有使用一致性 Hash 算法,而是使用了哈希槽( Hash Slot)的方式对数据集进行分片。
集群的整个数据库被分成 \(16384\) (\(2^{14}\))个槽(Slot),数据库中的每个键都属于这 \(16384\) 个槽中的一个,集群中的每个节点可以处理哈希槽的一个子集。
对于指定的 \(key\),它的计算哈希槽的方式:
slot = CRC16(key) % 16384
集群中的每个节点都会将自己的 slots 信息 通过消息发送集群中的其他节点,并且每个接收到 slots 信息的节点都会将数组保存下来。
重新分片
槽指派
ASK 错误
复制
当一部分 master节点发生故障或者无法与其他节点通信时,为了保证 Redis Cluster 的高可用,Redis Cluster 使用主-复制模型(master-replica model),其中,每个哈希槽都有 1 ~ n 个副本,包括一个主节点和 n - 1 个从节点。
故障转移
一致性
Redis集群不保证强一致性,在某些情况下,Redis集群可能会丢失向客户端确认的写操作。
Redis集群丢失写的第一个原因是因为它使用异步复制。

浙公网安备 33010602011771号