1 预备知识

除了知道DockerRedis cluster的基本概念和常规部署流程外,还需要知道Docker里的几个概念:

  • Volume:独立于container的一个数据保存区域,可以被container共享,也可以用来把本地的配置文件映射过去供container使用。
  • NetworkDocker内部的"网络",让不同的container可以互相访问,这是redis官方建议的在docker里做cluster时的方式。我们这里主要用bridge模式。

2 基本步骤

2.1 获取redis镜像

1
docker pull redis

2.2 在本机创建配置文件

在本地的一个文件夹内创建一个redis-cluster.conf配置文件,里面仅包含简单的集群配置信息:

1
2
3
4
5
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

2.3 创建一个Docker Network

1
docker network create my-net

2.4 用本地配置文件启动多个redis节点

1
docker run -d --name redis-1 --network my-net -v C:\Users\xxx\Desktop\conf\redis-cluster.conf:/usr/local/etc/redis/redis.conf redis redis-server /usr/local/etc/redis/redis.conf

上面这条命令里的几个参数:

  • docker run:运行一个container
  • -d:后台运行
  • --name:自定义的container的名称
  • --network:容器加入的网络
  • -v:volume映射,“本机地址:docker地址”的格式,“C:\Users\xxx\Desktop\conf\redis-cluster.conf"是刚才存放的配置文件地址(加文件名),"/usr/local/etc/redis/redis.conf"是我们的volume挂载的地址,这里我们把配置文件的名称也改掉了,本机是redis-cluster.confvolume里是redis.conf
  • redis:我们的image名称,默认用最新版
  • redis-server /usr/local/etc/redis/redis.conf:这跟我们常规启动redis服务是一样的,用我们刚才映射过去的配置文件启动。

把上面的"redis-1"换成"redis-2”…“redis-6”,启动6个节点,注意这里配置文件不用改,端口也全是6379,因为network会给我们每一个节点分配不同的IP。

完成后查看一下容器:

1
docker ps
查看输出
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS      NAMES

cd6d8811ce44   redis     "docker-entrypoint.s…"   2 seconds ago    Up 1 second     6379/tcp   redis-6

f67c48b6ea9d   redis     "docker-entrypoint.s…"   8 seconds ago    Up 7 seconds    6379/tcp   redis-5

4fe4a89469da   redis     "docker-entrypoint.s…"   13 seconds ago   Up 12 seconds   6379/tcp   redis-4

950537cd501e   redis     "docker-entrypoint.s…"   21 seconds ago   Up 20 seconds   6379/tcp   redis-3

4d09c04e87b1   redis     "docker-entrypoint.s…"   34 seconds ago   Up 32 seconds   6379/tcp   redis-2

d15c0933bc05   redis     "docker-entrypoint.s…"   12 minutes ago   Up 12 minutes   6379/tcp   redis-1

再查看一下network:

1
docker network inspect my-net

可以看到我们的6个container都在里面,每个分配了不同的ID

查看输出
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 {
        "Name": "my-net",
        "Id": "8fa94b07701cad47c4440298b2908fbadd0591b44999df2013a7e1eb4b7b541b",
        "Created": "2021-04-21T05:46:18.4468198Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "4d09c04e87b1b99ebe7827181ce89f8bddd054b047ae24a4179d37ff0f98d271": {
                "Name": "redis-2",
                "EndpointID": "46faad0fc995299d176f941dd97e06b5a35f16a5a2b4b5d66f3ccf624363cebb",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "4fe4a89469da15e772d8a1437698b5832bc95310ebc59a18fb4860ec93c86595": {
                "Name": "redis-4",
                "EndpointID": "c2a84c3c7e8db91f4f694f10b390c1a78f702f2b65e71eeecbc51dc2288e28be",
                "MacAddress": "02:42:ac:12:00:05",
                "IPv4Address": "172.18.0.5/16",
                "IPv6Address": ""
            },
            "950537cd501eb2731dbd69890fd30c933f3246d2d85fca6cc51818b0c3fc5b31": {
                "Name": "redis-3",
                "EndpointID": "1bfe934156ff36b05a4c44c3695b02cef2a50f6a5fd3a75f52c03e3c900cbb7c",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            },
            "cd6d8811ce443f98a504e8466d2cd321f8129eae06b03b7667e4c145a308a880": {
                "Name": "redis-6",
                "EndpointID": "d0b9d092e6c38433d760f16781bd3cd2100b8f9c1b7f37f5c499e172fe0845d5",
                "MacAddress": "02:42:ac:12:00:07",
                "IPv4Address": "172.18.0.7/16",
                "IPv6Address": ""
            },
            "d15c0933bc05450410f4c1923e70493f1fd79b200c16341be0b5cda4c599bbfa": {
                "Name": "redis-1",
                "EndpointID": "7262111112b513c1d4c3e090fc4ae7b01bbc6adf0df337eb38fa311b04d92b45",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "f67c48b6ea9d8fb31ba8b1ec96ad6ea8cc1c246747608420814e79f59abfd56c": {
                "Name": "redis-5",
                "EndpointID": "a86deeae79f267f21e55e7ee06da7d12a627617e348398125c6303a12439cbdc",
                "MacAddress": "02:42:ac:12:00:06",
                "IPv4Address": "172.18.0.6/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }

上面可以看到我们每一个container的IP,也可以用下面这条命令单独获取某个container的IP,比如获取redis-1这个container的IP:

1
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $INSTANCE_ID

2.5 启动cluster

根据上面获取的IP,我们先进入redis1这个container

1
docker exec -it redis-1 /bin/bash

然后跟常规一样运行cluster

1
redis-cli --cluster create 172.18.0.2:6379 172.18.0.3:6379 172.18.0.4:6379 172.18.0.5:6379 172.18.0.6:6379 172.18.0.7:6379 --cluster-replicas 1

redis会自动分配slot,输入yes完成cluster。

完成以后,我们以cluster模式启动(还是在redis-1这个container里面):

1
redis -c -p 6379

测试下面4条语句可以观察到cluster自动在节点间跳转

1
2
3
4
set foo bar
set hello world
get foo
get bar

3 在项目中使用

因为我们的network对于主机来说并没有开放,所以在本地运行的项目并不能直接访问到这些IP。但是我们可以把项目打包部署到这个network里面,就可以直接使用这个cluster了。