> ## Content Index
> Fetch the complete content index at: https://www.richarvin.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Docker学习笔记（高阶篇）二
- URL: https://www.richarvin.com/docker-xue-xi-bi-ji-gao-jie-pian-er/
- Published: 2024-03-13T06:36:31.000Z
- Updated: 2024-05-22T01:06:48.000Z
- Author: Richarvin
- Tags: 编程技术

## 实战演练（Redis三主三从）

---

因手上经常玩的是Ubuntu，随测随删，所以示例用此版本演示，生产环境中以Centos为主，基本上玩法一致。

1.指定路径下创建一个测试目录test

```bash
cd /root/data/docker_workspace

mkdir test

cd test
```

2.创建编辑docker-compose.yml文件

```bash
vim docker-compose.yml
```

3.拷贝配置文件至yml文件中并保存

```yaml
version: '3.3'
services:
  redis-node-1:
    image: redis:6.0.8
    command: ["redis-server", "--cluster-enabled", "yes", "--appendonly", "yes", "--port", "6381"]
    volumes:
      - /data/redis/share/redis-node-1:/data
    networks:
      - my_network
    privileged: true

  redis-node-2:
    image: redis:6.0.8
    command: ["redis-server", "--cluster-enabled", "yes", "--appendonly", "yes", "--port", "6382"]
    volumes:
      - /data/redis/share/redis-node-2:/data
    networks:
      - my_network
    privileged: true

  redis-node-3:
    image: redis:6.0.8
    command: ["redis-server", "--cluster-enabled", "yes", "--appendonly", "yes", "--port", "6383"]
    volumes:
      - /data/redis/share/redis-node-3:/data
    networks:
      - my_network
    privileged: true

  redis-node-4:
    image: redis:6.0.8
    command: ["redis-server", "--cluster-enabled", "yes", "--appendonly", "yes", "--port", "6384"]
    volumes:
      - /data/redis/share/redis-node-4:/data
    networks:
      - my_network
    privileged: true

  redis-node-5:
    image: redis:6.0.8
    command: ["redis-server", "--cluster-enabled", "yes", "--appendonly", "yes", "--port", "6385"]
    volumes:
      - /data/redis/share/redis-node-5:/data
    networks:
      - my_network
    privileged: true

  redis-node-6:
    image: redis:6.0.8
    command: ["redis-server", "--cluster-enabled", "yes", "--appendonly", "yes", "--port", "6386"]
    volumes:
      - /data/redis/share/redis-node-6:/data
    networks:
      - my_network
    privileged: true

networks:
  my_network:
    external: true
```

4.自定义网络

```bash
 docker network create my_network
```

5.运行实例

```bash
docker-compose up -d
```

![](https://picture.richarvin.com/202403/xnip2024-03-13_11-45-11.webp)

6.查看自定义网络中运行的6个容器IP地址

```bash
docker network inspect my_network
```

根据显示的json表中找出对应的关系键值对：Name-IPv4Address,整理出如下列表：

test\_redis-node-1\_1 172.19.0.4  
test\_redis-node-2\_1 172.19.0.2  
test\_redis-node-3\_1 172.19.0.7  
test\_redis-node-4\_1 172.19.0.5  
test\_redis-node-5\_1 172.19.0.6  
test\_redis-node-6\_1 172.19.0.3

每个节点后面的IP请根据自己实际的情况填写更改，IP是随机分配的。然后从节点一开始，每个节点的端口分别分配6381-6386结束

test\_redis-node-1\_1 172.19.0.4：6381  
test\_redis-node-2\_1 172.19.0.2：6382  
test\_redis-node-3\_1 172.19.0.7：6383  
test\_redis-node-4\_1 172.19.0.5：6384  
test\_redis-node-5\_1 172.19.0.6：6385  
test\_redis-node-6\_1 172.19.0.3：6386

7.构建主从关系（该演示中此命令在宿主机上运行，而非进入某个节点中运行）

```bash
redis-cli --cluster create 172.19.0.4:6381 172.19.0.2:6382 172.19.0.7:6383 172.19.0.5:6384 172.19.0.6:6385 172.19.0.3:6386 --cluster-replicas 1
```

如果报Command 'redis-cli' not found, but can be installed with:

apt install redis-tools

8.请用命令安装redis-tools

```bash
apt install redis-tools
```

![](https://picture.richarvin.com/202403/xnip2024-03-13_11-55-32.webp)

再次运行

```bash
redis-cli --cluster create 172.19.0.4:6381 172.19.0.2:6382 172.19.0.7:6383 172.19.0.5:6384 172.19.0.6:6385 172.19.0.3:6386 --cluster-replicas 1
```

确认无误，输入yes开始分配

![](https://picture.richarvin.com/202403/xnip2024-03-13_12-15-20.webp)

![](https://picture.richarvin.com/202403/xnip2024-03-13_12-17-11.webp)

9.进入主Master节点一查看所有节点信息

```bash
docker exec -it test_redis-node-1_1 /bin/bash
```

```bash
redis-cli -p 6381
```

![](https://picture.richarvin.com/202403/xnip2024-03-13_12-29-09.webp)

```bash
cluster info
```

![](https://picture.richarvin.com/202403/xnip2024-03-13_12-32-33.webp)

cluster\_state:ok: 集群的状态是OK，意味着这个节点认为集群是健康的。  
cluster\_slots\_assigned: 节点被分配了集群中所有16384个槽。  
cluster\_slots\_ok: 所有16384个槽都正常工作。  
cluster\_known\_nodes: 节点已知集群中有6个节点，包括它自己和其他节点。  
该输出表明此节点是集群的一部分，集群中有6个节点，并且此节点已经分配了所有的槽，没有任何槽是处于失败状态。基于输出的其余部分，我们可以看到集群当前有3个主节点（cluster\_size:3）

![](https://picture.richarvin.com/202403/xnip2024-03-13_12-37-32.webp)

cluster nodes命令继续查询列出了集群中每个节点的ID、IP地址、端口号以及它们是主节点(master)还是从节点(slave)。例如第一个节点是一个主节点（master），其余的是与之关联的从节点。

- 主节点 (test\_redis-node-3\_1)172.19.0.7:6383 与从节点 (test\_redis-node-5\_1)172.19.0.6:6385;
- 主节点(test\_redis-node-2\_1) 172.19.0.2:6382 与从节点(test\_redis-node-6\_1) 172.19.0.3:6386;
- 主节点 (test\_redis-node-1\_1)172.19.0.4:6381 与从节点(test\_redis-node-4\_1) 172.19.0.5:6384

## 主从切换测试

1、切换到宿主机上停止主节点一的容器（6381），观察其从节点6384是否会上位成为主节点？

![](https://picture.richarvin.com/202403/xnip2024-03-13_13-24-40.webp)

6381节点正常运行时的槽位

![](https://picture.richarvin.com/202403/xnip2024-03-13_13-27-14.webp)

6381关闭后，6385上位成了主节点

### 疑问？

为什么按照前面的那张主从对应表，原先主节点6381的从节点是6384，按照道理说，6381关闭了，应该是6384上位，怎么反而是主节点6383对应的从节点6385上位呢？

原来在Redis集群中，主节点的故障转移（failover）并不总是选择其对应的从节点作为新的主节点。选择哪个从节点晋升为新的主节点由Redis集群的故障转移过程决定，该过程遵循以下步骤：

- 检测主节点故障：集群中的其他节点（主要是从节点）会持续检测与主节点的通信。如果一个主节点无法访问，它的从节点将开始一个故障转移流程。
- 选举投票：在开始故障转移时，从节点会向集群中的其他主节点请求投票来成为新的主节点。
- 选择一个从节点：其他主节点将根据从节点的状态和偏移量（表示数据的新鲜程度）投票。通常拥有最完整数据集的从节点，即数据偏移量最大的从节点，会赢得选举。
- 晋升过程：一旦一个从节点赢得大多数票，它就会被晋升为新的主节点，并开始接收写请求。
- 更新集群状态：集群的状态将更新，新的主节点的信息将被传播到整个集群。

2、重启6381主节点，再观察

![](https://picture.richarvin.com/202403/xnip2024-03-13_13-41-00.webp)

发现6381恢复正常后，并没有如想象中的那样会把刚刚上位成为master节点的6385给踢下去做回从节点，而自己则重新成为master。原因如下：

在Redis集群中一旦一个从节点晋升为主节点，这个变化是有持续性的。也就是说，即使原来的主节点重新上线，晋升的从节点通常不会自动降级回从节点。原因如下：

- 稳定性：集群晋升新的主节点是为了维持稳定性和数据完整性。一旦一个从节点被晋升为主节点，它就会承担起响应客户端请求和数据同步的责任。将它再次降级可能会引起不必要的风险和混乱。
- 避免脑裂：晋升后，为了防止“脑裂”（split-brain）情况的发生，集群会避免出现两个节点声称自己是相同数据分片的主节点的情况。
- 数据最新：通常一个节点被晋升为主节点，是因为它有最新的数据副本。当原主节点恢复时，它的数据可能已经落后于新的主节点，因此原主节点会成为新主节点的从节点，以同步最新的数据。
- 自动化运维：大多数Redis集群的运维是自动化的，当集群自我修复后，不会再进行不必要的角色更改，除非由管理员手动介入。
- 人为干预：如果希望原主节点恢复其主节点角色，需要管理员手动介入进行调整。这通常包括将新主节点降级为从节点，并恢复原主节点的主节点角色。