[!note] 以下是为 Redis 7.2.4(最新版本-我替换成了latest)编写的完整
docker-compose.yml
文件,包含 6 个节点 (3 主 + 3 从) 的完整配置:
安装 #
version: '3.8'
services:
redis-7000:
image: redis:latest
container_name: redis-7000
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./config/redis-7000.conf:/usr/local/etc/redis/redis.conf
- ./data/7000:/data
networks:
- redis-cluster-net
ports:
- "7000:7000"
- "17000:17000"
redis-7001:
image: redis:latest
container_name: redis-7001
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./config/redis-7001.conf:/usr/local/etc/redis/redis.conf
- ./data/7001:/data
networks:
- redis-cluster-net
ports:
- "7001:7001"
- "17001:17001"
redis-7002:
image: redis:latest
container_name: redis-7002
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./config/redis-7002.conf:/usr/local/etc/redis/redis.conf
- ./data/7002:/data
networks:
- redis-cluster-net
ports:
- "7002:7002"
- "17002:17002"
redis-7003:
image: redis:latest
container_name: redis-7003
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./config/redis-7003.conf:/usr/local/etc/redis/redis.conf
- ./data/7003:/data
networks:
- redis-cluster-net
ports:
- "7003:7003"
- "17003:17003"
redis-7004:
image: redis:latest
container_name: redis-7004
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./config/redis-7004.conf:/usr/local/etc/redis/redis.conf
- ./data/7004:/data
networks:
- redis-cluster-net
ports:
- "7004:7004"
- "17004:17004"
redis-7005:
image: redis:latest
container_name: redis-7005
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- ./config/redis-7005.conf:/usr/local/etc/redis/redis.conf
- ./data/7005:/data
networks:
- redis-cluster-net
ports:
- "7005:7005"
- "17005:17005"
networks:
redis-cluster-net:
driver: bridge
配套操作步骤 #
- 创建目录和配置文件
mkdir -p redis-cluster/{config,data/{7000,7001,7002,7003,7004,7005}}
cd redis-cluster
- 生成所有配置文件(一键生成脚本)
for port in {7000..7005}; do
cat > config/redis-${port}.conf <<EOF
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
dir /data
# 重要:替换为你的宿主机IP(非容器IP)
cluster-announce-ip 192.168.1.100
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
EOF
done
- 启动所有容器
podman-compose up -d
- 初始化集群
podman exec -it redis-7000 redis-cli --cluster create \
$(for port in {7000..7005}; do echo -n "$(hostname -I | awk '{print $1}'):${port} "; done) \
--cluster-replicas 1
关键配置说明 #
cluster-announce-ip
参数- 必须设置为 宿主机的真实 IP(不能是
127.0.0.1
或容器 IP) - 如果使用局域网访问,例如
192.168.1.100
- 如果使用公网访问,设置为公网 IP
- 必须设置为 宿主机的真实 IP(不能是
端口映射规则
- 客户端端口:
7000-7005
- 集群总线端口:
17000-17005
(必须开放)
- 客户端端口:
安全建议(生产环境必做)
# 在配置文件中添加以下内容 requirepass your_strong_password masterauth your_strong_password
验证集群状态 #
# 查看集群信息
podman exec -it redis-7000 redis-cli -p 7000 cluster info
# 查看节点拓扑
podman exec -it redis-7000 redis-cli -p 7000 cluster nodes
常见问题解决 #
节点无法加入集群
- 检查
cluster-announce-ip
是否能被其他节点访问 - 检查防火墙是否开放
7000-7005
和17000-17005
端口
- 检查
客户端连接超时
- 确保客户端使用 宿主机的 IP 而不是容器 IP
- 检查 Redis 配置文件中的
port
和cluster-announce-port
是否一致
使用 #
Python #
from loguru import logger
from redis.cluster import RedisCluster, ClusterNode
def test_redis_cluster():
# 使用 ClusterNode 对象,并确保端口为 int 类型
# 可以只使用一个node也可以传入多个防止单个故障无法连接(单个连接成功后会自动发现其它)
startup_nodes = [
ClusterNode(host="192.168.105.156", port=7000),
ClusterNode(host="192.168.105.156", port=7001),
ClusterNode(host="192.168.105.156", port=7002),
]
try:
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
except Exception as e:
logger.error(f"连接 Redis 集群失败: {e}")
return
# 测试写入和读取数据
try:
rc.set("test-key", "hello redis cluster")
value = rc.get("test-key")
logger.info(f"test-key: {value}")
except Exception as e:
logger.error(f"操作 Redis 集群失败: {e}")
if __name__ == "__main__":
test_redis_cluster()
异步IO #
import asyncio
from loguru import logger
from redis.asyncio.cluster import RedisCluster, ClusterNode
async def test_redis_cluster():
# 定义集群启动节点,使用 ClusterNode 对象,确保端口为 int 类型
startup_nodes = [
ClusterNode(host="192.168.105.156", port=7000),
ClusterNode(host="192.168.105.156", port=7001),
ClusterNode(host="192.168.105.156", port=7002),
]
try:
# 创建 Redis 集群客户端
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
except Exception as e:
logger.error(f"连接 Redis 集群失败: {e}")
return
try:
# 异步写入数据
await rc.set("test-key", "hello redis cluster")
# 异步读取数据
value = await rc.get("test-key")
logger.info(f"test-key: {value}")
except Exception as e:
logger.error(f"操作 Redis 集群失败: {e}")
finally:
# 使用 aclose() 方法关闭客户端连接
await rc.aclose()
if __name__ == "__main__":
asyncio.run(test_redis_cluster())