通过 Docker 部署 Redis 集群 网友:绝了
Hi,各位读者们,我是你们的鸭哥!
由于最近公众号的改版,为了保证你们第一时间能看到鸭哥的文章,大家记得将公众号 加星标置顶 哦!
作者:超级小豆丁http://www.mydlq.club/article/93
# 什么是 Redis 集群模式
# 为什么需要 Redis 集群
高可用性:Redis 在集群模式下每个 Master 都是主从复制模式,其 Master 节点上的数据会实时同步到 Slave 节点上,当 Master 节点不可用时,其对应的 Slave 节点身份会更改为 Master 节点,保证集群的可用性。
数据横向扩展:Redis 是一个内存数据库,所有数据都存在内存中,在单节点中所在服务器能给与的内存是有一定限制。当数据量达到一定程度后,内存将不足以支撑这么多的数据存储,这时候需要将数据进行分片存储,而 Redis 集群模式就是将数据分片存储,非常方便横向扩展。
# Redis 集群的数据分片
节点 A 包含 0 到 5460 号哈希槽;
节点 B 包含 5461 到 10922 号哈希槽;
节点 C 包含 10923 到 16383 号哈希槽;
集群中的主从模型
在部署 Redis 集群模式时,至少需要六个节点组成集群才能保证集群的可用性。
# 主从复制的相关概念
全量复制: 用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点。当数据量过大的时候,会造成很大的网络开销。
增量复制: 用于处理在主从复制中因网络闪退等原因造成数据丢失场景,当从节点再次连上主节点,如果条件允许,主节点会补发丢失数据给从节点,因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销。但需要注意,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。
参与复制的主从节点都会维护自身复制偏移量,主节点在处理完写入命令操作后,会把命令的字节长度做累加记录,可以使用 info replication 命令查询 master_repl_offset 偏移量信息。
从节点每秒钟上报自身的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量。
从节点在接收到主节点发送的命令后,也会累加记录自身的偏移量,可以使用 info replication 命令查询 slave_repl_offset 偏移量信息。
复制积压缓冲区(backlog)是保存在主节点上的一个固定长度的队列,默认大小为 1MB,当主节点有连接的从节点时被创建,这时主节点响应写命令时,不但会把命令发给从节点,还会写入复制积压缓冲区,作为写命令的备份。
除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset) 。由于复制积压缓冲区定长且先进先出,所以它保存的是主节点最近执行的写命令,时间较早的写命令会被挤出缓冲区。
每个 Redis 节点启动后都会动态分配一个 40 位的十六进制字符串为运行 ID。运行 ID 的主要作用是来唯一识别 Redis 节点,比如,从节点保存主节点的运行 ID 识别自已正在复制是哪个主节点。如果只使用 IP + Port 的方式识别主节点,那么主节点重启变更了整体数据集(如替换 RDB/AOF 文件),从节点再基于偏移量复制数据将是不安全的,因此当运行 ID 变化后从节点将做全量复制。可以在 info server 命令查看当前节点的运行 ID。
需要注意的是 Redis 关闭再启动,运行的 ID 会随之变化。
# 主从复制的执行过程
从节点使用 psync 从主节点获取 runid 与 offset。
主节点会根据自身情况返回响应信息,可能是 FULLRESYNC runid offset 触发全量复制,可能是 CONTINUE 触发增量复制。
# Redis 集群相关概念
Redis 集群间通信机制
Redis 集群失败状态
Redis 集群重新分片机制
新增节点:别的节点上的槽分一些出来给新的节点
删除节点:删除节点的槽分给别的节点
Redis 集群的不足
复制结构只支持单层结构,不支持树型结构。
不支持多数据库,只能使用 0 数据库,执行 select 0 命令;
键是数据分区的最小粒度,不能将一个很大的键值对映射到不同的节点;
键事务支持有限,当多个键分布在不同节点时无法使用事务,同一节点才能支持事务;
键的批量操作支持有限,比如 mset, mget 命令,如果多个键映射在不同的槽中,就不能正常使用这些命令了;
Redis 群集配置参数
cluster-config-file: 设置 Redis 集群配置信息及状态的存储位置,该文件由 Redis 集群生成,我们只能指定其存储的位置。
cluster-node-timeout: 设置 Redis 群集节点的通信的超时时间;
cluster-migration-barrier: 主节点需要的最小从节点数,只有达到这个数,主节点失败时,它从节点才会进行迁移。
cluster-enabled: 是否开启 Redis 集群模式。
yes:启用 Redis 群集;
no:不启用集群模式;
cluster-require-full-coverage: 设置集群可用性。
yes:表示当负责一个插槽的主库下线,且没有相应的从库进行故障恢复时,集群不可用,下面论证该情况。
no:表示当负责一个插槽的主库下线且没有相应的从库进行故障恢复时,集群仍然可用,下面论证该情况。
cluster-slave-validity-factor:
0:则无论从节点与主节点失联多久,从节点都会尝试升级成主节点。
正数:则 cluster-node-timeout * cluster-slave-validity-factor 得到的时间,是从节点与主节点失联后,此从节点数据有效的最长时间,超过这个时间,从节点不会启动故障迁移。假设 cluster-node-timeout=5,cluster-slave-validity-factor=10,则如果从节点跟主节点失联超过50秒,此从节点不能成为主节点。
# Docker 部署 Redis 集群
1、Redis 部署机器分配
2、创建数据存储目录
$ mkdir -p /var/lib/redis/7000 & mkdir -p /var/lib/redis/7003
$ mkdir -p /var/lib/redis/7001 & mkdir -p /var/lib/redis/7004
$ mkdir -p /var/lib/redis/7002 & mkdir -p /var/lib/redis/7005
3、创建 Redis 配置文件
## 7000 端口配置文件
$ cat > /var/lib/redis/7000/redis.conf << EOF
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize no
protected-mode no
pidfile /data/redis.pid
EOF
## 7003 端口配置文件
$ cat > /var/lib/redis/7003/redis.conf << EOF
port 7003
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize no
protected-mode no
pidfile /data/redis.pid
EOF
## 7001 端口配置:redis.conf
$ cat > /var/lib/redis/7001/redis.conf << EOF
port 7001
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize no
protected-mode no
pidfile /data/redis.pid
EOF
## 7004 端口配置:redis-7004.conf
$ cat > /var/lib/redis/7004/redis.conf << EOF
port 7004
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize no
protected-mode no
pidfile /data/redis.pid
EOF
## 7002 端口配置:redis-7002.conf
$ cat > /var/lib/redis/7002/redis.conf << EOF
port 7002
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize no
protected-mode no
pidfile /data/redis.pid
EOF
## 7005 端口配置:redis-7005.conf
$ cat > /var/lib/redis/7005/redis.conf << EOF
port 7005
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize no
protected-mode no
pidfile /data/redis.pid
EOF
4、提前拉取 Redis 镜像
$ docker pull redis:6.0.8
5、运行启动 Redis 镜像
-d:设置容器后台运行;
-v:指定挂载的宿主机存储目录;
--name:指定运行后的容器名称;
--cpus:指定容器使用 CPU 数量;
--memory:限制容器使用内存数量;
--memory-swap:指定交换内存大小,这里设置为 0,即不用交换内存;
--net:指定 Docker 使用的网络模式;
--restart:指定 Docker 重启时容器的重启策略;
--privileged:设置容器拥有特权,能够获取宿主机 Root 权限;
## 运行 Redis 镜像 7000 端口
$ docker run -d -v /var/lib/redis/7000:/data \
--cpus=1 --memory=2GB --memory-swap=0 \
--privileged=true \
--restart=always \
--net host \
--name redis-7000 \
redis:6.0.8 redis-server /data/redis.conf
## 运行 Redis 镜像 7003 端口
$ docker run -d -v /var/lib/redis/7003:/data \
--cpus=1 --memory=2GB --memory-swap=0 \
--privileged=true \
--restart=always \
--net host \
--name redis-7003 \
redis:6.0.8 redis-server /data/redis.conf
## 运行 Redis 镜像 7001 端口
$ docker run -d -v /var/lib/redis/7001:/data \
--cpus=1 --memory=2GB --memory-swap=0 \
--privileged=true \
--restart=always \
--net host \
--name redis-7001 \
redis:6.0.8 redis-server /data/redis.conf
## 运行 Redis 镜像 7004端口
$ docker run -d -v /var/lib/redis/7004:/data \
--cpus=1 --memory=2GB --memory-swap=0 \
--privileged=true \
--restart=always \
--net host \
--name redis-7004 \
redis:6.0.8 redis-server /data/redis.conf
## 运行 Redis 镜像 7002 端口
$ docker run -d -v /var/lib/redis/7002:/data \
--cpus=1 --memory=2GB --memory-swap=0 \
--privileged=true \
--restart=always \
--net host \
--name redis-7002 \
redis:6.0.8 redis-server /data/redis.conf
## 运行 Redis 镜像 7005 端口
$ docker run -d -v /var/lib/redis/7005:/data \
--cpus=1 --memory=2GB --memory-swap=0 \
--privileged=true \
--restart=always \
--net host \
--name redis-7005 \
redis:6.0.8 redis-server /data/redis.conf
6、创建 Redis 集群
-p:指定连接 Redis 的端口;
create:创建 Redis 集群;
--cluster:使用 Redis 集群模式命令;
--cluster-replicas:指定副本数(slave 数量);
$ docker exec -it redis-7000 \
redis-cli -p 7000 --cluster create \
192.168.2.11:7000 192.168.2.12:7001 192.168.2.13:7002 \
192.168.2.11:7003 192.168.2.12:7004 192.168.2.13:7005 \
--cluster-replicas 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.2.12:7004 to 192.168.2.11:7000
Adding replica 192.168.2.13:7005 to 192.168.2.12:7001
Adding replica 192.168.2.11:7003 to 192.168.2.13:7002
M: 5e50824c55d4df42db4d2987796f0c0b468c273f 192.168.2.11:7000
slots:[0-5460] (5461 slots) master
M: 36565e0273fd62921aa1f2d85c5f7ac98a5b9466 192.168.2.12:7001
slots:[5461-10922] (5462 slots) master
M: 0cc1aaf960defae7332e9256dd25ee5e5c99e65f 192.168.2.13:7002
slots:[10923-16383] (5461 slots) master
S: 42d6e3979395ba93cd1352b6d17044f6b25d9379 192.168.2.11:7003
replicates 0cc1aaf960defae7332e9256dd25ee5e5c99e65f
S: ac5d34b57a8f73dabc60d3a56469055ec64fcde7 192.168.2.12:7004
replicates 5e50824c55d4df42db4d2987796f0c0b468c273f
S: 470b7ff823f10a309fb07311097456210506f6d8 192.168.2.13:7005
replicates 36565e0273fd62921aa1f2d85c5f7ac98a5b9466
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.2.11:7000)
M: 5e50824c55d4df42db4d2987796f0c0b468c273f 192.168.2.11:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 470b7ff823f10a309fb07311097456210506f6d8 192.168.2.13:7005
slots: (0 slots) slave
replicates 36565e0273fd62921aa1f2d85c5f7ac98a5b9466
S: 42d6e3979395ba93cd1352b6d17044f6b25d9379 192.168.2.11:7003
slots: (0 slots) slave
replicates 0cc1aaf960defae7332e9256dd25ee5e5c99e65f
S: ac5d34b57a8f73dabc60d3a56469055ec64fcde7 192.168.2.12:7004
slots: (0 slots) slave
replicates 5e50824c55d4df42db4d2987796f0c0b468c273f
M: 0cc1aaf960defae7332e9256dd25ee5e5c99e65f 192.168.2.13:7002
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 36565e0273fd62921aa1f2d85c5f7ac98a5b9466 192.168.2.12:7001
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
7、查看集群信息
-p:指定连接 Redis 的端点;
-c:使用集群模式;
$ docker exec -it redis-7000 redis-cli -p 7000 -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:866
cluster_stats_messages_pong_sent:854
cluster_stats_messages_sent:1720
cluster_stats_messages_ping_received:849
cluster_stats_messages_pong_received:866
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:1720
> cluster nodes
470b7ff823f10a309fb07311097456210506f6d8 192.168.2.13:7005@17005 slave 36565e0273fd62921aa1f2d85c5f7ac98a5b9466 0 1600267217000 2 connected
42d6e3979395ba93cd1352b6d17044f6b25d9379 192.168.2.11:7003@17003 slave 0cc1aaf960defae7332e9256dd25ee5e5c99e65f 0 1600267218171 3 connected
ac5d34b57a8f73dabc60d3a56469055ec64fcde7 192.168.2.12:7004@17004 slave 5e50824c55d4df42db4d2987796f0c0b468c273f 0 1600267216161 1 connected
0cc1aaf960defae7332e9256dd25ee5e5c99e65f 192.168.2.13:7002@17002 master - 0 1600267218070 3 connected 10923-16383
36565e0273fd62921aa1f2d85c5f7ac98a5b9466 192.168.2.12:7001@17001 master - 0 1600267217163 2 connected 5461-10922
5e50824c55d4df42db4d2987796f0c0b468c273f 192.168.2.11:7000@17000 myself,master - 0 1600267217000 1 connected 0-5460
http://www.redis.cn/topics/cluster-tutorial.html http://www.redis.cn/topics/cluster-spec.html https://jasonkayzk.github.io https://www.cnblogs.com/kevingrace/p/5685332.html