本文章将介绍如何在 Windows 系统的 Docker Desktop 环境中搭建 Redis 集群。将创建一个包含 6 个节点(3 主 3 从)的 Redis 集群。
环境准备
- Windows 10/11 操作系统
- Docker Desktop 已安装并运行
步骤
清理环境(如之前有尝试)
如果之前已经尝试过创建 Redis 集群,请先执行清理操作:
# 停止并删除所有 Redis 容器
docker stop redis-7001 redis-7002 redis-7003 redis-7004 redis-7005 redis-7006 2>$null
docker rm redis-7001 redis-7002 redis-7003 redis-7004 redis-7005 redis-7006 2>$null
# 删除网络
docker network rm redis-cluster-net 2>$null
# 删除本地目录和配置文件
Remove-Item -Recurse -Force ~/redis-cluster 2>$null
# 确认清理完成
docker ps -a | Select-String "redis-7"
docker network ls | Select-String "redis-cluster-net"
创建 Docker 网络
docker network create redis-cluster-net
创建目录结构
# 创建主目录
mkdir ~/redis-cluster
cd ~/redis-cluster
# 为每个节点创建目录
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
New-Item -ItemType Directory -Path "$port/conf" -Force
New-Item -ItemType Directory -Path "$port/data" -Force
}
创建 Redis 配置文件
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
$confContent = @"
port $port
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
protected-mode no
bind 0.0.0.0
"@
Set-Content -Path "$port/conf/redis.conf" -Value $confContent
}
启动 Redis 容器
# Redis 7001
docker run -d --name redis-7001 -p 7001:7001 -p 17001:17001 -v ${PWD}/7001/conf/redis.conf:/etc/redis/redis.conf -v ${PWD}/7001/data:/data --network redis-cluster-net redis:latest redis-server /etc/redis/redis.conf
# Redis 7002
docker run -d --name redis-7002 -p 7002:7002 -p 17002:17002 -v ${PWD}/7002/conf/redis.conf:/etc/redis/redis.conf -v ${PWD}/7002/data:/data --network redis-cluster-net redis:latest redis-server /etc/redis/redis.conf
# Redis 7003
docker run -d --name redis-7003 -p 7003:7003 -p 17003:17003 -v ${PWD}/7003/conf/redis.conf:/etc/redis/redis.conf -v ${PWD}/7003/data:/data --network redis-cluster-net redis:latest redis-server /etc/redis/redis.conf
# Redis 7004
docker run -d --name redis-7004 -p 7004:7004 -p 17004:17004 -v ${PWD}/7004/conf/redis.conf:/etc/redis/redis.conf -v ${PWD}/7004/data:/data --network redis-cluster-net redis:latest redis-server /etc/redis/redis.conf
# Redis 7005
docker run -d --name redis-7005 -p 7005:7005 -p 17005:17005 -v ${PWD}/7005/conf/redis.conf:/etc/redis/redis.conf -v ${PWD}/7005/data:/data --network redis-cluster-net redis:latest redis-server /etc/redis/redis.conf
# Redis 7006
docker run -d --name redis-7006 -p 7006:7006 -p 17006:17006 -v ${PWD}/7006/conf/redis.conf:/etc/redis/redis.conf -v ${PWD}/7006/data:/data --network redis-cluster-net redis:latest redis-server /etc/redis/redis.conf
检查容器状态
docker ps
如下图所示
初始化 Redis 集群
docker exec -it redis-7001 redis-cli --cluster create redis-7001:7001 redis-7002:7002 redis-7003:7003 redis-7004:7004 redis-7005:7005 redis-7006:7006 --cluster-replicas 1
当提示时输入 yes
确认配置。
验证集群状态
docker exec -it redis-7001 redis-cli -c -p 7001 cluster nodes
如下图所示 :
测试集群功能
docker exec -it redis-7001 redis-cli -c -p 7001
测试Redis是否可用,可用则搭建成功 !
在 Redis CLI 中执行:
set test1 "hello"
set test2 "world"
get test1
get test2
简化版本(3 节点集群)
如果您只需要 3 个主节点(没有从节点),可以只创建 7001-7003,然后在初始化集群时使用以下命令:
docker exec -it redis-7001 redis-cli --cluster create redis-7001:7001 redis-7002:7002 redis-7003:7003 --cluster-replicas 0
使用
要停止集群,可以使用 docker stop
命令停止所有容器。要重新启动,只需使用 docker start
命令启动容器,集群会自动恢复。
常见问题解决
- 端口冲突:确保 7001-7006 以及 17001-17006 端口没有被其他程序占用
- 权限问题:如果遇到文件权限问题,尝试以管理员身份运行 PowerShell
- 容器启动失败:检查 Docker Desktop 是否正常运行,并确保有足够的内存分配
高级功能
密码认证配置
修改配置文件
- 将
your_secure_password_here
更换为自己的密码
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
$confContent = @"
port $port
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
protected-mode no
bind 0.0.0.0
requirepass your_secure_password_here
masterauth your_secure_password_here
"@
Set-Content -Path "$port/conf/redis.conf" -Value $confContent
}
启动带认证的容器
# 示例:Redis 7001 带认证
docker run -d --name redis-7001 -p 7001:7001 -p 17001:17001 `
-v ${PWD}/7001/conf/redis.conf:/etc/redis/redis.conf `
-v ${PWD}/7001/data:/data `
--network redis-cluster-net `
redis:latest redis-server /etc/redis/redis.conf
初始化带认证的集群
docker exec -it redis-7001 redis-cli -a your_secure_password_here --cluster create `
redis-7001:7001 redis-7002:7002 redis-7003:7003 `
redis-7004:7004 redis-7005:7005 redis-7006:7006 `
--cluster-replicas 1
持久化配置优化
AOF 和 RDB 混合持久化
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
$confContent = @"
port $port
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
save 900 1
save 300 10
save 60 10000
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data
protected-mode no
bind 0.0.0.0
requirepass your_secure_password_here
masterauth your_secure_password_here
"@
Set-Content -Path "$port/conf/redis.conf" -Value $confContent
}
内存管理和淘汰策略
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
$confContent = @"
port $port
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
maxmemory 1gb
maxmemory-policy volatile-lru
protected-mode no
bind 0.0.0.0
requirepass your_secure_password_here
masterauth your_secure_password_here
"@
Set-Content -Path "$port/conf/redis.conf" -Value $confContent
}
监控和慢查询日志
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
$confContent = @"
port $port
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 100
protected-mode no
bind 0.0.0.0
requirepass your_secure_password_here
masterauth your_secure_password_here
"@
Set-Content -Path "$port/conf/redis.conf" -Value $confContent
}
集群管理和监控工具
安装 redis-cli 工具
# 在 Windows 上安装 Redis CLI
choco install redis-64
使用 RedisInsight 进行可视化监控
- 下载并安装 RedisInsight
- 连接到集群中的任意节点
- 查看集群状态、内存使用情况、慢查询等
使用命令行工具监控集群
# 查看集群信息
docker exec -it redis-7001 redis-cli -c -p 7001 -a your_secure_password_here cluster info
# 查看节点信息
docker exec -it redis-7001 redis-cli -c -p 7001 -a your_secure_password_here cluster nodes
# 查看内存使用情况
docker exec -it redis-7001 redis-cli -c -p 7001 -a your_secure_password_here info memory
# 查看持久化信息
docker exec -it redis-7001 redis-cli -c -p 7001 -a your_secure_password_here info persistence
备份和恢复策略
创建备份脚本
# backup-redis.ps1
$date = Get-Date -Format "yyyyMMdd"
$backupDir = "~/redis-backups/$date"
New-Item -ItemType Directory -Path $backupDir -Force
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
docker exec redis-$port redis-cli -a your_secure_password_here save
Copy-Item -Path "~/redis-cluster/$port/data/dump.rdb" -Destination "$backupDir/dump-$port.rdb"
Copy-Item -Path "~/redis-cluster/$port/data/appendonly.aof" -Destination "$backupDir/appendonly-$port.aof"
}
Write-Host "Backup completed to $backupDir"
创建恢复脚本
# restore-redis.ps1
param(
[Parameter(Mandatory=$true)]
[string]$backupDate
)
$backupDir = "~/redis-backups/$backupDate"
if (-not (Test-Path $backupDir)) {
Write-Error "Backup directory $backupDir does not exist"
exit 1
}
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
docker stop redis-$port
Remove-Item -Path "~/redis-cluster/$port/data/dump.rdb" -Force -ErrorAction SilentlyContinue
Remove-Item -Path "~/redis-cluster/$port/data/appendonly.aof" -Force -ErrorAction SilentlyContinue
Copy-Item -Path "$backupDir/dump-$port.rdb" -Destination "~/redis-cluster/$port/data/dump.rdb"
Copy-Item -Path "$backupDir/appendonly-$port.aof" -Destination "~/redis-cluster/$port/data/appendonly.aof"
docker start redis-$port
}
Write-Host "Restore completed from $backupDir"
Redis 性能优化
foreach ($port in @(7001, 7002, 7003, 7004, 7005, 7006)) {
$confContent = @"
port $port
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
maxmemory 2gb
maxmemory-policy allkeys-lru
maxclients 10000
tcp-backlog 511
timeout 0
tcp-keepalive 300
protected-mode no
bind 0.0.0.0
requirepass your_secure_password_here
masterauth your_secure_password_here
"@
Set-Content -Path "$port/conf/redis.conf" -Value $confContent
}
配置解释
port $port
- 作用:指定 Redis 实例监听的端口号。
- 说明:在循环中,
$port
变量会被替换为 7001, 7002 等,确保每个容器使用独立的端口。
cluster-enabled yes
- 作用:启用 Redis 的集群模式。
- 说明:这是将 Redis 实例转变为集群节点的最关键配置,没有它,节点只会以单机模式运行。
cluster-config-file nodes.conf
- 作用:指定集群自动生成的配置文件名称。
- 说明:Redis 集群运行时会自动维护这个文件,记录集群的状态、节点信息、持久化变量等。用户不应手动修改此文件。
cluster-node-timeout 5000
- 作用:设置集群节点不可用的超时时间(毫秒)。
- 说明:如果一个节点在 5000ms(5秒)内无法响应,它将被其他节点视为故障节点,并触发主从切换(failover)。这个值需要根据网络状况调整,太短可能导致不必要的故障转移,太长则会影响故障恢复速度。
appendonly yes
- 作用:启用 AOF(Append Only File)持久化模式。
- 说明:相比于默认的 RDB 快照,AOF 通过记录 every 写操作命令来持久化数据,能提供更好的数据安全性,通常最多丢失 1 秒的数据(取决于
appendfsync
配置)。
appendfsync everysec
- 作用:控制 AOF 文件同步到磁盘的频率。
- 说明:
everysec
(推荐):每秒同步一次。在性能和数据安全性之间取得了很好的平衡,即使故障,最多丢失 1 秒的数据。always
:每个写命令都同步。最安全,但性能最差。no
:由操作系统决定何时同步。性能最好,但可能丢失较多数据。
auto-aof-rewrite-percentage 100
- 作用:与下一项配合,触发 AOF 文件重写(rewrite)的条件之一。
- 说明:当当前 AOF 文件大小比上一次重写后的大小增长了 100%(即翻了一倍)时,会触发重写。
auto-aof-rewrite-min-size 64mb
- 作用:触发 AOF 文件重写的另一个条件。
- 说明:AOF 文件至少要达到 64MB 才会触发重写。这个配置防止文件很小的时候就频繁重写。
- 两者关系:必须同时满足“增长百分比达到 100%” 且 “文件大小超过 64MB” 才会触发重写。重写可以压缩 AOF 文件,移除冗余命令。
maxmemory 2gb
- 作用:设置 Redis 实例可使用的最大内存容量。
- 说明:这是防止 Redis 占用所有系统内存、导致系统崩溃的关键配置! 你必须根据你的 Docker 容器内存限制和宿主机总内存来设置这个值(例如,设置为容器内存限制的 80-90%)。
2gb
只是一个示例值。
maxmemory-policy allkeys-lru
- 作用:定义当内存使用达到
maxmemory
限制时,Redis 的键淘汰策略(eviction policy)。 - 说明:
allkeys-lru
意味着当内存不足时,Redis 会尝试移除所有键中最近最少使用(LRU)的键,以腾出空间。 - 其他常见策略:
volatile-lru
:只从设置了过期时间的键中移除最近最少使用的键。allkeys-random
:随机移除所有键。noeviction
(默认):不淘汰任何键,在写操作时返回错误。生产环境通常不推荐。
- 作用:定义当内存使用达到
maxclients 10000
- 作用:设置同一时间最大客户端连接数。
- 说明:默认是 10000。如果达到此限制,Redis 会拒绝新的连接。需要根据系统资源和应用需求调整。
tcp-backlog 511
- 作用:设置 TCP 连接队列的长度。
- 说明:在高连接速率环境下,增大这个值可以帮助处理连接高峰。需要同时调整系统的
/proc/sys/net/core/somaxconn
值(在 Docker 中可能需要通过sysctls
参数设置)。
timeout 0
- 作用:客户端空闲 N 秒后关闭连接(0 表示禁用)。
- 说明:设置为
0
意味着连接将始终保持打开,除非客户端主动断开。这适用于需要长连接的场景,避免了频繁创建连接的开销。
tcp-keepalive 300
- 作用:向客户端发送 TCP ACK 保活探测的间隔时间(秒)。
- 说明:设置为
300
表示如果连接空闲,每 300 秒(5分钟)会发送一个保活包,以检测连接是否仍然有效并保持连接活跃。有助于清理僵尸连接。
protected-mode no
- 作用:是否启用保护模式。
- 说明:在 Docker 容器或受信任的网络环境中,需要设置为
no
以允许远程连接。如果为yes
(默认),且没有配置密码和绑定 IP,Redis 只会回环地址(127.0.0.1)连接。
bind 0.0.0.0
- 作用:指定 Redis 监听所有网络接口上的连接。
- 说明:在 Docker 中,必须设置为
0.0.0.0
才能让容器外的客户端(包括其他容器和宿主机)访问到它。如果只绑定127.0.0.1
,则只能在容器内部访问。
requirepass your_secure_password_here
- 作用:设置客户端连接 Redis 所需的密码。
- 说明:极大增强了安全性,防止未授权访问。 所有节点应使用相同的密码。
your_secure_password_here
应被替换为一个非常强壮且唯一的密码。
masterauth your_secure_password_here
- 作用:设置从节点(replica)连接主节点进行数据复制时所需的密码。
- 说明:必须与
requirepass
的密码一致。这样,当主从节点之间需要通信或故障转移时,它们才能成功地进行认证和数据同步。