Cluster模式是Redis的一种高级集群模式,它通过数据分片和分布式存储实现了负载均衡和高可用性。在Cluster模式下,Redis将所有的键值对数据分散在多个节点上。每个节点负责一部分数据,称为 槽位
。通过对数据的分片,Cluster模式可以突破单节点的内存限制,实现更大规模的数据存储。
Redis Cluster将数据分为 16384
个槽位,每个节点负责管理一部分槽位。当客户端向Redis Cluster发送请求时,Cluster会根据 键
的哈希值将请求路由到相应的节点。具体来说,Redis Cluster使用CRC16算法计算键的哈希值,然后对16384取模,得到槽位编号。
使用Cluster集群有以下优点:
数据分片,实现大规模数据存储。
负载均衡,提高系统性能。
自动故障转移,提高可用性。
使用Docker搭建RedisCluster集群
使用Docker容器,可以很方便地搭建RedisCluster集群。
首先,我们要创建虚拟网卡,主要是用于redis-cluster能于外界进行网络通信,一般常用桥接模式。
1 docker network create --subnet=192.168.100.0/24 redis_cluster_net
Redis-cluster集群最小规模是三主三从,我们安排一下容器结点的IP和端口:
IP
PORT
REMARK
192.168.100.101
7001
主节点master-1
192.168.100.102
7002
主节点master-2
192.168.100.103
7003
主节点master-3
192.168.100.104
6379
从节点slave-1
192.168.100.105
6379
从节点slave-2
192.168.100.106
6379
从节点slave-3
接下来创建redis.conf配置文件。
我们先新建一个目录
1 mkdir docker-redis-cluster && cd docker-redis-cluster
编辑 master
结点配置文件 redis-master-1.conf
:
1 2 3 4 5 6 7 8 9 port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes daemonize no protected-mode no pidfile /var/run/redis.pid cluster-announce-ip 192.168.242.93
主结点配置说明:
port: 指定了启动的端口号
cluster-enabled: yes启动允许集群
cluster-config-file: 集群配置文件(自动创建)
cluster-node-timeout: 集群超时时间(毫秒)
appendonly: 持久化 yes
daemonize: 后台运行 no
protected-mode: no 允许外部IP访问
cluster-announce-ip: 集群节点 IP,如果想要集群可以供外网访问,这里直接填宿主机的IP
三个主结点,每个的配置只是port不同,可以使用shell指令复制多两份出来:
1 for i in {2..3}; do sed "s/port 7001/port 700$i/" redis-master-1.conf > redis-master-$i.conf ; done
slave
结点配置文件 redis-slave-1.conf
:
1 2 3 4 5 6 7 port 6379 cluster-enabled no appendonly yes daemonize no protected-mode no pidfile /var/run/redis.pid slaveof 192.168.100.101 7001
和配置主结点一样,使用shell指令复制多两份出来:
1 for i in {2..3}; do sed "s/\(192.168.100\).101 7001/\1.10$i 700$i/" redis-slave-1.conf > redis-slave-$i.conf ; done
slave
结点配置说明:
cluster-enabled: no 不参与集群分配
appendonly: 持久化 yes
daemonize: 后台运行 no
slaveof 192.168.100.101 7001: 直接指定成为对应master的从节点
创建docker-compose.yml
我们使用 docker-compose.yml
来创建6个docker容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 version: '3.7' x-image: &default-image redis:5.0 .7 networks: redis_cluster_net: name: redis_cluster_net services: redis-master-1 : image: *default-image container_name: redis-master-1 command: ["redis-server" , "/home/redis/cluster/redis.conf" ] networks: redis_cluster_net: ipv4_address: 192.168 .100.101 volumes: - ./redis-master-1 .conf:/home/redis/cluster/redis.conf - ./master-1 -data:/data ports: - 7001 :7001 - 17001 :17001 redis-master-2 : image: *default-image container_name: redis-master-2 command: [ "redis-server" , "/home/redis/cluster/redis.conf" ] networks: redis_cluster_net: ipv4_address: 192.168 .100.102 volumes: - ./redis-master-2 .conf:/home/redis/cluster/redis.conf - ./master-2 -data:/data ports: - 7002 :7002 - 17002 :17002 redis-master-3 : image: *default-image container_name: redis-master-3 command: [ "redis-server" , "/home/redis/cluster/redis.conf" ] networks: redis_cluster_net: ipv4_address: 192.168 .100.103 volumes: - ./redis-master-3 .conf:/home/redis/cluster/redis.conf - ./master-3 -data:/data ports: - 7003 :7003 - 17003 :17003 redis-slave-1 : image: *default-image container_name: redis-slave-1 command: [ "redis-server" , "/home/redis/cluster/redis.conf" ] networks: redis_cluster_net: ipv4_address: 192.168 .100.104 volumes: - ./redis-slave-1 .conf:/home/redis/cluster/redis.conf - ./slave-1 -data:/data ports: - 7004 :6379 redis-slave-2 : image: *default-image container_name: redis-slave-2 command: [ "redis-server" , "/home/redis/cluster/redis.conf" ] networks: redis_cluster_net: ipv4_address: 192.168 .100.105 volumes: - ./redis-slave-2 .conf:/home/redis/cluster/redis.conf - ./slave-2 -data:/data ports: - 7005 :6379 redis-slave-3 : image: *default-image container_name: redis-slave-3 command: [ "redis-server" , "/home/redis/cluster/redis.conf" ] networks: redis_cluster_net: ipv4_address: 192.168 .100.106 volumes: - ./redis-slave-3 .conf:/home/redis/cluster/redis.conf - ./slave-3 -data:/data ports: - 7006 :6379
注意3个主结点的容器,需要同时映射7001端口和17001端口。每个Redis Cluster节点都需要打开两个TCP连接。用于服务客户端的普通Redis TCP端口(如6379),以及数据端口加上10000得到的端口(例如16379)。第二个高端口用于集群总线,是使用二进制协议的节点到节点通信通道。节点使用集群总线进行故障检测、配置更新、故障转移授权等。
配置好 docker-compose.yml
文件之后,使用命令启动容器:
docker-compose up -d
创建集群并分配slots
此时仅仅创建了三对主从节点,但是三个主节点(7001, 7002, 7003)是孤立的,并且还未分配slots。
进入任意一个主结点:
1 docker exec -it redis-master-1 /bin/bash
然后执行下面的命令:
1 redis-cli --cluster create 192.168.100.101:7001 192.168.100.102:7002 192.168.100.103:7003 --cluster-replicas 0
在提示后输入 yes
:
1 2 3 4 5 6 7 8 9 10 11 > >> Performing hash slots allocation on 3 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 M: 6ef13d3f45b4598c90a072a47bd076d7fbc50969 192.168.100.101:7001 slots:[0-5460] (5461 slots) master M: 431173ccf97e48aa0c67a66ef25e3013d14ac4a8 192.168.100.102:7002 slots:[5461-10922] (5462 slots) master M: 5e1f46e8552d1e98b6b1b657c1d188b78b03e6fc 192.168.100.103:7003 slots:[10923-16383] (5461 slots) master Can I set the above configuration? (type 'yes' to accept): yes
正常来说就会得到以下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 > >> 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 192.168.100.101:7001) M: 6ef13d3f45b4598c90a072a47bd076d7fbc50969 192.168.100.101:7001 slots:[0-5460] (5461 slots) master M: 5e1f46e8552d1e98b6b1b657c1d188b78b03e6fc 192.168.242.93:7003 slots:[10923-16383] (5461 slots) master M: 431173ccf97e48aa0c67a66ef25e3013d14ac4a8 192.168.242.93:7002 slots:[5461-10922] (5462 slots) master [OK] All nodes agree about slots configuration.> >> Check for open slots... > >> Check slots coverage... [OK] All 16384 slots covered.
这时候这个三主三从的redis集群就创建好了。
测试连接
使用集群模式(-c
)连接主结点:
> redis-cli -h 192.168.100.101 -p 7001 -c
然后随便设置一个值:
192.168.100.101:7001> set k1 v1
如果计算出来这个 key
的 slot
不在当前结点,则会提示:
-> Redirected to slot [12706] located at 192.168.242.93:7003 OK
表示通过计算 slot
分配到 192.168.242.93:7003
结点去了。
我们通过普通模式连接到主结点 192.168.242.93:7003
和从结点 192.168.100.106:6379
,都能查到这个 k1
参考资料