Docker搭建redis集群

Docker搭建redis集群

    在《Redis的三种集群模式这篇文章中,我们初步认识了redis三种不同的集群模式,接下来这篇文章,我们再通过实际部署搭建来对它们进行进一步的学习和了解。

    一、主从复制模式

    前提条件

    这里准备了三台虚拟主机:192.168.205.10、192.168.205.11、192.168.205.12

  •     三台主机均安装好centos7系统
  •     三台主机均安装好docker并启动docker(我这里安装的docker版本为20.10.7)
  •     三台主机拉取redis镜像(我这里使用redis6.2.2版本,并将镜像推送到了私有仓库)

     

    1、三台主机都要进行的操作

    1)创建存放redis.conf文件的目录

    mkdir -p  /root/hxq/redis

    2)拉取redis配置文件

    确定系统下是否安装wget命令,如果没有,则执行安装命令:yum -y install wget

    执行命令:

    cd /root/hxq/redis

    wget -c http://download.redis.io/redis-stable/redis.conf

    3)启动redis容器

    docker run --name redis -v /root/hxq/redis/redis.conf:/usr/local/etc/redis/redis.conf -d -p 6379:6379  192.168.205.10:5000/redis:6.2.2

    说明:

    -p 端口映射,6379是redis端口 

    192.168.205.10:5000/redis:6.2.2为镜像名称

    2、进入三台主机redis容器内部

    1)进入redis容器: docker exec -it 容器id/容器名称 /bin/bash

    2)进入redis客户端:redis-cli

    3)查询当前主机redis的信息

    执行命令:info replication

    

   我们发现三台都是主节点

   3、手动绑定主节点

   说明:这里以192.168.205.10为主节点,192.168.205.11和192.168.205.12为从节点

   1)分布进入11和12主机上的redis容器内部,进入redis客户端

   执行命令:redis-cli

   2)绑定主redis信息:SLAVEOF  主ip   主端口

  执行命令:SLAVEOF  192.168.205.10  6379

   3)info 查询节点信息

   

   我们再进入10服务器,查看节点信息:

   

   至此,redis主从已经搭建完毕

  4、测试主从复制

     1)测试读写数据

    主节点写入数据

     

     从节点同步数据

     

     从节点没有写入权限

     

    由此我们可以看出,主可以读写,从只能读。这也是redis集群的特点:读写分离。

    2)客户端连接

    建议用主节点连接就可以了,因为可以读写。用从节点只能读取数据。

    

    另外,我们可以进一步认识到主从复制的缺点:

    1)不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复

    2)难以支持在线扩容,Redis的容量受限于单机配置

 

    二、哨兵模式(Sentinel)

    在redis主从复制基础上搭建redis哨兵模式

    1、配置文件

    有两种方式创建sentinel.conf:

    1)通过wget命令获取sentinel的配置文件

    wget http://download.redis.io/redis-stable/sentinel.conf

    然后再根据实际情况进行修改

    2)手动创建

    cd  /root/hxq/redis-sentinel

    vim sentinel.conf

 1 port 26379
 2 
 3 daemonize yes
 4 
 5 logfile "/var/log/redis/sentinel.log"
 6 
 7 # 监控名为redis-master集群;其主节点信息为【192.168.205.10:6379】;当发生意外时,至少有两个节点同意,这里的2为quorum,投票数
 8 
 9 sentinel monitor redis-master 192.168.205.10 6379 2
10 
11 # 监控认为超过5S还没响应,就认为redis-master集群挂了
12 
13 sentinel down-after-milliseconds redis-master 5000
14 
15 # 对sentinel集群暴露自己的ip和端口
16 
17 sentinel announce-ip 192.168.205.10
18 
19 sentinel announce-port 26379

   2、运行哨兵

   docker run -it --name sentinel -p 26379:26379 -v /root/hxq/redis-sentinel/sentinel.conf:/usr/local/etc/redis/sentinel.conf -d  redis镜像名称 bash

   1)进入容器

   docker exec -it sentinel  bash

   2)创建日志目录和文件

   mkdir /var/log/redis

   touch /var/log/redis/sentinel.log

   3)启动哨兵

   redis-sentinel  /usr/local/etc/redis/sentinel.conf

   4)查看日志:

     cat /var/log/redis/sentinel.log

     

     在另外两台机器上按照同样的方法在一个容器中运行sentinel,配置文件有所不同:

     # 对sentinel集群暴露自己的ip和端口

     sentinel announce-ip ip地址

     说明:这里的ip地址为sentinel所在服务器的ip地址,因为这里使用docker启动容器,如果不给定ip地址的话,就会默认使用docker分配的ip地址,就会出现问题

     3、进入sentinel客户端

     redis-cli -p 26379

     执行命令,查看哨兵节点的信息:info sentinel

      

      4、验证failover(故障转移)

      为了验证哨兵机制下的自动主从切换,我们将主服务器192.168.205.10上的redis容器先停掉

      执行命令:docker stop redis

        

      Sentinel包括两个重要的术语:主观下线客观下线

      主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。

      客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。

    5、sentinel服务日志说明

    Sentinel服务启动后会打印一些相关日志信息,以下是相关日志特殊字符说明:

 1 +reset-master :主服务器已被重置。
 2 
 3 +slave :一个新的从服务器已经被 Sentinel 识别并关联。
 4 
 5 +failover-state-reconf-slaves :故障转移状态切换到了reconf-slaves 状态。
 6 
 7 +failover-detected :另一个 Sentinel 开始了一次故障转移操作,或者一个从服务器转换成了主服务器。
 8 
 9 +slave-reconf-sent :领头(leader)的 Sentinel 向实例发送了 SLAVEOF 命令,为实例设置新的主服务器。
10 
11 +slave-reconf-inprog :实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。
12 
13 +slave-reconf-done :从服务器已经成功完成对新主服务器的同步。
14 
15 -dup-sentinel :对给定主服务器进行监视的一个或多个 Sentinel 已经因为重复出现而被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。
16 
17 +sentinel :一个监视给定主服务器的新 Sentinel 已经被识别并添加。
18 
19 +sdown :给定的实例现在处于主观下线状态。
20 
21 -sdown :给定的实例已经不再处于主观下线状态。
22 
23 +odown :给定的实例现在处于客观下线状态。
24 
25 -odown :给定的实例已经不再处于客观下线状态。
26 
27 +new-epoch :当前的纪元(epoch)已经被更新。
28 
29 +try-failover :一个新的故障迁移操作正在执行中,等待被大多数 Sentinel 选中(waiting to be elected by themajority)。
30 
31 +elected-leader :赢得指定纪元的选举,可以进行故障迁移操作了。
32 
33 +failover-state-select-slave :故障转移操作现在处于select-slave 状态 —— Sentinel 正在寻找可以升级为主服务器的从服务器。
34 
35 no-good-slave :Sentinel 操作未能找到适合进行升级的从服务器。Sentinel 会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。
36 
37 selected-slave :Sentinel 顺利找到适合进行升级的从服务器。
38 
39 failover-state-send-slaveof-noone :Sentinel 正在将指定的从服务器升级为主服务器,等待升级功能完成。
40 
41 failover-end-for-timeout :故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器(slaves will eventually be configured to replicate with the newmaster anyway)。
42 
43 failover-end :故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。
44 
45 +switch-master :配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。
46 
47 +tilt :进入 tilt 模式。
48 
49 -tilt :退出 tilt 模式。

   

     三、Redis Cluster集群

    单机部署

     1、创建网络

    1)为什么需要创建网络?

  因为默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。说简单点就是为了让容器可以直接通过容器名称进行通信。

    从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过容器名称进行通信。方法很简单,只要在创建容器时使用 --name 为容器命名即可。

    但是使用 Docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。通过 docker network create 命令可以创建自定义网络模式,默认为 bridge 网桥/桥接模式,完整命令如下:

    docker network create redis-net

    2)查看网络模式

    执行命令:docker network ls 

    

    3)查看网络的详细信息

    执行命令:docker network inspect redis-net

    

    2、编写Redis配置文件

    cd /root/hxq/redis-cluster

    vim  redis-cluster.tmpl

    redis-cluster.tmpl 文件内容如下:

 1 port ${PORT}
 2 
 3 requirepass 1234
 4 
 5 masterauth 1234
 6 
 7 protected-mode no
 8 
 9 daemonize no
10 
11 appendonly yes
12 
13 cluster-enabled yes
14 
15 cluster-config-file nodes.conf
16 
17 cluster-node-timeout 15000
18 
19 cluster-announce-ip 192.168.205.10
20 
21 cluster-announce-port ${PORT}
22 
23 cluster-announce-bus-port 1${PORT}

    1)相关配置参数说明

    2)每个Redis集群节点都需要打开两个TCP连接

    一个用于为客户端提供服务的正常 Redis TCP 端口,例如 6379。还有一个基于 6379 端口加 10000 的端口,比如 16379。

    第二个端口用于集群总线,这是一个使用二进制协议的节点到节点通信通道。节点使用集群总线进行故障检测、配置更新、故障转移授权等等。客户端永远不要尝试与集群总线端口通信,与正常的 Redis 命令端口通信即可,但是请确保防火墙中的这两个端口都已经打开,否则 Redis 集群节点将无法通信。

    在 redis-cluster 目录下执行以下命令:

    循环创建 8001 - 8006 相关的目录及文件

1 for port in `seq 8001 8006`; do \
2 
3   mkdir -p ${port}/conf \
4 
5   && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \
6 
7   && mkdir -p ${port}/data;\
8 
9 done

     查看命令执行结果,如果没有 tree 命令先安装 :yum install -y tree

     执行命令:tree /root/hxq/redis-cluster/

    

    查看每个节点的配置文件详细信息

    cat /root/hxq/redis-cluster/800{1..6}/conf/redis.conf

 1 port 8001
 2 requirepass 1234
 3 masterauth 1234
 4 protected-mode no
 5 daemonize no
 6 appendonly yes
 7 cluster-enabled yes
 8 cluster-config-file nodes.conf
 9 cluster-node-timeout 15000
10 cluster-announce-ip 192.168.205.10
11 cluster-announce-port 8001
12 cluster-announce-bus-port 18001
13 port 8002
14 requirepass 1234
15 masterauth 1234
16 protected-mode no
17 daemonize no
18 appendonly yes
19 cluster-enabled yes
20 cluster-config-file nodes.conf
21 cluster-node-timeout 15000
22 cluster-announce-ip 192.168.205.10
23 cluster-announce-port 8002
24 cluster-announce-bus-port 18002
25 port 8003
26 requirepass 1234
27 masterauth 1234
28 protected-mode no
29 daemonize no
30 appendonly yes
31 cluster-enabled yes
32 cluster-config-file nodes.conf
33 cluster-node-timeout 15000
34 cluster-announce-ip 192.168.205.10
35 cluster-announce-port 8003
36 cluster-announce-bus-port 18003
37 port 8004
38 requirepass 1234
39 masterauth 1234
40 protected-mode no
41 daemonize no
42 appendonly yes
43 cluster-enabled yes
44 cluster-config-file nodes.conf
45 cluster-node-timeout 15000
46 cluster-announce-ip 192.168.205.10
47 cluster-announce-port 8004
48 cluster-announce-bus-port 18004
49 port 8005
50 requirepass 1234
51 masterauth 1234
52 protected-mode no
53 daemonize no
54 appendonly yes
55 cluster-enabled yes
56 cluster-config-file nodes.conf
57 cluster-node-timeout 15000
58 cluster-announce-ip 192.168.205.10
59 cluster-announce-port 8005
60 cluster-announce-bus-port 18005
61 port 8006
62 requirepass 1234
63 masterauth 1234
64 protected-mode no
65 daemonize no
66 appendonly yes
67 cluster-enabled yes
68 cluster-config-file nodes.conf
69 cluster-node-timeout 15000
70 cluster-announce-ip 192.168.205.10
71 cluster-announce-port 8006
72 cluster-announce-bus-port 18006

     3、创建redis容器

     1)创建容器

     将宿主机的 8001 ~ 8006 之间的端口与 6 个 Redis 容器映射,并将宿主机的目录与容器内的目录进行映射(目录挂载)。记得指定网络模式,使用我们自己创建的 redis-net 网络。

 1 for port in $(seq 8001 8006); do \
 2 
 3   docker run -di -p ${port}:${port} -p 1${port}:1${port} \
 4 
 5   --restart always --name redis-${port} --net redis-net \
 6 
 7   -v /root/hxq/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
 8 
 9   -v /root/hxq/redis-cluster/${port}/data:/data \
10 
11   192.168.205.10:5000/redis:6.2.2  redis-server /usr/local/etc/redis/redis.conf; \
12 
13 done

     创建如下图:

     

     查看容器是否创建成功

     执行命令: docker ps -n 6

     

    查看给每个节点分配的IP信息

    docker network inspect redis-net | grep -i -E "name|ipv4address"

    

    4、创建 Redis Cluster集群

    1)进入容器

    docker exec -it redis-8001 bash

    2)切换至指定目录

    cd /usr/local/bin/

    3)执行命令,创建集群

    redis-cli -a 1234 --cluster create 172.19.0.2:8001 172.19.0.3:8002 172.19.0.4:8003 172.19.0.5:8004 172.19.0.6:8005 172.19.0.7:8006 --cluster-replicas 1

    说明:命令中的--cluster-replicas 代表主从节点的比例,这里因为是3主3从,所以参数为1

    创建过程,如下图:

     

    至此一个高可用的 Redis Cluster 集群搭建完成,如下图所示,该集群中包含 6 个 Redis 节点,3 主 3 从。三个主节点会分配槽,处理客户端的命令请求,而从节点可用在主节点故障后,顶替主节点。

    

     4)检查集群状态

    # 使用IP

    redis-cli -a  1234  --cluster  check 192.168.205.10:8001

    # 使用容器名称(推荐这种方式)

    redis-cli  -a  1234  --cluster  check redis-8001:8001

    

    5)查看集群信息和节点信息

    随便进入一个容器节点,然后    cd /usr/local/bin

    # 连接至集群某个节点

    redis-cli -c -a 1234 -h redis-8003 -p 8003

    # 查看集群信息

    cluster info

    #查看集群结点信息

    cluster nodes

    如下图:

     

    6)SET/GET操作

     

    说明:在 Redis Cluster 集群模式中,无论连接哪个节点,每次我们执行写入或者读取操作的时候,所有的键会根据哈希函数运算并映射到 0 ~ 16383 整数槽内,如果恰好对应的槽就在你当前连接的节点中,则直接执行命令,否则重定向至对应节点执行命令。

    7)计算键属于那个槽

    计算公式:slot = CRC16(key) & 16383

    执行命令: cluster keyslot  "name"

    5、客户端连接

 最后测试下客户端连接操作,随便哪个节点,看看可否通过外部访问 Redis Cluster 集群。

    

    

  

    至此使用多个容器搭建 Redis Cluster 集群环境就到这里。

     多机环境

    为了让环境更加真实,我们再用多机环境来部署一遍:

    192.168.10.11

    192.168.10.12

    整体搭建步骤还是分为4步:

  •     下载 Redis 镜像(其实这步可以省略,因为创建容器时,如果本地镜像不存在,就会去远程拉取)
  •     编写 Redis 配置文件
  •     创建 Redis 容器
  •     创建 Redis Cluster 集群

     由于在多机环境与单机环境下部署都很相似,为了让文章篇幅显得不那么冗余,这里只提出与单机部署上有区别的地方。

     1、网络

    按照 Redis 官网的提示,为了使 Docker 与 Redis Cluster 兼容,您需要使用 Docker 的 host 网络模式

    host 网络模式需要在创建容器时通过参数 --net host 或者 --network host 指定,host 网络模式可以让容器共享宿主机网络栈,容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。所以这里不需要自定义网络,在后面创建容器的时候,--net参数需指定为host

    2、配置文件

    cd /root/hxq/redis-cluster

    vi redis-cluster.tmpl

    11机器和12机器上面的配置有所不同:  

    192.168.205.11服务器上面的redis-cluster.tmpl:

port ${PORT}
requirepass 1234
masterauth 1234
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.205.11
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}

    192.168.205.12服务器上面的redis-cluster.tmpl:

 1 port ${PORT}
 2 requirepass 1234
 3 masterauth 1234
 4 protected-mode no
 5 daemonize no
 6 appendonly yes
 7 cluster-enabled yes
 8 cluster-config-file nodes.conf
 9 cluster-node-timeout 15000
10 cluster-announce-ip 192.168.205.12
11 cluster-announce-port ${PORT}
12 cluster-announce-bus-port 1${PORT}

   3、创建配置文件和目录

   1)循环创建相关的目录及文件

    cd /root/hxq/redis-cluster

   11服务器:

1 for port in `seq 8001 8003`; do \
2 
3   mkdir -p ${port}/conf \
4 
5   && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \
6 
7   && mkdir -p ${port}/data;\
8 
9 done

    12服务器:

1 for port in `seq 8004 8006`; do \
2 
3   mkdir -p ${port}/conf \
4 
5   && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \
6 
7   && mkdir -p ${port}/data;\
8 
9 done

    2)查看配置文件 

    如果未安装tree命令,则执行:yum install -y tree

    tree  /root/hxq/redis-cluster

    11服务器:cat /root/hxq/redis-cluster/800{1..3}/conf/redis.conf

    12服务器:cat /root/hxq/redis-cluster/800{4..6}/conf/redis.conf

     4、创建Redis容器

    11服务器上面,创建容器:

 1 for port in $(seq 8001 8003); do \
 2 
 3   docker run -di --restart always --name redis-${port} --net host \
 4 
 5   -v /root/hxq/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
 6 
 7   -v /root/hxq/redis-cluster/${port}/data:/data \
 8 
 9   192.168.205.10:5000/redis:6.2.2 redis-server /usr/local/etc/redis/redis.conf; \
10 
11 done

     12服务器上面,创建容器:

 1 for port in $(seq 8004 8006); do \
 2 
 3   docker run -di --restart always --name redis-${port} --net host \
 4 
 5   -v /root/hxq/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
 6 
 7   -v /root/hxq/redis-cluster/${port}/data:/data \
 8 
 9   192.168.205.10:5000/redis:6.2.2  redis-server /usr/local/etc/redis/redis.conf; \
10 
11 done

    查看容器是否创建成功:docker ps -n 3 

   注意:这里创建容器时,指定--net为host

    5、创建 Redis Cluster 集群

   1)随便进入一个容器节点,并进入 /usr/local/bin/ 目录

    docker exec -it  redis-8001 bash

    cd  /usr/local/bin/

   2)创建集群

   redis-cli -a 1234 --cluster create 192.168.205.11:8001 192.168.205.11:8002 192.168.205.11:8003 192.168.205.12:8004 192.168.205.12:8005 192.168.205.12:8006 --cluster-replicas 1

   

   6、连接至集群某个节点

   redis-cli -c -a 1234 -h 192.168.205.11 -p 8001

   注意:因为使用host模式,这个地方-h参数 应该取宿主机ip地址

   

   至此一个高可用的 Redis Cluster 集群搭建完成。

 

 

   参考链接:

   https://cloud.tencent.com/developer/article/1474195

   https://juejin.cn/post/6844903908398071815

   https://juejin.cn/post/6868814738751488008

   https://cloud.tencent.com/developer/news/688466

posted @ 2021-08-14 10:28  欢乐豆123  阅读(1374)  评论(0编辑  收藏  举报