在3.0版本正式推出,有效地解决了Redis分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡的目的
环境
- redis5.0.7
- centos7
概述
Redis Cluster集群搭建三分个步骤
- 准备节点
- 节点握手
- 分配槽
用到的命令
redis-server redis.conf # 启动cluster
redis-cli -p port # 普通客户连接模式
redis-cli -p -c port # cluster客户端连接模式
redis-cli -p 6379 cluster addslots {0..5000} #手动分配槽位
cluster help #查看cluster所有的命令
cluster nodes #查看cluster节点信息
cluster meet 127.0.0.1 6392 # 与其它节点握手,建立集群关系
cluster info #查看当前cluster节点信息
cluster reset #重置cluster配置
cluster replicate <id> #与主节点建立主从关系
准备节点
新建目录(data, logs, conf), 创建6个redis.conf文件,端口6391~6396.
- 创建目录. conf, data, logs
mkdir -p /usr/local/redis-cluster/
- 复制redis.conf文件,共6个(端口6391~6396), 配置文件命名规则redis-{port}.conf
- 修改cluster集群相关配置项
以下是模板配置,其它端口的配置,只需要修改端口号即可.
bind 127.0.0.1 # 绑定的IP
daemonize yes # 后台运行
port 6391 # 监听端口
pidfile /var/run/redis_6391.pid # PID文件
logfile "/usr/local/redis-cluster/logs/cluster-6391.log" # 日志文件
dbfilename dump-6391.rdb #rdb存储文件名称
dir /usr/local/redis-cluster/data/ #工作目录
cluster-enabled yes # 开启cluster功能
cluster-config-file nodes-6391.conf # 集群内部配置文件
cluster-node-timeout 15000 # 节点超时设置, 单位: 毫秒
- 使用脚本快速创建其它配置文件
#查看替换
sed 's/6391/6392/g' redis-6391.conf |grep -v "#"|grep -v "^$" > redis-6392.conf
sed 's/6391/6393/g' redis-6391.conf |grep -v "#"|grep -v "^$" > redis-6393.conf
sed 's/6391/6394/g' redis-6391.conf |grep -v "#"|grep -v "^$" > redis-6394.conf
sed 's/6391/6395/g' redis-6391.conf |grep -v "#"|grep -v "^$" > redis-6395.conf
sed 's/6391/6396/g' redis-6391.conf |grep -v "#"|grep -v "^$" > redis-6396.conf
- 准备启动所有的节点
cd /usr/local/redis-cluster/conf/
redis-server redis-6391.conf
redis-server redis-6392.conf
redis-server redis-6393.conf
redis-server redis-6394.conf
redis-server redis-6395.conf
redis-server redis-6396.conf
- 查看启动日志, 生成节点唯一ID, 集群ID与RUNID不同, 不会 每次重启就生成一次.
节点ID,它是一个40位16进制字符串,用于唯一标识集群内一个节点
- 第一次启动时如果没有集群配置文件,它会自动创建集群配置文件,以nodes开头的文件,在data目录下
集群自动生成的文件有什么用?
- 如添加节点、节点下线、故障转移等, 节点会自动保存集群状态到配置文件中
- Redis自动维护集群配置文件,不要手动修改,防止节点重启时产生集群信息错乱
- 此时6个节点并没有什么联系,彼此孤立的, 集群还不可用.
cluster_state: fail 表示集群不可用. 如何让它们能正常工作呢?需要进行下一步握手操作.彼此建立连接.
-
启动过程示意图
节点握手
节点握手是指一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程,
节点握手是集群彼此通信的第一步,由客户端发起命令:cluster meet{ip}{port}
- 使用cluster meet ip port握手操作(异步操作,非阻塞)
redis-cli -p 6391
#与其它节点握手操作.
127.0.0.1:6391> cluster meet 127.0.0.1 6392
127.0.0.1:6391> cluster meet 127.0.0.1 6393
127.0.0.1:6391> cluster meet 127.0.0.1 6394
127.0.0.1:6391> cluster meet 127.0.0.1 6395
127.0.0.1:6391> cluster meet 127.0.0.1 6396
#查看节点之间的信息
127.0.0.1:6391>cluster nodes
-
先进行其它节点的握手, 然后再与之前握手过的节点相联, 也能彼此感知
节点建立握手之后集群还不能正常工作,这时集群处于下线状态,所有的数据读写都被禁止
- 从图中可以看出, 集群未分配槽位, redis-cluster使用了16384个槽位
- 只有当16384个槽位全部分配给节点,集群才进入在线状态
- 总结
- 节点之间使用ping/pong维护彼此之间的联系.
- meet、ping、pong消息是Gossip协议通信的载体
- 主要作用是节点彼此交换状态数据信息
分配槽位
我们采用3主3从部署cluster集群
- 查看帮助
cluster help
- 槽位分配错误使用
cluster reset
- 分配槽位, 注意只能使用redis-cli方式, 槽位之间是两个小点, 文档上写着3个点,执行报错, 5.0版本之后变了.
redis-cli -h 127.0.0.1 -p 6391 cluster addslots {0..5461}
redis-cli -h 127.0.0.1 -p 6392 cluster addslots {5462..10922}
redis-cli -h 127.0.0.1 -p 6393 cluster addslots {10923..16383}
- 如果报
(error) ERR Slot 5462 is already busy
错误的话, 先查看cluster nodes
, 排查问题, 实在不行,使用cluster reset
重置操作. 重新握手操作.然后再分配槽位.
-
建立主从关系, 上面我们使用了三个节点做为主节点, 剩余3个节点做为从节点,做数据备份.
- 建立主从关系必须是在未分配槽的节点上操作.
- 6391, 6392, 6393已经分配槽位了,是主节点
- 将6394与6391建立主从关系
192.168.21.22:6394>cluster replicate 39f296c2274407013a4fb07d301370c2e3ab2bb3
- 将6395与6392建立主从关系
192.168.21.22:6395>cluster replicate ce9858bf540fbf297b3c2d6b43732696ac3b13e7
- 将6396与6393建立主从关系
192.168.21.22:6396>cluster replicate bafb26d0cc0476ef021f3dad8946d207bfeb5e04
上面涉及到的40位的ID是cluster集群产生的ID, 可以cluster nodes查看.
- 建立好了再使用
cluster info
能清楚的查看节点之间的关系, 谁是主, 谁是从, 从对应的主是哪一个.都很清楚
-
cluster集群可以正常工作啦
-
建立主从关系后, 会进行数据同步操作
常见错误
- (error) ERR To set a master the node must be empty and without assigned slots.
是因为执行cluster replicate在已经分配槽位的节点里执行操作,应该在未分配槽位上的节点.
测试集群是否正常工作.
使用redis-cli -c -p 6391
连接.而不是之前的redis-cli -p 6391
, 集群操作需要加一个参数-c
-
redis-cli --help
-c Enable cluster mode (follow -ASK and -MOVED redirections).
- Cluster 默认会对 key 值使用 crc32 算法进行 hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位
- 在分配槽位时,相当于把对应的槽位挂载在指定的节点上, key计算出来的槽位,然后跟据槽位找到对应的节点,将key存储在这个节点上.
- 若
set sgfoot www.sgfoot.com
, 集群计算出对应的槽位是: 6498, 而6498槽位被挂载在127.0.0.1:6392节点上, 不归自己管, 所以会返回一个信息-> Redirected to slot [6498] located at 127.0.0.1:6392
让你去连接6392节点上查看,你刚才存储的值.