基于目前烂大街微服务的情况下,Redis在企业中使用非常频繁,比如:缓存服务、分布式锁、分布式原子计数锁、队列等等。本文主要讲解redis-cluster集群搭建,规划模拟6个节点,三主三从。

系统CentOS 7
CPU2核
内存4G
硬盘50G
Docker19.03.5(安装
Docker-compose1.16.1(与docker版本映射表格)(安装
Redis5.0

节点规划 

容器名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

准备 redis.conf

 创建数据存放目录

# 注意:以下命令均在/mnt/redis/目录下执行
mkdir /mnt/redis

cd /redis

# data 数据目录,config 配置文件目录
mkdir -p {redis-master1/data,redis-master2/data,redis-master3/data,redis-slave1/data,redis-slave2/data,redis-slave3/data,redis-master1/config,redis-master2/config,redis-master3/config,redis-slave1/config,redis-slave2/config,redis-slave3/config}

获取5.0版本redis.conf文件(坚~单击跳转),对redis.conf内如下配置内容进行修改: 

# 修改 可以接受连接的网卡地址,0.0.0.0 接受所有
bind 0.0.0.0
# 端口
port 6391
# 节点超时时间,毫秒
cluster-node-timeout 15000
# 集群内部配置文件
cluster-config-file "nodes-6379.conf"

## 设置密码
###1、如果对集群设置密码,那么requirepass和masterauth都需要设置,否则发生主从切换时,就会遇到授权问题,可以模拟并观察日志
###2、各个节点的密码都必须一致,否则Redirected就会失败
###3、设置密码后,操作redis-cli需(redis-cli -c -p 端口)通过auth password进行密码验证
### -c 集群方式登陆客户端程序
masterauth 123456
requirepass 123456

将redis.conf复制6份到对应的config文件夹下:

echo redis-master1 redis-master2 redis-master3 redis-slave1 redis-slave2 redis-slave3 | xargs -n 1 cp -v redis.sh
  • -n 1 - 告诉 xargs 命令每个命令行最多使用一个参数,并发送到 cp 命令中。
  • cp – 用于复制文件。
  • -v – 启用详细模式来显示更多复制细节。

修改redis.conf端口号以及文件名

# 批量修改端口
sed -i 's/port 6391/port 6392/' redis-master2/redis.conf && \
sed -i 's/port 6391/port 6393/' redis-master3/redis.conf && \
sed -i 's/port 6391/port 6394/' redis-slave1/redis.conf && \
sed -i 's/port 6391/port 6395/' redis-slave2/redis.conf && \
sed -i 's/port 6391/port 6396/' redis-slave3/redis.conf

# 批量修改文件名
mv redis-master1/redis.conf redis-master1/nodes-3691.conf && \
mv redis-master2/redis.conf redis-master2/nodes-3692.conf && \
mv redis-master3/redis.conf redis-master3/nodes-3693.conf && \
mv redis-slave1/redis.conf redis-slave1/nodes-3694.conf && \
mv redis-slave2/redis.conf redis-slave2/nodes-3695.conf && \
mv redis-slave3/redis.conf redis-slave3/nodes-3696.conf

编写启动文件

vim redis.sh

# 内容:
redis-server  /config/nodes-${PORT}.conf

编写 redis-docker-compose.yml

version: "3.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 # 标准输入打开
     # docker 网络设置
     networks: 
        redis-cluster:
            ipv4_address: 172.50.0.2
     tty: true
     privileged: true # 拥有容器内命令执行的权限
     # 映射数据卷,配置目录
     volumes: [
         "/mnt/redis/redis-master1/data:/data",
         "/mnt/redis/redis-master1/config:/config",
         "/mnt/redis/redis.sh:/config/redis.sh",
         "/etc/localtime:/etc/localtime" # 时间同步
         
     ] 
     entrypoint: # 设置服务默认的启动程序
       - /bin/bash
       - redis.sh
  redis-master2:
       image: redis:5.0
       working_dir: /config
       container_name: redis-master2
       environment:
              - PORT=6392
       networks:
          redis-cluster:
             ipv4_address: 172.50.0.3
       ports:
         - "6392:6392"
         - "16392:16392"
       stdin_open: true
       tty: true
       privileged: true
       volumes: [
         "/mnt/redis/redis-master2/data:/data",
         "/mnt/redis/redis-master2/config:/config",
         "/mnt/redis/redis.sh:/config/redis.sh",
         "/etc/localtime:/etc/localtime"
       ]
       entrypoint:
         - /bin/bash
         - redis.sh
  redis-master3:
       image: redis:5.0
       container_name: redis-master3
       working_dir: /config
       environment:
              - PORT=6393
       networks:
          redis-cluster:
            ipv4_address: 172.50.0.4
       ports:
         - "6393:6393"
         - "16393:16393"
       stdin_open: true
       tty: true
       privileged: true
       volumes: [
         "/mnt/redis/redis-master3/data:/data",
         "/mnt/redis/redis-master3/config:/config",
         "/mnt/redis/redis.sh:/config/redis.sh",
         "/etc/localtime:/etc/localtime"
       ]
       entrypoint:
         - /bin/bash
         - redis.sh
  redis-slave1:
       image: redis:5.0
       container_name: redis-slave1
       working_dir: /config
       environment:
            - PORT=6394
       networks:
          redis-cluster:
             ipv4_address: 172.50.0.5
       ports:
         - "6394:6394"
         - "16394:16394"
       stdin_open: true
       tty: true
       privileged: true
       volumes: [
         "/mnt/redis/redis-slave1/data:/data",
         "/mnt/redis/redis-slave1/config:/config",
         "/mnt/redis/redis.sh:/config/redis.sh",
         "/etc/localtime:/etc/localtime"
       ]
       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-cluster:
              ipv4_address: 172.50.0.6
       tty: true
       privileged: true
       volumes: [
         "/mnt/redis/redis-slave2/data:/data",
         "/mnt/redis/redis-slave2/config:/config",
         "/mnt/redis/redis.sh:/config/redis.sh",
         "/etc/localtime:/etc/localtime"
       ]
       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-cluster:
            ipv4_address: 172.50.0.7
       tty: true
       privileged: true
       volumes: [
         "/mnt/redis/redis-slave3/data:/data",
         "/mnt/redis/redis-slave3/config:/config",
         "/mnt/redis/redis.sh:/config/redis.sh",
         "/etc/localtime:/etc/localtime"
       ]
       entrypoint:
         - /bin/bash
         - redis.sh
networks:
  redis-cluster:
     driver: bridge # 创建一个docker 的桥接网络
     ipam:
       driver: default
       config:
          -
           subnet: 172.50.0.0/16

Docker编排Redis集群

在这里提供一个批量修改文件,设置密码的方式(如果你再最开始已经设置密码,请忽略!!):

sed -i 's/\#\ masterauth\ <master-password>/masterauth\ 123456/g' `grep nodes-63 -rl --include="*.conf" redis/`

sed -i 's/# requirepass foobared/requirepass 123456/g' `grep nodes-63 -rl --include="*.conf" redis/`
docker-compose -f redis-cluster-docker-compose.yml up -d

集群初始化

# 进入容器内部
docker exec -it redis-master1 bash

# 初始化
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

########################################
     ## 当然你也可以直接这样执行 ##
########################################

docker exec -it redis-master1 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

# 查看一下集群状态信息,设置密码时,不可用

docker exec -it redis-master1 redis-cli -p 6391 --cluster-replicas 1 cluster info

 验证集群数据一致性

验证手段:我们再redis-master1创建一条数据(key:testKey,value:1),分别在redis-master2、edis-slave3分片查询数据(get testKey)。

你可能会用到的命令:

# 进入容器内部
docker exec -it redis-master1 bash
# 连接客户端
redis-cli -p 6396 -c
# 创建数据
set testKey 1
# 查看数据
get testKey

从上图可以看出,如果在当前分片没有get到数据,集群会自动切换到特定的分片,如果你想了解更多请百度/Google Redis集群路由规则原理。我们无论从那个节点都能get到数据(slave节点只读),因此我们的Redis-Cluster 集群数据具备一致性。

 
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐