使用 Docker 一键搭建 Redis Cluster
Redis Cluster 6.0.10 已经发布了,还没有找到一键搭建 Mac 测试环境的命令。Goframe 框架的 Redis 好像还不支持 Cluster,于是准备装一个集群进行测试。
集群模式介绍
Redis Cluster是社区版推出的Redis分布式集群解决方案,主要解决Redis分布式方面的需求,比如,当遇到单机内存,并发和流量等瓶颈的时候,Redis Cluster能起到很好的负载均衡的目的。
Redis Cluster着眼于提高并发量。
群集至少需要3主3从,且每个实例使用不同的配置文件。
在redis-cluster架构中,redis-master节点一般用于接收读写,而redis-slave节点则一般只用于备份, 其与对应的master拥有相同的slot集合,若某个redis-master意外失效,则再将其对应的slave进行升级为临时redis-master。
在redis的官方文档中,对redis-cluster架构上,有这样的说明:在cluster架构下,默认的,一般redis-master用于接收读写,而redis-slave则用于备份,当有请求是在向slave发起时,会直接重定向到对应key所在的master来处理。 但如果不介意读取的是redis-cluster中有可能过期的数据并且对写请求不感兴趣时,则亦可通过readonly命令,将slave设置成可读,然后通过slave获取相关的key,达到读写分离。具体可以参阅redis官方文档等相关内容
自己整理了一下,命令如下:
建立配置模板
port ${PORT}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip ${IP}
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes
将上述内容保存为 redis-cluster.tmpl
,参数名如下
# redis端口
port ${PORT}
# 关闭保护模式
protected-mode no
# 开启集群
cluster-enabled yes
# 集群节点配置
cluster-config-file nodes.conf
# 超时
cluster-node-timeout 5000
# 集群节点IP host模式为宿主机IP
cluster-announce-ip 192.168.124.5
# 集群节点端口 7001 - 7006
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
# 开启 appendonly 备份模式
appendonly yes
# 每秒钟备份
appendfsync everysec
# 对aof文件进行压缩时,是否执行同步操作
no-appendfsync-on-rewrite no
# 当目前aof文件大小超过上一次重写时的aof文件大小的100%时会再次进行重写
auto-aof-rewrite-percentage 100
# 重写前AOF文件的大小最小值 默认 64mb
auto-aof-rewrite-min-size 64mb
创建 Docker 虚拟网络
docker network create redis
docker network inspect redis
创建一键启动脚本
p=$(pwd)
ip=$(ifconfig en0 | grep "inet " | awk '{print $2}')
shell="/usr/local/bin/redis-cli --cluster create "
for port in $(seq 8010 8015); do
echo "create config file for " $port
rm -rf ./${port}
mkdir -p ./${port}/conf \
&& IP=${ip} PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf \
&& mkdir -p ./${port}/data;
shell="$shell $ip:$port"
done
for port in $(seq 8010 8015); do
echo "create pod for " $port
docker stop redis-${port} >> /dev/null
docker rm redis-${port} >> /dev/null
docker run -it -d -p ${port}:${port} -p 1${port}:1${port} \
--privileged=true -v $p/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
--privileged=true -v $p/${port}/data:/data \
--restart always --name redis-${port} --net redis \
--sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
done
echo "you should run this script to starting cluster"
echo "$shell"
docker exec -it redis-8010 bash
将上述内容保存为 start.sh
即可运行,其中 nc0
需要修改为你本机的宿主网卡,如 WIFI 或者有线网卡。
执行结果如下:
create config file for 8010
create config file for 8011
create config file for 8012
create config file for 8013
create config file for 8014
create config file for 8015
create pod for 8010
cc68f32f836ac845c5515269f9371c50ca62e4d4aaf28c7479f2eb2a046cb605
create pod for 8011
018fbc1b557a01aa147eb5ccdde73c2d355071e5447739998b7b605e1a5e0d80
create pod for 8012
6c87629efdde55afc0a093f1ea180204a9475db5071bd45df1b2a534096727ad
create pod for 8013
f2a83070e11f5fbabd8728d39a076e5befb2bdc7efd2bedb8c294bf3fc80957b
create pod for 8014
6320501af030000e383aac1731ca9d908e184c1057a801c51f6676eba78b45cd
create pod for 8015
3fe4f8f4f3acf5b3ba44cd50ef01056a89281a1e046b44e04f9c4c13996197d0
you should run this script to starting cluster
/usr/local/bin/redis-cli --cluster-replicas 1 --cluster create 192.168.17.117:8010 192.168.17.117:8011 192.168.17.117:8012 192.168.17.117:8013 192.168.17.117:8014 192.168.17.117:8015
117:8013 192.168.17.117:8014 192.168.17.117:8015 192.168.17.117:8012 192.168.17.1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.17.117:8014 to 192.168.17.117:8010
Adding replica 192.168.17.117:8015 to 192.168.17.117:8011
Adding replica 192.168.17.117:8013 to 192.168.17.117:8012
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: f79cf8e7f6578e4fcf605629492d24ee5a28c342 192.168.17.117:8010
slots:[0-5460] (5461 slots) master
M: 63278b067faa1b7a247cfed1267acbcd4b5febd1 192.168.17.117:8011
slots:[5461-10922] (5462 slots) master
M: 1ed31b17403eb1739fe19e76eba9f143dbd6db64 192.168.17.117:8012
slots:[10923-16383] (5461 slots) master
S: 1b93607a971564a3f743d3862556af95a4d9f3d0 192.168.17.117:8013
replicates 1ed31b17403eb1739fe19e76eba9f143dbd6db64
S: 27b0febdaa85e3f1fa268eea0236eacbf0d79e4a 192.168.17.117:8014
replicates f79cf8e7f6578e4fcf605629492d24ee5a28c342
S: 082198a46fee0e941e446b5e00d994a5d569f975 192.168.17.117:8015
replicates 63278b067faa1b7a247cfed1267acbcd4b5febd1
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 192.168.17.117:8010)
M: f79cf8e7f6578e4fcf605629492d24ee5a28c342 192.168.17.117:8010
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 1b93607a971564a3f743d3862556af95a4d9f3d0 192.168.17.117:8013
slots: (0 slots) slave
replicates 1ed31b17403eb1739fe19e76eba9f143dbd6db64
M: 1ed31b17403eb1739fe19e76eba9f143dbd6db64 192.168.17.117:8012
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 082198a46fee0e941e446b5e00d994a5d569f975 192.168.17.117:8015
slots: (0 slots) slave
replicates 63278b067faa1b7a247cfed1267acbcd4b5febd1
M: 63278b067faa1b7a247cfed1267acbcd4b5febd1 192.168.17.117:8011
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 27b0febdaa85e3f1fa268eea0236eacbf0d79e4a 192.168.17.117:8014
slots: (0 slots) slave
replicates f79cf8e7f6578e4fcf605629492d24ee5a28c342
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
root@cc68f32f836a:/data#
请注意 /usr/local/bin/redis-cli --cluster-replicas 1 --cluster create 192.168.17.117:8010 192.168.17.117:8011 192.168.17.117:8012 192.168.17.117:8013 192.168.17.117:8014 192.168.17.117:8015 117:8013 192.168.17.117:8014 192.168.17.117:8015 192.168.17.117:8012 192.168.17.1
即可完成创建。 命令是创建 cluster 的命令,有个
--cluster-replicas 1 参数,回车以后输入
Yes
集群模式下的操作方法
自动跳转
由于Redis Cluster会根据key进行hash运算,然后将key分散到不同slots,name的hash运算结果在不同节点上的slots中。读写的时候则会进行提示,Key 已经 moved
到指点的节点
root@cc68f32f836a:/data# redis-cli -p 8010 get aaa
(error) MOVED 10439 192.168.17.117:8011
通过命令行读写的时候,可以加参数 -c
自动跟随
root@cc68f32f836a:/data# redis-cli -p 8010 -c get aaa
"ok"
查看集群状态
root@cc68f32f836a:/data# redis-cli -p 8010 -c cluster nodes
1b93607a971564a3f743d3862556af95a4d9f3d0 192.168.17.117:8013@18013 slave 1ed31b17403eb1739fe19e76eba9f143dbd6db64 0 1610963851866 3 connected
1ed31b17403eb1739fe19e76eba9f143dbd6db64 192.168.17.117:8012@18012 master - 0 1610963851000 3 connected 10923-16383
082198a46fee0e941e446b5e00d994a5d569f975 192.168.17.117:8015@18015 slave 63278b067faa1b7a247cfed1267acbcd4b5febd1 0 1610963850545 2 connected
f79cf8e7f6578e4fcf605629492d24ee5a28c342 192.168.17.117:8010@18010 myself,master - 0 1610963851000 1 connected 0-5460
63278b067faa1b7a247cfed1267acbcd4b5febd1 192.168.17.117:8011@18011 master - 0 1610963851558 2 connected 5461-10922
27b0febdaa85e3f1fa268eea0236eacbf0d79e4a 192.168.17.117:8014@18014 slave f79cf8e7f6578e4fcf605629492d24ee5a28c342 0 1610963851152 1 connected
查看slots分片
root@cc68f32f836a:/data# redis-cli -p 8010 -c cluster slots
1) 1) (integer) 10923
2) (integer) 16383
3) 1) "192.168.17.117"
2) (integer) 8012
3) "1ed31b17403eb1739fe19e76eba9f143dbd6db64"
4) 1) "192.168.17.117"
2) (integer) 8013
3) "1b93607a971564a3f743d3862556af95a4d9f3d0"
2) 1) (integer) 0
2) (integer) 5460
3) 1) "192.168.17.117"
2) (integer) 8010
3) "f79cf8e7f6578e4fcf605629492d24ee5a28c342"
4) 1) "192.168.17.117"
2) (integer) 8014
3) "27b0febdaa85e3f1fa268eea0236eacbf0d79e4a"
3) 1) (integer) 5461
2) (integer) 10922
3) 1) "192.168.17.117"
2) (integer) 8011
3) "63278b067faa1b7a247cfed1267acbcd4b5febd1"
4) 1) "192.168.17.117"
2) (integer) 8015
3) "082198a46fee0e941e446b5e00d994a5d569f975"
查看集群信息
root@cc68f32f836a:/data# redis-cli -p 8010 -c cluster info
root@cc68f32f836a:/data# redis-cli -p 8010 -c cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:683
cluster_stats_messages_pong_sent:692
cluster_stats_messages_sent:1375
cluster_stats_messages_ping_received:687
cluster_stats_messages_pong_received:683
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:1375
读写分离
在redis的官方文档中,对redis-cluster架构上,有这样的说明:在cluster架构下,默认的,一般redis-master用于接收读写,而redis-slave则用于备份,当有请求是在向slave发起时,会直接重定向到对应key所在的master来处理。
但如果不介意读取的是redis-cluster中有可能过期的数据并且对写请求不感兴趣时,则亦可通过readonly
命令,将slave设置成可读,然后通过slave获取相关的key,达到读写分离。
容灾
在创建集群时,如果启用 --cluster-replicas 1
参数,集群将会自动在 master 异常时提升一个 slave 为 master。