1、集群的概念
- 集群是一组相互独立的、通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理。一个客户与集群相互作用时,集群像是一个独立的服务器。集群配置是用于提高可用性和可缩放性。当请求到来首先由负载均衡服务器处理,把请求转发到另外的一台服务器上,redis集群主要是缓解单台服务器同一时间大量请求带来的的压力,就算集群中有服务器宕机,也不影响整体对外提供服务。
- Redis cluster在设计的时候,就考虑到了去中⼼化,去中间件,也就是说,集群中 的每个节点都是平等的关系,都是对等的,每个节点都保存各⾃的数据和整个集 群的状态。每个节点都和其他所有节点连接,⽽且这些连接保持活跃,这样就保 证了我们只需要连接集群中的任意⼀个节点,就可以获取到其他节点的数据
- Redis集群没有并使⽤传统的⼀致性哈希来分配数据,⽽是采⽤另外⼀种叫做哈希槽 (hash slot)的⽅式来分配的。redis cluster 默认分配了 16384 个slot,当我们 set⼀个key 时,会⽤CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。
- Redis 集群会把数据存在⼀个 master 节点,然后在这个 master 和其对应的salve 之间进⾏数据同步。当读取数据时,也根据⼀致性哈希算法到对应的 master 节 点获取数据。只有当⼀个master 挂掉之后,才会启动⼀个对应的 salve 节点,充当 master。
2、组织架构
3、环境准备(每个节点都执行)
#创建目录
mkdir -p /opt/{6380,6381}/{log,pid,etc}
#添加配置文件
cat >/opt/6380/etc/redis.conf<<-EOF
bind 0.0.0.0
port 6380
daemonize yes
pidfile "/opt/6380/pid/redis.pid"
logfile "/opt/6380/log/redis.log"
dir /opt/6380/
dbfilename dump.rdb
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
EOF
cp /opt/6380/etc/redis.conf /opt/6381/etc/
sed -i "s/6380/6381/g" /opt/6381/etc/redis.conf
#启动
redis-server /opt/6380/etc/redis.conf
redis-server /opt/6381/etc/redis.conf
#添加防火墙规则
#redis会在当前端口+10000的端口上进行集群节点间的数据交流。
firewall-cmd --permanent --add-port=6380/tcp
firewall-cmd --permanent --add-port=6381/tcp
firewall-cmd --permanent --add-port=16380/tcp
firewall-cmd --permanent --add-port=16381/tcp
firewall-cmd --reload
4、手动搭建redis集群
4.1、手动节点发现
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.162 6380
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.163 6380
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.161 6381
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.162 6381
redis-cli -h 192.168.20.161 -p 6380 CLUSTER MEET 192.168.20.163 6381
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
4.2、手动添加主从复制关系
redis-cli -h 192.168.20.161 -p 6381 CLUSTER REPLICATE 9bd06eadbaf32eff955a211a927fa6ab7dc4d56b
redis-cli -h 192.168.20.162 -p 6381 CLUSTER REPLICATE b1b2dfdea90fe6d833f5a83d77a7a8320bd7497b
redis-cli -h 192.168.20.163 -p 6381 CLUSTER REPLICATE d70d68d2b8557d753e2dcfd03b8aa707727adb11
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
4.2、手动分配槽位
#一共16384个槽位,只有当槽位全部分布完成后,集群才会正常工作,配置时使用的是槽位的序号,从0开始。
redis-cli -h 192.168.20.161 -p 6380 CLUSTER ADDSLOTS {0..5460}
redis-cli -h 192.168.20.162 -p 6380 CLUSTER ADDSLOTS {5461..10921}
redis-cli -h 192.168.20.163 -p 6380 CLUSTER ADDSLOTS {10922..16383}
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
5、验证集群的可用性
5.1、测试数据写入
[root@node01 ~]# cat set.sh
#!/bin/bash
for i in `seq -w 10000`;
do
redis-cli -h 192.168.20.161 -p 6380 -c set k_$i v_$i
done
bash set.sh
5.2、验证随机性
redis-cli -c -h 192.168.20.161 -p 6380 keys \* > keys_all.txt
cat keys_all.txt |awk -F "_" '{print $2}'|sort -n | head
5.3、检查集群是否健康
#key分布误差
redis-cli --cluster rebalance 192.168.20.161:6380
>>> Performing Cluster Check (using node 192.168.20.161:6380)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.
#key分布情况
redis-cli --cluster info 192.168.20.161:6380
192.168.20.161:6380 (d70d68d2...) -> 3314 keys | 5461 slots | 1 slaves.
192.168.20.162:6380 (9bd06ead...) -> 3348 keys | 5461 slots | 1 slaves.
192.168.20.163:6380 (b1b2dfde...) -> 3338 keys | 5462 slots | 1 slaves.
[OK] 10000 keys in 3 masters.
0.61 keys per slot on average.
6、调整槽位分配错误
6.1、使用工具重新分配槽位
#重新分配槽位
redis-cli --cluster reshard 192.168.20.161:6380
#第一次交互:输入迁出的槽的数量
How many slots do you want to move (from 1 to 16384)? 5461
#第二次交互:输入接受的ID
What is the receiving node ID? cluster2的6380的ID
#第三次交互:输入发送者的ID
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: cluster1的6380的ID
Source node #2: done
#第四次交互:YES!
#重复上面的操作,将槽位正确分配给 192.168.20.162:6380,192.168.20.16:6380 节点
6.2、pipline
前提条件:
1.了解aof格式
2.了解新版本redis默认是开启混合模式的
3.需要修改为普通的aof格式并重启
4.恢复时使用-c参数无效,需要在每一个节点都执行
命令:
redis-cli -c -h 192.168.20.161 -p 6380 --pipe < redis.aof
redis-cli -c -h 192.168.20.162 -p 6380 --pipe < redis.aof
redis-cli -c -h 192.168.20.163 -p 6380 --pipe < redis.aof
7、使用工具搭建集群
7.1、删除上面使用手工搭建的集群
redis-cli -h 192.168.20.161 -p 6380 FLUSHALL
redis-cli -h 192.168.20.162 -p 6380 FLUSHALL
redis-cli -h 192.168.20.163 -p 6380 FLUSHALL
redis-cli -h 192.168.20.161 -p 6380 CLUSTER RESET
redis-cli -h 192.168.20.162 -p 6380 CLUSTER RESET
redis-cli -h 192.168.20.163 -p 6380 CLUSTER RESET
redis-cli -h 192.168.20.161 -p 6381 CLUSTER RESET
redis-cli -h 192.168.20.162 -p 6381 CLUSTER RESET
redis-cli -h 192.168.20.163 -p 6381 CLUSTER RESET
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
7.2、使用命令一键搭建
redis-cli --cluster create 192.168.20.161:6380 192.168.20.162:6380 192.168.20.163:6380 192.168.20.161:6381 192.168.20.162:6381 192.168.20.163:6381 --cluster-replicas 1
7.3、检查集群状态
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
redis-cli --cluster info 192.168.20.161:6380
redis-cli --cluster check 192.168.20.161:6380
8、集群扩容
8.0、原理图
8.1、创建新节点
#创建目录
mkdir -p /opt/{6390,6391}/{log,pid,etc}
#添加配置文件
cp /opt/6380/etc/redis.conf /opt/6390/etc/
cp /opt/6380/etc/redis.conf /opt/6391/etc/
sed -i "s/6380/6390/g" /opt/6390/etc/redis.conf
sed -i "s/6380/6391/g" /opt/6391/etc/redis.conf
#启动
redis-server /opt/6390/etc/redis.conf
redis-server /opt/6391/etc/redis.conf
#因为是在cluster01,上添加两个节点,所以需要cluster01上添加防火墙规则。
firewall-cmd --permanent --add-port=6390/tcp
firewall-cmd --permanent --add-port=6391/tcp
firewall-cmd --permanent --add-port=16390/tcp
firewall-cmd --permanent --add-port=16391/tcp
firewall-cmd --reload
8.2、添加节点
redis-cli -h 192.168.20.161 -p 6380 cluster meet 192.168.20.161 6390
redis-cli -h 192.168.20.161 -p 6380 cluster meet 192.168.20.161 6391
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
8.3、添加主从关系
redis-cli -h 192.168.20.161 -p 6391 CLUSTER REPLICATE 01ef4f1ab3102603892ceb55904965ab3211f9eb
8.4、分配hash slot
#重新分配槽位
redis-cli --cluster reshard 192.168.20.161:6380
#第一次交互:从已经构建的集群中拿出多少
How many slots do you want to move (from 1 to 16384)? 4096
#第二次交互:接受节点的ID是什么
What is the receiving node ID? 6390的ID
#第三次交互:哪些节点需要导出,这里输入all,则会自动的从每个节点拿出一些槽位,交给第四个节点。
Source node #1: all
#第四次交互:确认是否执行
Do you want to proceed with the proposed reshard plan (yes/no)? yes
8.5、集群状态
* redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
* redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
9、集群收缩
9.1、原理图
9.2、重新分配
重新分配槽位
redis-cli --cluster reshard 192.168.20.161:6380
第一次交互:需要迁移多少个槽位
How many slots do you want to move (from 1 to 16384)? 1365
第二次交互:接受节点的ID是什么
What is the receiving node ID? 6380的ID
第三次交互:哪些节点需要导出
Source node #1: 6390的ID
Source node #2: done
第四次交互:确认
Do you want to proceed with the proposed reshard plan (yes/no)? yes
重复上面的操作,直到6390所有的槽位都被分配出去了
检查集群状态,确认6390没有槽位了
redis-cli --cluster info 192.168.20.161:6380
9.3、删除节点
redis-cli --cluster del-node 192.168.20.161:6390 01ef4f1ab3102603892ceb55904965ab3211f9eb
redis-cli --cluster del-node 192.168.20.161:6391 e897b069b8e869a2f04a0774bbdf2327dc546cca
9.4、验证集群状态
redis-cli -h 192.168.20.161 -p 6380 CLUSTER INFO
redis-cli --cluster info 192.168.20.161:6380
10、验证高可用
10.1、查看集群节点信息
redis-cli -h 192.168.20.161 -p 6380 CLUSTER NODES
10.2、模拟故障
#停止主节点 192.168.20.161:6380
[root@node01 ~]# ps aux|grep redis
root 20335 0.2 0.1 146004 3404 ? Ssl 16:11 0:29 redis-server 0.0.0.0:6380 [cluster]
root 20340 0.1 0.1 146404 3652 ? Ssl 16:11 0:24 redis-server 0.0.0.0:6381 [cluster]
#杀死主节点
kill 20335
#查看信息
redis-cli -h 192.168.20.161 -p 6381 CLUSTER NODES
#再重新启动节点 192.168.20.161:6380
redis-server /opt/6380/etc/redis.conf
#再次查看状态
redis-cli -h 192.168.20.161 -p 6381 CLUSTER NODES
10.3、总结
1.主库挂了,从库会自动接替主库的角色,集群恢复正常会受超时时间控制
2.老的主库修复上线后,会自动变成从库,同步新的主库