1. 环境准备与基础概念
Redis集群在Docker环境下的部署已经成为现代分布式系统开发的标配方案。作为一名长期在生产环境使用Redis的老兵,我见过太多因为基础环境配置不当导致的集群问题。让我们从最基础的准备工作开始。
1.1 系统要求与Docker安装
首先需要一台Linux主机(推荐Ubuntu 20.04 LTS或CentOS 7+),配置建议:
- 至少2核CPU
- 4GB以上内存
- 20GB可用磁盘空间
Docker安装建议使用官方脚本:
bash复制# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 设置稳定版仓库
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装Docker引擎
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 验证安装
sudo docker run hello-world
注意:生产环境务必配置Docker用户组,避免频繁使用sudo。执行
sudo usermod -aG docker $USER后需要重新登录生效。
1.2 Redis集群架构设计
我们采用三主三从的经典架构,这种设计在容错性和性能之间取得了良好平衡:
- 每个主节点对应一个从节点
- 数据自动分片到不同主节点
- 主节点故障时从节点自动提升
端口规划如下:
| 节点类型 | 容器端口 | 宿主机端口 | 容器名称 |
|---|---|---|---|
| 主节点1 | 7000 | 7000 | redis-7000 |
| 从节点1 | 7001 | 7001 | redis-7001 |
| 主节点2 | 7002 | 7002 | redis-7002 |
| 从节点2 | 7003 | 7003 | redis-7003 |
| 主节点3 | 7004 | 7004 | redis-7004 |
| 从节点4 | 7005 | 7005 | redis-7005 |
2. Redis镜像获取与配置
2.1 获取特定版本Redis镜像
在生产环境中,我强烈建议锁定Redis版本以避免意外升级带来的兼容性问题。这里我们使用Redis 6.0.6:
bash复制docker pull redis:6.0.6
验证镜像:
bash复制docker images | grep redis
预期输出应包含:
code复制redis 6.0.6 sha256:... 3 days ago 104MB
2.2 配置文件详解
Redis集群的配置文件是关键所在,以下是7000节点的完整配置示例(/usr/local/docker/redis/7000/redis.conf):
conf复制port 7000
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 20000
cluster-announce-ip 192.168.93.71
cluster-announce-port 7000
cluster-announce-bus-port 17000
重要参数说明:
cluster-announce-*系列参数:在Docker网络环境中必须明确声明IP和端口cluster-node-timeout:节点超时时间(毫秒),超过此时长则认为节点不可用appendonly:开启AOF持久化,比RDB更可靠但会牺牲一些性能
创建配置文件的实用技巧:
bash复制for port in {7000..7005}; do
mkdir -p /usr/local/docker/redis/$port/data
cat > /usr/local/docker/redis/$port/redis.conf <<EOF
port $port
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes-$port.conf
cluster-node-timeout 20000
cluster-announce-ip 192.168.93.71
cluster-announce-port $port
cluster-announce-bus-port 1$port
EOF
done
3. 容器化部署实战
3.1 启动Redis节点容器
使用host网络模式可以简化集群通信,以下是7000节点的启动命令:
bash复制docker run -d \
--name redis-7000 \
--net host \
-v /usr/local/docker/redis/7000/redis.conf:/etc/redis/redis.conf \
-v /usr/local/docker/redis/7000/data:/data \
redis:6.0.6 \
redis-server /etc/redis/redis.conf
关键参数解析:
--net host:使用主机网络,避免NAT带来的复杂性- 卷挂载:将配置和数据持久化到宿主机
- 启动命令:指定配置文件路径
批量启动所有节点的脚本:
bash复制for port in {7000..7005}; do
docker run -d \
--name redis-$port \
--net host \
-v /usr/local/docker/redis/$port/redis.conf:/etc/redis/redis.conf \
-v /usr/local/docker/redis/$port/data:/data \
redis:6.0.6 \
redis-server /etc/redis/redis.conf
done
验证容器状态:
bash复制docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep redis
3.2 集群初始化
当所有节点都运行后,执行集群创建命令:
bash复制redis-cli --cluster create \
192.168.93.71:7000 \
192.168.93.71:7001 \
192.168.93.71:7002 \
192.168.93.71:7003 \
192.168.93.71:7004 \
192.168.93.71:7005 \
--cluster-replicas 1
参数说明:
--cluster-replicas 1:每个主节点分配1个从节点- IP地址必须与
cluster-announce-ip一致
预期输出应包含:
code复制[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
3.3 集群验证
进入任意节点验证集群状态:
bash复制docker exec -it redis-7000 redis-cli -p 7000 cluster nodes
健康检查命令:
bash复制docker exec -it redis-7000 redis-cli -p 7000 cluster info
4. 生产环境优化与故障处理
4.1 性能调优建议
-
内存管理:
- 设置
maxmemory为物理内存的70% - 使用
maxmemory-policy allkeys-lru进行内存回收
- 设置
-
持久化配置:
conf复制appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb -
内核参数调整:
bash复制echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf echo "net.core.somaxconn = 65535" >> /etc/sysctl.conf sysctl -p
4.2 常见问题排查
问题1:集群创建时报错"Node not empty"
- 原因:旧数据未清理
- 解决:删除所有节点的data目录内容后重启容器
问题2:从节点无法同步数据
- 检查项:
- 网络连通性
- 防火墙设置
- 主节点内存是否充足
问题3:集群节点状态显示fail
- 恢复步骤:
bash复制# 首先检查节点日志 docker logs redis-7000 # 尝试手动恢复 redis-cli -p 7000 cluster failover
4.3 监控与维护
推荐监控方案:
-
Redis自带命令:
bash复制redis-cli -p 7000 --stat redis-cli -p 7000 --bigkeys -
Prometheus+Granafa:
- 使用redis_exporter采集指标
- 配置告警规则
-
日志收集:
bash复制
docker logs -f redis-7000 > redis-7000.log &
5. 高级配置与扩展
5.1 自定义Docker网络
虽然host模式简单,但bridge模式更安全:
bash复制# 创建自定义网络
docker network create redis-net --subnet 172.28.0.0/16
# 启动容器时指定网络
docker run -d \
--name redis-7000 \
--net redis-net \
--ip 172.28.0.10 \
...
5.2 TLS加密配置
生成证书:
bash复制openssl genrsa -out redis.key 2048
openssl req -new -key redis.key -out redis.csr
openssl x509 -req -in redis.csr -signkey redis.key -out redis.crt
修改配置:
conf复制tls-port 7000
port 0
tls-cert-file /path/to/redis.crt
tls-key-file /path/to/redis.key
tls-cluster yes
5.3 集群扩容方案
横向扩展步骤:
- 启动新节点
- 加入集群:
bash复制
redis-cli --cluster add-node 新节点IP:端口 现有节点IP:端口 - 重新分配槽位:
bash复制
redis-cli --cluster reshard 现有节点IP:端口
6. 最佳实践总结
经过多年实践,我总结了以下Redis集群的黄金法则:
- 版本一致性:所有节点必须使用相同Redis版本
- 资源隔离:生产环境不要与其他服务混部
- 监控先行:在问题发生前建立完善的监控
- 定期备份:即使有持久化也要定期备份数据
- 测试验证:任何配置变更前先在测试环境验证
对于关键业务系统,建议部署哨兵集群监控Redis集群状态,实现自动故障转移。同时考虑多机房部署方案,使用Redis的异地多活功能保障业务连续性。