目 录CONTENT

文章目录

【实用教程】用Docker Compose 3分钟快速搭建Redis Cluster 集群

冰点
2025-09-26 / 0 评论 / 0 点赞 / 4 阅读 / 21830 字

用Docker Compose快速搭建Redis Cluster集群(附完整配置与解析)

有的时候我们为了验证redis的一些特性,需要搭建一个实验环境,如果向运维申请不太好协调,本教程使用特别简单的一种方式,快速搭建一个redis集群,本环境最新版本使用redis8。

一、为什么选择Docker Compose搭建Redis Cluster?

在传统部署方式中,搭建Redis Cluster需要手动配置每个节点、执行集群初始化命令,步骤繁琐且易出错;而Docker Compose通过配置即代码的方式,将所有节点的部署逻辑整合到一个docker-compose.yml文件中,只需一条命令即可完成集群创建,优势显著:

二、完整Docker Compose配置解析

先上完整的docker-compose.yml配置(即文中提供的版本),再逐段拆解关键参数,帮大家理解每一行配置的作用:

version: '3'  # Compose文件版本,兼容Docker 1.13.0+

services:
  # 第一个Redis节点(主节点)
  redis-node-0:
    image: bitnamilegacy/redis-cluster:5.0  # 基于Bitnami的Redis集群镜像(稳定版5.0)
    ports:
      - "6380:6379"  # 宿主机端口6380映射到容器内Redis默认端口6379
    volumes:
      - redis-cluster_data-0:/bitnami/redis/data  # 数据卷挂载,持久化Redis数据
    environment:
      - REDIS_PASSWORD=test@redis  # Redis集群密码(所有节点必须一致)
      - REDIS_NODES=redis-node-0 redis-node-1 redis-node-2  # 集群所有节点名称(用于发现节点)
      - REDIS_ALLOW_REMOTE_CONNECTIONS=yes  # 允许远程连接(非本地容器可访问)
      - REDIS_CLUSTER_DYNAMIC_IPS=no  # 禁用动态IP(避免容器重启后IP变化导致集群故障)
      - REDIS_CLUSTER_ANNOUNCE_IP=172.24.32.232  # 宣告IP(必须是宿主机可被访问的IP)
      - REDIS_CLUSTER_ANNOUNCE_PORT=6380  # 关键:宣告宿主机映射端口(而非容器内6379)

  # 第二个Redis节点(主节点)
  redis-node-1:
    image: bitnamilegacy/redis-cluster:5.0
    ports:
      - "6381:6379"
    volumes:
      - redis-cluster_data-1:/bitnami/redis/data
    environment:
      - REDIS_PASSWORD=test@redis
      - REDIS_NODES=redis-node-0 redis-node-1 redis-node-2
      - REDIS_ALLOW_REMOTE_CONNECTIONS=yes
      - REDIS_CLUSTER_DYNAMIC_IPS=no
      - REDIS_CLUSTER_ANNOUNCE_IP=172.24.32.232
      - REDIS_CLUSTER_ANNOUNCE_PORT=6381  # 对应宿主机映射端口6381

  # 第三个Redis节点(主节点+集群初始化节点)
  redis-node-2:
    image: bitnamilegacy/redis-cluster:5.0
    ports:
      - "6382:6379"
    depends_on:  # 依赖关系:确保node0和node1启动后再启动node2
      - redis-node-0
      - redis-node-1
    volumes:
      - redis-cluster_data-2:/bitnami/redis/data
    environment:
      - REDIS_PASSWORD=test@redis
      - REDISCLI_AUTH=test@redis  # redis-cli工具的认证密码(用于执行集群创建命令)
      - REDIS_NODES=redis-node-0 redis-node-1 redis-node-2
      - REDIS_CLUSTER_REPLICAS=0  # 副本数:0表示所有节点都是主节点(无从节点,简化版集群)
      - REDIS_CLUSTER_CREATOR=yes  # 标记为“集群创建者”:此节点会自动执行集群初始化命令
      - REDIS_ALLOW_REMOTE_CONNECTIONS=yes
      - REDIS_CLUSTER_DYNAMIC_IPS=no
      - REDIS_CLUSTER_ANNOUNCE_IP=172.24.32.232
      - REDIS_CLUSTER_ANNOUNCE_PORT=6382

# 数据卷定义:用于持久化每个节点的数据(容器删除后数据不丢失)
volumes:
  redis-cluster_data-0:
  redis-cluster_data-1:
  redis-cluster_data-2:

# 自定义网络:避免与宿主机或其他容器网络冲突
networks:
  default:
    driver: bridge  # 桥接模式(默认网络模式,适合单机部署)
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16  # 独立子网:172.28.0.0网段,避免与其他服务IP冲突

redis-host.conf

# Redis Cluster配置文件(适用于Docker环境下的集群节点)
# 核心功能:定义Redis服务端口、网络策略、持久化方式及集群通信规则


################################## 网络与访问控制 ##################################
# 绑定地址:允许所有IPv4(0.0.0.0)和IPv6(::)地址访问
# 集群环境必须配置,确保节点间跨容器通信
bind 0.0.0.0 ::

# 保护模式:开启(yes)
# 作用:仅允许通过密码认证或指定IP的客户端访问,防止未授权访问
protected-mode yes

# 服务端口:6379(Redis默认端口)
# 与Docker Compose中的端口映射对应(如宿主机6380:容器内6379)
port 6379

# TCP连接队列大小:511
# 高并发场景可调整为1024,避免连接被拒绝
tcp-backlog 511

# 客户端超时时间:0(永不超时)
# 集群节点间保持长连接,禁用超时防止通信中断
timeout 0

# TCP保活机制:300秒(5分钟)
# 定期发送心跳包检测连接有效性,避免"假死"节点
tcp-keepalive 300


################################## 进程与日志配置 ##################################
# 守护进程模式:禁用(no)
# 容器环境必须设为no,否则Redis会以后台进程运行导致容器退出
daemonize no

# 外部进程监控:禁用(no)
# 容器内由Docker管理进程生命周期,无需外部监控
supervised no

# PID文件路径:容器内存储进程ID的位置
# 用于容器内部管理Redis进程
pidfile /opt/bitnami/redis/tmp/redis.pid

# 日志级别:notice
# 日志详细程度:debug > verbose > notice > warning
# 生产环境推荐notice(平衡详细度与性能)
loglevel notice

# 日志输出路径:空字符串(输出到标准输出)
# 容器环境下便于通过docker logs命令查看日志
logfile ""


################################## 数据库基础配置 ##################################
# 数据库数量:16个
# 注意:Redis Cluster仅使用db0,其他数据库无效
databases 16

# 启动时显示Logo:启用(yes)
# 仅影响启动日志输出,无功能影响,生产环境可设为no
always-show-logo yes


################################## RDB持久化配置 ##################################
# RDB快照触发条件(满足任一条件即执行)
save 900 1    # 900秒(15分钟)内有1次写入操作
save 300 10   # 300秒(5分钟)内有10次写入操作
save 60 10000 # 60秒(1分钟)内有10000次写入操作

# 快照生成失败时是否停止写入:是(yes)
# 生产环境建议开启,防止数据丢失却未察觉
stop-writes-on-bgsave-error yes

# RDB文件压缩:启用(yes)
# 压缩快照文件大小,代价是轻微CPU消耗,推荐开启
rdbcompression yes

# RDB文件校验:启用(yes)
# 加载快照时校验完整性,防止损坏的RDB导致节点启动失败
rdbchecksum yes

# RDB文件名:dump.rdb
# 快照文件名称,存储在dir指定的目录
dbfilename dump.rdb

# 数据存储目录:/bitnami/redis/data
# 需与Docker Compose的volumes挂载路径一致,确保数据持久化
dir /bitnami/redis/data


################################## 主从复制配置 ##################################
# 从节点服务过期数据:是(yes)
# 主节点故障时,从节点继续提供旧数据,避免服务中断
replica-serve-stale-data yes

# 从节点只读:是(yes)
# 防止从节点被误写入,保证主从数据一致性
replica-read-only yes

# 无盘复制:禁用(no)
# 关闭时使用磁盘传输数据,适合中小数据量;大数据量可设为yes减少IO
repl-diskless-sync no

# 无盘复制延迟:5秒
# 等待从节点准备就绪后再发送数据,避免网络拥塞
repl-diskless-sync-delay 5

# 禁用TCP_NODELAY:否(no)
# 关闭Nagle算法,减少数据传输延迟,加速主从同步
repl-disable-tcp-nodelay no

# 从节点优先级:100
# 数值越小优先级越高,故障转移时优先选择高优先级节点
replica-priority 100


################################## 安全配置 ##################################
# 访问密码:test@redis
# 集群所有节点必须使用相同密码,否则节点间无法通信
requirepass test@redis


################################## 惰性删除配置 ##################################
# 内存淘汰时惰性删除:否(no)
# 内存不足时立即删除过期键,适合数据一致性要求高的场景
lazyfree-lazy-eviction no

# 键过期时惰性删除:否(no)
# 键过期后立即删除,不延迟处理
lazyfree-lazy-expire no

# 服务器删除操作惰性执行:否(no)
# DEL命令立即执行,不交给后台线程
lazyfree-lazy-server-del no

# 从节点惰性清空数据:否(no)
# 从节点同步主节点数据时,立即清空旧数据
replica-lazy-flush no


################################## AOF持久化配置 ##################################
# 开启AOF持久化:是(yes)
# 生产环境建议开启,与RDB配合实现双保险
appendonly yes

# AOF文件名:appendonly.aof
# AOF日志文件名称,存储在dir指定目录
appendfilename "appendonly.aof"

# AOF刷盘策略:everysec(每秒一次)
# 策略对比:
# - always:每次写入都刷盘(最安全,性能最差)
# - everysec:每秒刷盘(平衡安全与性能,推荐)
# - no:由操作系统决定(性能最好,风险最高)
appendfsync everysec

# AOF重写时是否暂停刷盘:否(no)
# 重写期间继续刷盘,避免数据丢失
no-appendfsync-on-rewrite no

# AOF自动重写触发条件:
auto-aof-rewrite-percentage 100  # 文件大小比上次重写后增长100%(翻倍)
auto-aof-rewrite-min-size 64mb   # 文件最小达到64MB才可能触发重写

# 加载AOF时允许截断:是(yes)
# AOF文件损坏时,忽略损坏部分继续加载,避免节点启动失败
aof-load-truncated yes

# AOF混合持久化:是(yes)
# AOF文件头部存储RDB快照,尾部存储增量命令,兼顾加载速度与数据完整性
aof-use-rdb-preamble yes


################################## Lua脚本配置 ##################################
# Lua脚本执行超时时间:5000毫秒(5秒)
# 防止长时间运行的脚本阻塞Redis主线程
lua-time-limit 5000


################################## 集群核心配置 ##################################
# 开启集群模式:是(yes)
# 此参数是区分集群节点与单机节点的关键
cluster-enabled yes

# 集群配置文件:/bitnami/redis/data/nodes.conf
# 自动生成和维护,存储集群槽位分配、节点信息等,请勿手动修改
cluster-config-file /bitnami/redis/data/nodes.conf

# 集群宣告IP:172.24.32.232
# 节点向集群其他节点宣告的IP地址,必须是宿主机可访问的IP
# 与Docker Compose中的REDIS_CLUSTER_ANNOUNCE_IP保持一致
cluster-announce-ip 172.24.32.232


################################## 性能与监控配置 ##################################
# 慢查询阈值:10000微秒(10毫秒)
# 执行时间超过此值的命令会被记录到慢查询日志
slowlog-log-slower-than 10000

# 慢查询日志最大长度:128条
# 日志满后自动删除最旧的记录
slowlog-max-len 128

# 延迟监控阈值:0(关闭)
# 设为>0的值(毫秒)时开启,记录超过该阈值的延迟事件
latency-monitor-threshold 0

# 键空间事件通知:关闭(空字符串)
# 不发送任何事件通知,减少性能消耗;需使用时可配置(如"KEA")
notify-keyspace-events ""


################################## 数据结构优化配置 ##################################
# Hash结构压缩阈值
hash-max-ziplist-entries 512  # 元素数量≤512时使用紧凑存储
hash-max-ziplist-value 64     # 元素值≤64字节时使用紧凑存储

# List结构压缩配置
list-max-ziplist-size -2       # -2表示按字节限制(≤8KB时使用紧凑存储)
list-compress-depth 0          # 0表示不压缩列表两端的节点

# Set结构编码优化
set-max-intset-entries 512     # 元素≤512且全为整数时使用紧凑存储

# ZSet结构压缩阈值
zset-max-ziplist-entries 128   # 元素数量≤128时使用紧凑存储
zset-max-ziplist-value 64      # 元素值≤64字节时使用紧凑存储

# HyperLogLog存储优化
hll-sparse-max-bytes 3000      # ≤3000字节时使用稀疏存储

# Stream节点大小限制
stream-node-max-bytes 4096     # 单个节点最大4096字节
stream-node-max-entries 100    # 单个节点最多100个条目

# 主动重哈希:启用(yes)
# 定期优化Hash表,避免哈希冲突导致性能下降
activerehashing yes


################################## 客户端限制配置 ##################################
# 客户端输出缓冲区限制(防止单个客户端占用过多内存)
client-output-buffer-limit normal 0 0 0    # 普通客户端:无限制
client-output-buffer-limit replica 256mb 64mb 60  # 从节点客户端:256MB后限流,64MB持续60秒则断开
client-output-buffer-limit pubsub 32mb 8mb 60    # 订阅客户端:32MB后限流,8MB持续60秒则断开


################################## 系统优化配置 ##################################
# 主线程执行频率:10Hz(每秒10次)
# 高并发场景可提高至20-50,提升响应速度(会增加CPU消耗)
hz 10

# 动态调整主线程频率:启用(yes)
# 根据负载自动调整hz值,平衡性能与CPU消耗
dynamic-hz yes

# AOF重写增量刷盘:启用(yes)
# 重写AOF时每写32KB数据刷盘一次,避免磁盘IO峰值
aof-rewrite-incremental-fsync yes

# RDB快照增量刷盘:启用(yes)
# 生成RDB时每写32KB数据刷盘一次,优化磁盘IO
rdb-save-incremental-fsync yes

三、关键配置详解(避坑重点!)

在实战中,很多人搭建Redis Cluster后会遇到“节点无法通信”“远程无法连接”等问题,核心原因是对以下几个关键配置理解不到位,这里单独拎出来重点说明:

1. REDIS_CLUSTER_ANNOUNCE_IP与REDIS_CLUSTER_ANNOUNCE_PORT

这是最容易踩坑的配置,也是集群能正常工作的核心:

  • 背景:Redis Cluster节点之间需要互相通信,默认情况下,容器会使用自己的内部IP(如172.17.0.x)和内部端口(6379)向其他节点“宣告”自己的地址;但如果宿主机外的服务要访问集群,或宿主机有端口映射,内部地址会导致“节点可达性问题”。

  • 解决方案:

    • REDIS_CLUSTER_ANNOUNCE_IP:填写宿主机的IP地址(如配置中的172.24.32.232,需确保其他节点/服务能访问该IP);

    • REDIS_CLUSTER_ANNOUNCE_PORT:填写宿主机的映射端口(如node0的6380,而非容器内的6379),确保外部流量能通过宿主机端口转发到容器。

2. REDIS_CLUSTER_CREATOR=yes与depends_on

集群初始化需要一个“发起者”节点,负责执行redis-cli --cluster create命令:

  • REDIS_CLUSTER_CREATOR=yes:标记redis-node-2为“创建者”,该节点启动后会自动执行集群初始化,无需手动操作;

  • depends_on: [redis-node-0, redis-node-1]:确保另外两个节点先启动,避免初始化时节点未就绪导致失败。

3. 自定义网络(networks)

默认情况下,Docker Compose会创建一个默认网络,但可能与宿主机其他服务的子网冲突(如172.17.0.0是Docker默认桥接网段):

  • 配置中指定subnet: 172.28.0.0/16,为Redis集群分配独立网段,彻底避免IP冲突问题;

  • 网络驱动使用bridge,适合单机部署;如果是多机部署,可改用overlay网络。

4. 数据卷(volumes)

每个节点对应一个独立的数据卷(redis-cluster_data-0/1/2):

  • 作用:持久化Redis数据,即使容器被删除,数据仍保存在宿主机的/var/lib/docker/volumes/目录下;

  • 优势:节点重启、重建时,数据不会丢失,保证集群数据一致性。

四、集群部署与验证步骤

理解配置后,实际部署只需3步,非常简单:

步骤1:准备配置文件

在宿主机创建一个目录(如redis-cluster),并在该目录下创建docker-compose.yml文件,将上文的完整配置复制进去。

步骤2:启动Redis Cluster集群

在redis-cluster目录下执行以下命令,启动集群(-d表示后台运行):

docker-compose up -d

启动后可通过以下命令查看容器状态,确保3个节点都处于Up状态:

docker-compose ps

步骤3:验证集群可用性

验证1:进入容器查看集群信息

选择任意一个节点(如redis-node-0),进入容器内部:

docker-compose exec redis-node-0 bash

在容器内执行redis-cli命令(需输入密码),查看集群状态:

redis-cli -a test@redis cluster info

如果输出类似以下内容,说明集群正常(cluster_state:ok表示集群状态健康):

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
...

验证2:测试数据读写

在redis-cli中执行数据写入与读取,验证分片功能(Redis Cluster会将数据按槽位分配到不同节点):

# 写入数据(key为"test_key")
set test_key "hello_redis_cluster"
# 读取数据
get test_key
# 查看该key所在的节点
cluster keyslot test_key

如果能正常写入并读取,且cluster keyslot能返回对应的槽位(如15495),说明集群分片功能正常。

验证3:远程访问测试

在另一台能访问宿主机(172.24.32.232)的机器上,使用redis-cli远程连接集群(需指定任意一个节点的宿主机IP和端口):

redis-cli -h 172.24.32.232 -p 6380 -a test@redis

连接成功后执行cluster nodes,能看到所有3个节点的信息,说明远程访问正常。

五、常见问题与解决方案

在部署过程中,可能会遇到以下问题,这里提供针对性解决方案:

问题1:集群启动后cluster_state:fail

  • 原因:节点之间无法通信,大概率是REDIS_CLUSTER_ANNOUNCE_IP或REDIS_CLUSTER_ANNOUNCE_PORT配置错误;

  • 解决方案:

    1. 确认REDIS_CLUSTER_ANNOUNCE_IP是宿主机的正确IP(可通过ifconfig或ip addr查看);

    2. 确认REDIS_CLUSTER_ANNOUNCE_PORT与ports中的宿主机端口一致(如node0的6380);

    3. 重启集群:docker-compose down && docker-compose up -d。

问题2:远程无法连接集群

  • 原因:

    1. 宿主机防火墙未开放6380/6381/6382端口;

    2. REDIS_ALLOW_REMOTE_CONNECTIONS未设置为yes;

  • 解决方案:

    1. 开放端口(以CentOS为例):

      firewall-cmd --zone=public --add-port=6380-6382/tcp --permanent
      firewall-cmd --reload
      
    2. 确认environment中REDIS_ALLOW_REMOTE_CONNECTIONS=yes。

问题3:容器启动后立即退出

  • 原因:数据卷权限不足,或之前的集群数据残留导致冲突;

  • 解决方案:

    1. 删除旧数据卷:docker volume rm redis-cluster_redis-cluster_data-0 redis-cluster_redis-cluster_data-1 redis-cluster_redis-cluster_data-2;

    2. 重启集群:docker-compose up -d。

六、扩展建议

本文搭建的是3主0从的简化版集群,适合测试或小规模应用;如果用于生产环境,建议优化以下几点:

  1. 增加从节点:将REDIS_CLUSTER_REPLICAS设置为1或2,为每个主节点配置从节点,实现故障自动切换(如3主3从);

  2. 启用密码复杂度:将REDIS_PASSWORD改为更复杂的密码(包含大小写、数字、特殊字符),避免暴力破解;

  3. 挂载自定义配置文件:如果需要修改Redis的核心配置(如maxmemory、appendonly),可通过volumes挂载自定义的redis.conf文件;

  4. 监控集群状态:使用Redis官方的redis-cli cluster info,或第三方工具(如Prometheus + Grafana)监控集群健康度、内存使用率等指标。

0

评论区