zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

Docker学习笔记18:docker实例之redis 集群搭建

2023-09-14 09:14:48 时间

Redis 集群是一个提供在多个 Redis 节点间共享数据的程序集。

Redis 集群并不支持处理多个 keys 的命令,因为这需要在不同的节点间移动数据,从而达不到像 Redis 那样的性能,在高负载的情况下可能会导致不可预料的错误.

Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。

Redis 集群的优势:

  • 自动分割数据到不同的节点上。
  • 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

Redis 集群没有使用一致性 hash, 而是引入了哈希槽的概念。Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。

1、下载 redis.conf

下载地址:https://github.com/antirez/redis/blob/unstable/redis.conf

2、修改 redis.conf

开启集群功能:

cluster-enabled yes

设置节点端口:

port 6391

节点超时时间,单位毫秒:

cluster-node-timeout 15000

集群内部配置文件:

cluster-config-file "nodes-6379.conf"

3、编写 docker-compose.yml

节点规划图如下:注意,这里是同一个网段的,要不然,后期还需要调整容器网络互联。

容器名称容器IP地址映射端口号服务运行模式
 redis-master1172.50.0.26391->6391master
 redis-master2172.50.0.36392->6392master
 redis-master3172.50.0.46393->6393master
redis-slave1172.50.0.56394->6394slave
redis-slave2172.50.0.66395->6395slave
redis-slave3172.50.0.76396->6396slave

配置如下:

version: "3" #这里版本不要写太高
services:
  redis-master1: 
     image: redis:5.0 # 基础镜像
     container_name: redis-master1 # 容器服务名
     working_dir: /config # 工作目录
     environment: # 环境变量
       - PORT=6391 # 跟 config/nodes-6391.conf 里的配置一样的端口
     ports: # 映射端口,对外提供服务
       - "6391:6391" # redis 的服务端口
       - "16391:16391" # redis 集群监控端口
     stdin_open: true # 标准输入打开
     networks: # docker 网络设置
        redis-master:
            ipv4_address: 172.50.0.2
     tty: true
     privileged: true # 拥有容器内命令执行的权限
     volumes: ["/config:/config"] # 映射数据卷,配置目录
     entrypoint: # 设置服务默认的启动程序
       - /bin/bash
       - redis.sh
  redis-master2:
       image: redis:5.0
       working_dir: /config
       container_name: redis-master2
       environment:
              - PORT=6392
       networks:
          redis-master:
             ipv4_address: 172.50.0.3
       ports:
         - "6392:6392"
         - "16392:16392"
       stdin_open: true
       tty: true
       privileged: true
       volumes: ["/config:/config"]
       entrypoint:
         - /bin/bash
         - redis.sh
  redis-master3:
       image: redis:5.0
       container_name: redis-master3
       working_dir: /config
       environment:
              - PORT=6393
       networks:
          redis-master:
            ipv4_address: 172.50.0.4
       ports:
         - "6393:6393"
         - "16393:16393"
       stdin_open: true
       tty: true
       privileged: true
       volumes: ["/config:/config"]
       entrypoint:
         - /bin/bash
         - redis.sh
  redis-slave1:
       image: redis:5.0
       container_name: redis-slave1
       working_dir: /config
       environment:
            - PORT=6394
       networks:
          redis-master:
             ipv4_address: 172.50.0.5
       ports:
         - "6394:6394"
         - "16394:16394"
       stdin_open: true
       tty: true
       privileged: true
       volumes: ["/config:/config"]
       entrypoint:
         - /bin/bash
         - redis.sh
  redis-salve2:
       image: redis:5.0
       working_dir: /config
       container_name: redis-salve2
       environment:
             - PORT=6395
       ports:
         - "6395:6395"
         - "16395:16395"
       stdin_open: true
       networks:
          redis-master:
              ipv4_address: 172.50.0.6
       tty: true
       privileged: true
       volumes: ["/config:/config"]
       entrypoint:
         - /bin/bash
         - redis.sh
  redis-salve3:
       image: redis:5.0
       container_name: redis-slave3
       working_dir: /config
       environment:
          - PORT=6396
       ports:
         - "6396:6396"
         - "16396:16396"
       stdin_open: true
       networks:
          redis-master:
            ipv4_address: 172.50.0.7
       tty: true
       privileged: true
       volumes: ["/config:/config"]
       entrypoint:
         - /bin/bash
         - redis.sh
networks:
  redis-master:
     driver: bridge # 创建一个docker 的桥接网络
     ipam:
       driver: default
       config:
          -
           subnet: 172.50.0.0/16
  redis-slave:
       driver: bridge
       ipam:
         driver: default
         config:
            -
             subnet: 172.30.0.0/16

4、编写 redis 默认的启动脚本

创建文件 config/redis.sh,内容如下:

redis-server  /config/nodes-${PORT}.conf

把如下文件,都复制到/config 目录下面:

5、启动集群

启动服务命令如下:

docker-compose up -d
#为了查看启动过程,可以不加-d
[root@test docker-redis-cluster-master]# 
[root@test docker-redis-cluster-master]# docker-compose  up 
WARNING: Some networks were defined but are not used by any service: redis-slave
Removing redis-slave1
Removing redis-slave3
Removing redis-salve2
Recreating a17b29f39ed2_a17b29f39ed2_a17b29f39ed2_redis-slave1 ... 
redis-master3 is up-to-date
Recreating b39430619beb_b39430619beb_b39430619beb_redis-slave3 ... 
redis-master1 is up-to-date
redis-master2 is up-to-date
Recreating a17b29f39ed2_a17b29f39ed2_a17b29f39ed2_redis-slave1 ... done
Attaching to redis-master3, redis-master1, redis-master2, redis-salve2, redis-slave3, redis-slave1
......
redis-master1    | 5:M 27 Dec 2019 02:30:36.470 * Ready to accept connections

查看服务运行:

[root@test ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                        NAMES
dadd8d0e7321        redis               "/bin/bash redis.sh"     15 seconds ago      Up 14 seconds       0.0.0.0:6394->6394/tcp, 6379/tcp, 0.0.0.0:16394->16394/tcp   redis-slave1
b71fe5a88277        redis               "/bin/bash redis.sh"     15 seconds ago      Up 14 seconds       0.0.0.0:6395->6395/tcp, 6379/tcp, 0.0.0.0:16395->16395/tcp   redis-salve2
6930e571891c        redis               "/bin/bash redis.sh"     15 seconds ago      Up 14 seconds       0.0.0.0:6396->6396/tcp, 6379/tcp, 0.0.0.0:16396->16396/tcp   redis-slave3
6a02d66a952f        redis               "/bin/bash redis.sh"     16 minutes ago      Up 4 minutes        0.0.0.0:6391->6391/tcp, 6379/tcp, 0.0.0.0:16391->16391/tcp   redis-master1
9a8f2da073d8        redis               "/bin/bash redis.sh"     16 minutes ago      Up 4 minutes        0.0.0.0:6393->6393/tcp, 6379/tcp, 0.0.0.0:16393->16393/tcp   redis-master3
205d8d356efb        redis               "/bin/bash redis.sh"     16 minutes ago      Up 4 minutes        0.0.0.0:6392->6392/tcp, 6379/tcp, 0.0.0.0:16392->16392/tcp   redis-master2

初始化集群(这一步开始命令须在 redis5.0 及以上版本运行)。

创建 3 主 3 从的 redis 集群:

[root@test ~]# docker exec -it 6a02d66a952f /bin/bash 
root@6a02d66a952f:/config# redis-cli --cluster create 172.50.0.2:6391 172.50.0.3:6392 172.50.0.4:6393 172.50.0.5:6394 172.50.0.6:6395 172.50.0.7:6396 --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 172.50.0.6:6395 to 172.50.0.2:6391
Adding replica 172.50.0.7:6396 to 172.50.0.3:6392
Adding replica 172.50.0.5:6394 to 172.50.0.4:6393
M: 2f1e442083481ab68cb22585a7dbad1594ba731b 172.50.0.2:6391
   slots:[0-5460] (5461 slots) master
M: ef77f264968897f55f7435353d90c55172a96f9b 172.50.0.3:6392
   slots:[5461-10922] (5462 slots) master
M: 9f65e3dc492cbef9f2837166c092163ab4082cab 172.50.0.4:6393
   slots:[10923-16383] (5461 slots) master
S: 61eb8a66f2defca5f6ca363c1b813cfb399d31f6 172.50.0.5:6394
   replicates 9f65e3dc492cbef9f2837166c092163ab4082cab
S: 963654cf1538bc1c92656d2ed660b88a9bb4dff7 172.50.0.6:6395
   replicates 2f1e442083481ab68cb22585a7dbad1594ba731b
S: 3220a0a93c9f06394d4c6d0796cfa5594196a075 172.50.0.7:6396
   replicates ef77f264968897f55f7435353d90c55172a96f9b
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 172.50.0.2:6391)
M: 2f1e442083481ab68cb22585a7dbad1594ba731b 172.50.0.2:6391
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: ef77f264968897f55f7435353d90c55172a96f9b 172.50.0.3:6392
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 9f65e3dc492cbef9f2837166c092163ab4082cab 172.50.0.4:6393
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 61eb8a66f2defca5f6ca363c1b813cfb399d31f6 172.50.0.5:6394
   slots: (0 slots) slave
   replicates 9f65e3dc492cbef9f2837166c092163ab4082cab
S: 963654cf1538bc1c92656d2ed660b88a9bb4dff7 172.50.0.6:6395
   slots: (0 slots) slave
   replicates 2f1e442083481ab68cb22585a7dbad1594ba731b
S: 3220a0a93c9f06394d4c6d0796cfa5594196a075 172.50.0.7:6396
   slots: (0 slots) slave
   replicates ef77f264968897f55f7435353d90c55172a96f9b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

查看初始化结果。

进入 redis-cli, 查看节点信息:

root@6a02d66a952f:/config# redis-cli -h 172.50.0.2 -p 6391   
172.50.0.2:6391> cluster nodes
ef77f264968897f55f7435353d90c55172a96f9b 172.50.0.3:6392@16392 master - 0 1577415280000 2 connected 5461-10922
9f65e3dc492cbef9f2837166c092163ab4082cab 172.50.0.4:6393@16393 master - 0 1577415280839 3 connected 10923-16383
61eb8a66f2defca5f6ca363c1b813cfb399d31f6 172.50.0.5:6394@16394 slave 9f65e3dc492cbef9f2837166c092163ab4082cab 0 1577415282843 4 connected
963654cf1538bc1c92656d2ed660b88a9bb4dff7 172.50.0.6:6395@16395 slave 2f1e442083481ab68cb22585a7dbad1594ba731b 0 1577415281841 5 connected
2f1e442083481ab68cb22585a7dbad1594ba731b 172.50.0.2:6391@16391 myself,master - 0 1577415280000 1 connected 0-5460
3220a0a93c9f06394d4c6d0796cfa5594196a075 172.50.0.7:6396@16396 slave ef77f264968897f55f7435353d90c55172a96f9b 0 1577415280000 6 connected
172.50.0.2:6391> 

上图显示,redis 集群符合预期。

6、测试集群

普通模式连接:由于 test 根据哈希槽计算,是分布在 6392 服务上。所以这里会提示转到 6392。

root@6a02d66a952f:/config# redis-cli -h 172.50.0.2 -p 6391              
172.50.0.2:6391> ping
PONG
172.50.0.2:6391> set test 1
(error) MOVED 6918 172.50.0.3:6392
172.50.0.2:6391> 

集群模式连接:以下例子显示操作正常。

root@6a02d66a952f:/config# redis-cli -c -h 172.50.0.2 -p 6391 set test 1
OK
root@6a02d66a952f:/config# redis-cli -c -h 172.50.0.2 -p 6391 get test     
"1"
root@6a02d66a952f:/config# 

集群模式连接读写正常,集群搭建成功。

docker企业级项目实战,后续会进行更新,敬请期待。