容器化应用实战:Redis

[!note] 核心摘要

  • 单节点:挂载整个 conf 目录 + 空配置文件即可启动,避开 ES 单文件挂载坑
  • 客户端验证:临时容器跑 redis-cli 连接,或宿主机直连映射端口
  • 集群架构:3 主 3 从,数据分片依赖 16384 个 hash 槽
  • 集群创建redis-cli --cluster create + --cluster-replicas 1,每个 master 挂 1 个从节点

一、单节点部署

1. 准备配置文件

创建配置文件目录:

[root@localhost ~]# mkdir -p /opt/redis/conf

创建配置文件(先建空文件占位):

[root@localhost ~]# touch /opt/redis/conf/redis.conf

2. 下载镜像并运行容器

[root@localhost ~]# docker run -p 6379:6379 --name redis -v /opt/redis/data:/data -v /opt/redis/conf:/etc/redis -d redis redis-server /etc/redis/redis.conf
cdbb193f0ee1b236563b29a4bc2c9948d285723942bc5b33966b28703487c3b

查看容器:

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS        PORTS                                         NAMES
cdbb193f0ee    redis     "docker-entrypoint.s…"   4 seconds ago   Up 3 seconds  0.0.0.0:6379->6379/tcp, :::6379->6379/tcp     redis

3. 挂载方式细节(避开 ES 的坑)

这条 redis 的挂载写法:

-v /opt/redis/conf:/etc/redis

挂载的是整个目录,不是单个 redis.conf 文件。

  1. 宿主机 /opt/redis/conf 目录提前 mkdir -p 建好;
  2. 宿主机里面提前 touch 生成空文件 redis.conf
  3. 把整个宿主机 conf 目录挂载到容器 /etc/redis 目录;
  4. 容器启动命令指定读取配置:redis-server /etc/redis/redis.conf

[!note] 为什么这样写
这种写法就避开 ES 那个经典坑:它没有 -v 宿主机/redis.conf:/容器/redis.conf 挂载单个文件,而是挂载目录。就算宿主机里面 conf 目录下的 redis.conf 是空文件,也不会出现「把文件生成目录」的问题。

[!warning] 小坑提醒
这里 touch 出来是空的 redis.conf,redis 拿空配置文件启动会使用内置默认参数;如果要自定义配置,需要把完整 redis 配置内容写入宿主机的 /opt/redis/conf/redis.conf

4. 验证:使用客户端连接

[root@localhost ~]# docker run -it redis:latest redis-cli -h 172.17.0.2
172.17.0.2:6379>
172.17.0.2:6379> set name zhangsan
OK
172.17.0.2:6379> get name
"zhangsan"

简单解读

  1. docker run -it redis:latest redis-cli -h 172.17.0.2:启动一个临时 redis 容器,运行 redis-cli 客户端,去连接 redis 服务容器的 docker 网桥 IP(172.17.0.2)。两个容器同在默认 bridge 网络,所以可以直接访问容器内部 IP。
  2. set name zhangsan:写入 key-value,返回 OK 代表写入成功。
  3. get name:读取 key,返回 "zhangsan",证明 redis 服务正常工作。

[!warning] 容器 IP 会变
redis 容器重启后,容器 IP 172.17.0.2 有可能变化,这种方式只适合课堂测试。
实际也可以:redis-cli -h 宿主机IP -p 6379,从宿主机访问映射端口。

二、Redis 集群部署(3 主 3 从)

集群方式:三主三从

  • 三主:实现数据分片
  • 三从:实现数据备份

1. 一键部署脚本

[root@localhost ~]# vim redis-cluster.sh
for port in $(seq 8001 8006); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.100.152
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
appendonly yes
EOF
docker run -p ${port}:${port} -p 1${port}:1${port} --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d redis:5.0.7 redis-server /etc/redis/redis.conf; \
done

2. 脚本解读

  1. seq 8001 8006:循环生成 6 个节点,端口 8001-8006,6 个容器,后续组成 3 主 3 从 Redis 集群。
  2. 每个节点独立宿主机目录:/mydata/redis/node-${port},分别存放 data 数据、redis.conf 配置。
  3. 集群关键配置:
    • cluster-enabled yes:开启集群模式
    • cluster-config-file nodes.conf:集群节点信息文件
    • cluster-announce-ip:对外宣告宿主机物理 IP(非常关键,不能写容器内网 IP)
    • cluster-announce-port / cluster-announce-bus-port:业务端口、集群总线端口(总线端口 = 1 + 业务端口,如 8001 → 18001)
    • appendonly yes:开启 AOF 持久化
  4. docker run:做两组端口映射,业务端口 ${port}、集群总线端口 1${port};挂载单文件 redis.conf(⚠️ 这里会遇到你前面 ES 同样的坑:宿主机必须提前生成好文件,否则 docker 会把它创建成目录);镜像版本 redis:5.0.7。
  5. 脚本执行完只会把 6 个 redis 容器启动,还没有创建集群关系,后续还需要执行 redis-cli --cluster create 命令组建 3 主 3 从集群。

![[03_云原生/Docker/image/d44462ee9ab94fbea81385267126ba49_MD5.jpg]]

3. 创建集群

进入任意 1 个容器:

[root@localhost ~]# docker exec -it redis-8001 bash
root@cf732ad577d7:/data# redis-cli --cluster create 192.168.100.152:8001 192.168.100.152:8002 192.168.100.152:8003 192.168.100.152:8004 192.168.100.152:8004 192.168.100.152:8005 192.168.100.152:8006 --cluster-replicas 1
>>> Performing hash slots allocation on 7 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.100.152:8004 to 192.168.100.152:8001
Adding replica 192.168.100.152:8005 to 192.168.100.152:8002
Adding replica 192.168.100.152:8006 to 192.168.100.152:8003
Adding extra replicas...
Adding replica 192.168.100.152:8004 to 192.168.100.152:8001
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: ab7c815e85cb40a5c1f30c5602b81d3209b435f9 192.168.100.152:8001
  slots:[0-5460] (5461 slots) master
M: 2a870205057fca8072a362983650b9641d5aff3f 192.168.100.152:8002
  slots:[5461-10922] (5462 slots) master

要点解读

  1. docker exec -it redis-8001 bash:进入 8001 容器内部。
  2. redis-cli --cluster create 创建 redis 集群,--cluster-replicas 1 代表每个 master 分配 1 个从节点,3 主 3 从。

[!warning] 截图命令有笔误
截图命令重复写了 192.168.100.152:8004,正确应该是 6 个节点:8001、8002、8003、8004、8005、8006。

  1. hash 槽(0-16383)分配给 3 台 master,数据分片就是靠 hash 槽实现。
  2. 分配从节点:8004 跟随 8001,8005 跟随 8002,8006 跟随 8003。
  3. 警告 Some slaves are in the same host as their master:所有主从都跑在同一台物理机;生产环境主从要分散在不同机器,避免整机宕机全部挂掉,学习环境可以忽略该警告。

输入 yes,开始创建集群

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 192.168.100.152:8001)
M: ab7c815e85cb40a5c1f30c5602b81d3209b435f9 192.168.100.152:8001
  slots:[0-5460] (5461 slots) master
  2 additional replica(s)
S: 68e20c2b480d3c8781686738a094db7fd575b0c8 192.168.100.152:8006
  slots: (0 slots) slave
  replicates ab7c815e85cb40a5c1f30c5602b81d3209b435f9
M: 31fd6a5eaf99c34365f349600f364b88a2c06dcf 192.168.100.152:8003
  slots:[10923-16383] (5461 slots) master
  1 additional replica(s)
S: 7a918820de560fa1f92c7d6614e52c3d6a9fcb2e 192.168.100.152:8005
  slots: (0 slots) slave
  replicates ab7c815e85cb40a5c1f30c5602b81d3209b435f9
S: be8ee684b0c25d9de867ba5c7d7f9a39e0981c25 192.168.100.152:8004
  slots: (0 slots) slave
  replicates 31fd6a5eaf99c34365f349600f364b88a2c06dcf
M: 2a870205057fca8072a362983650b9641d5aff3f 192.168.100.152:8002
  slots:[5461-10922] (5462 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

结果解读

  1. 输入 yes 确认集群配置,节点互相执行 CLUSTER MEET 握手加入集群。
  2. M 代表 master 主节点,S 代表 slave 从节点;replicates xxx 表示该从节点归属哪个主节点。
  3. [OK] All nodes agree about slots configuration.:所有节点槽位配置达成一致。
  4. [OK] All 16384 slots covered.16384 个 hash 槽全部分配完毕,Redis 集群创建成功。

[!warning] 异常现象说明
截图里出现了一个主节点绑定 2 个从节点的异常现象,是上一条命令复制粘贴重复节点 8004 导致的;正常 3 主 3 从,每个 master 应当只绑定 1 个 slave。

三、命令速查

命令作用
docker run -p 6379:6379 --name redis -v /opt/redis/data:/data -v /opt/redis/conf:/etc/redis -d redis redis-server /etc/redis/redis.conf运行 Redis 容器
docker run -it redis:latest redis-cli -h 172.17.0.2临时容器连接 Redis 服务
redis-cli -h 宿主机IP -p 6379宿主机连接映射端口
redis-cli --cluster create 节点列表 --cluster-replicas 1创建集群(3 主 3 从)

更多推荐