资讯动态

Docker部署Redis Cluster实战:三主三从高可用集群搭建指南

发布时间:2026/10/16 6:29:03 来源:尧图企业网站定制
1. 项目概述与整体拆解1.1 为什么要在Docker里部署Redis Cluster先说结论用Docker跑Redis Cluster不是炫技而是被现实逼出来的方案。我最早在裸机上搭Redis Cluster三主三从六个实例光环境准备就折腾了大半天。每台机器要装Redis、调内核参数、开防火墙端口、写systemd服务中间只要有一台机器的版本不对整个集群的二进制协议兼容性就可能出问题。后来换到Docker一次拉镜像、批量起容器半小时就能拿到一套可用的集群。这不是说Docker就一定比裸机好而是对于需要频繁重建、迁移、扩容的开发和测试环境容器的优势太明显了。另一个重要的动机是环境一致性。Redis Cluster对节点间通信的依赖很强节点版本不一致、配置参数漂移都会产生莫名其妙的故障。Docker镜像把Redis版本、依赖库、运行环境全部固化在一个镜像里不管在哪台机器上跑行为都是一致的。这个特性在多人协作时尤其有用我见过太多因为我本地能跑、你环境不行而引发的扯皮用容器封装之后这类问题基本绝迹。还要说清楚一个适用边界如果你的业务是核心生产环境、有严格的性能要求和SLA保证我建议优先考虑裸机或Kubernetes等编排平台上的裸金属Pod方案。因为Docker的网络转发会带来一定的性能损耗特别是跨节点访问时的延迟增加。但如果你是开发环境、测试环境、演示环境或者业务规模还在百GB数据量级别以内Docker这套方案完全够用而且省心。1.2 这次要搭建的目标拓扑我们这次搭建的目标集群是六节点三主三从也就是官方推荐的Redis Cluster最小高可用架构。为什么是三主三从而不是三主零从或者两主两从因为Redis Cluster的哈希槽总数为16384个一个主节点至少要分担超过5000个槽位才能发挥集群的横向扩展能力。三主节点时每个节点分管大约5461个槽负载相对均衡。如果只有两个主节点虽然技术上可行但会浪费一个节点的容量而且在故障转移时能用的副本数量也不够。三从节点的价值在于故障转移。某个主节点宕机时它的从节点会自动提升为新的主节点这个过程由集群自身的 Gossip 协议和配置纪元configuration epoch机制驱动不需要人工介入。如果某个主节点没有从节点那它宕机后这5000多个槽位直接不可用整个集群等于部分瘫痪。所以生产上至少需要一主一从三主三从是兼顾成本和可用性的平衡点。网络层面我们这次采用Docker bridge网络加固定IP的方式。每个Redis容器分配一个静态IP集群节点之间通过这个IP通信。为什么不直接使用Docker内置的DNS服务名比如redis-1:6379因为Redis Cluster的节点间通信基于IP和端口它会把这些信息写入nodes.conf文件并在节点之间互相传播。如果用容器名通信集群重建或容器重启后节点记录的IP信息可能失效造成节点不可达的问题。固定IP是这条路线上最稳的方案。当然如果你只有一台机器且不关心外部访问也可以直接用--network host模式让容器共享宿主机网络。这个方案更简单省去了端口映射和IP配置的麻烦但缺点是只能在本机访问不适合与外部系统集成而且多个容器共享网络栈后端口管理容易混乱。我们这次以bridge模式为主讲解host模式在常见问题章节再做补充说明。1.3 投入产出比评估动手之前先帮你算一笔时间账。按照下面的步骤操作熟练的话15到20分钟可以完成集群搭建。这里统计的是纯操作时间不包括镜像下载时间。镜像拉取视网络情况约1到3分钟编写六个节点的配置文件和目录约5分钟启动六个容器约2分钟创建集群并分配槽位约1分钟验证集群状态约2分钟这个效率比手动在六台虚拟机或裸机上配置高出一个量级。如果你使用脚本批量生成配置时间还能压缩到5分钟以内。这就是Docker在Redis Cluster场景下最直接的价值——用标准化流程替代重复劳动。2. 核心配置细节解析2.1 Redis镜像与版本选型镜像选择上我长期使用的是官方镜像redis不推荐用第三方的优化版镜像。原因有三个。第一官方镜像的更新节奏与Redis上游版本保持同步安全漏洞修复及时。第二官方镜像的默认配置与Redis官方文档一致排查问题时资料最好找。第三第三方面向特定业务的镜像往往会预置一些插件或配置这些未知变量在集群环境里很难排查。版本选择方面建议使用Redis 6.x或7.x。Redis 6.0引入了ACL访问控制列表、SSL支持、诸多性能优化Redis 7.0进一步强化了集群功能比如支持在集群模式下使用部分命令、更好的内存效率。我这次实测使用的是Redis 7.x镜像如果你还在用Redis 5.x建议尽早升级因为旧版本的集群故障转移速度和稳定性都有差距。需要注意的一点是同一个集群内所有节点的镜像版本必须完全一致包括小版本号。我曾经因为混用6.2.7和6.2.6两个小版本导致在故障转移测试时出现RDB文件兼容性警告虽然最终没出大问题但这种不可控因素能避免就避免。2.2 关键配置参数逐项解析以下是六个节点都要用到的核心配置。我会把每个参数的作用和为什么这么配讲清楚。port 6379 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes appendfsync everysec protected-mode no requirepass yourpassword masterauth yourpassword逐项解释port 6379Redis实例监听的数据端口。集群模式下每个节点需要额外占用一个端口作为集群总线端口默认是数据端口加10000即16379。这个端口用于节点间的Gossip通信、配置传播、故障检测等必须保证节点间能互相访问。cluster-enabled yes这是开启集群模式的开关。配置为yes后Redis实例会以集群节点身份启动不再是一个普通的单机实例。cluster-config-file nodes.conf集群元数据文件。这个文件由Redis自动生成和维护记录了集群节点列表、哈希槽分配情况、当前配置纪元等信息。注意这个文件的存放路径容器里要留出可写空间。cluster-node-timeout 5000节点超时时间单位毫秒。指一个节点与另一个节点失去联系多久后判定对方疑似故障。这个值影响故障转移的响应速度。5秒是默认值对多数场景够用。如果希望故障转移更快可以调到2000但过低会增加误判风险网络抖动时可能引发不必要的从节点晋升。appendonly yes、appendfsync everysec开启AOF持久化每秒刷盘一次。集群不意味着可以不做持久化只有主节点内存中的数据还不够因为从节点晋升时需要有最新的数据副本。AOF和RDB可以同时开启生产环境甚至建议两者都开。protected-mode no关闭保护模式。这一步需要特别谨慎。默认情况下Redis只允许本机回环地址访问这显然不符合我们多节点通信的需求。但关闭保护模式意味着任何人都能访问你的6379端口所以必须同时设置requirepass密码。请务必设置密码不要图省事留空。requirepass和masterauth分别是客户端访问密码和主从同步认证密码。在集群模式下主从节点之间会进行数据复制从节点必须以masterauth里设置的密码去连接主节点否则复制链路建立不起来。这两个密码必须一致否则会出现主节点有密码、从节点没密码的死锁问题。2.3 网络配置与固定IP规划Docker网络模式下需要提前规划好子网和IP。假定我们创建一个名为redis-net的自定义网络子网为172.28.0.0/24网关172.28.0.1。六个容器的IP分配建议如下容器名称数据端口集群总线端口固定IPredis-1637916379172.28.0.11redis-2637916379172.28.0.12redis-3637916379172.28.0.13redis-4637916379172.28.0.14redis-5637916379172.28.0.15redis-6637916379172.28.0.16这里要强调一个容易踩坑的点为什么所有数据端口都是6379不冲突在bridge网络模式中每个容器拥有自己独立的网络命名空间所以它们内部的6379端口互不冲突Docker负责把宿主机的端口映射到容器内的端口。如果你的宿主机需要从外部访问这些Redis实例就要用-p 7001:6379这样的方式把宿主机的7001端口映射到容器的6379端口。但集群节点间通信时使用的是容器IP和内部端口所以映射不映射、映射到哪个宿主端口都不影响集群内部的通信。固定IP的核心意义在于nodes.conf文件。当第一个节点启动时它会把自己的IP:端口信息写入一个临时的nodes.conf文件。在集群创建完成后所有节点的IP、槽位、主从关系都会固化在各自的nodes.conf中。如果容器IP是动态的重启后IP变了其他节点记录的还是旧IP就会导致集群脑裂般的假象——节点明明活着集群却说不可达。使用固定IP相当于给每个节点办了张永不更换的身份证。3. 实操过程与集群创建3.1 目录结构与配置文件准备我的习惯是为每个集群独立创建目录防止多个集群的nodes.conf文件相互干扰。目录结构如下/data/redis-cluster/ ├── redis-1/ │ ├── redis.conf │ └── data/ ├── redis-2/ │ ├── redis.conf │ └── data/ ├── redis-3/ │ ├── redis.conf │ └── data/ ├── redis-4/ │ ├── redis.conf │ └── data/ ├── redis-5/ │ ├── redis.conf │ └── data/ └── redis-6/ ├── redis.conf └── data/data目录用于挂载Redis的持久化数据包括AOF文件和nodes.conf。这个设计保证了容器销毁后数据仍在宿主机上重新启动容器可以恢复到之前的状态。六个节点的配置文件内容几乎一样唯一的不同可以不加——因为IP是由容器启动时通过环境变量或命令行参数指定的Redis配置里不需要区分。但如果你希望每个节点配置独立也可以把cluster-config-file nodes.conf改成nodes-redis-1.conf这样的名称便于容器外直接查看哪个文件对应哪个节点。我自己为了排查方便会用带编号的配置文件。生成配置文件时我常用的技巧是用for循环批量生成for i in $(seq 1 6); do mkdir -p /data/redis-cluster/redis-$i/data cat /data/redis-cluster/redis-$i/redis.conf EOF port 6379 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes appendfsync everysec protected-mode no requirepass yourpassword masterauth yourpassword bind 0.0.0.0 EOF done重点讲解bind 0.0.0.0这个配置。Redis默认只绑定127.0.0.1即使关闭了保护模式如果绑定地址不对外部节点依然无法访问。设置为0.0.0.0表示监听所有网络接口这样才能接受来自docker网络内其他容器的连接请求。这一点被坑过的人不在少数因为单机模式不绑内网IP根本不影响本地测试集群模式直接就不通了。3.2 启动六个容器确认目录和配置就绪后先创建自定义网络docker network create --subnet172.28.0.0/24 redis-net然后逐个启动容器。由于六个容器的启动命令只有IP和目录不同我建议不要手敲六遍直接用循环for i in $(seq 1 6); do docker run -d \ --name redis-$i \ --network redis-net \ --ip 172.28.0.$((i10)) \ -p 700$i:6379 \ -v /data/redis-cluster/redis-$i/data:/data \ -v /data/redis-cluster/redis-$i/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7.2 \ redis-server /usr/local/etc/redis/redis.conf done这里做一个参数拆解-p 700$i:6379宿主机端口映射。redis-1映射7001redis-2映射7002以此类推。这样从宿主机的外部工具比如AnotherRedisDesktopManager可以分别连到7001到7006访问六个节点。注意宿主机端口映射只影响外部访问不影响集群内部节点间的通信。-v .../data:/data把容器的/data目录Redis默认工作目录挂载到宿主机。持久化文件就写在这里。-v .../redis.conf:/usr/local/etc/redis/redis.conf把配置文件挂载进去通过启动命令指定加载。很多教程在这个环节会省掉数据目录挂载只挂配置文件。我强烈不建议这么做。Redis Cluster运行过程中会持续更新nodes.conf一旦容器被删除集群元数据也一起丢了再次启动时节点会认为自己是新节点整个集群的槽位分配信息和主从关系需要重新初始化。挂载数据目录是防止集群元数据丢失最有效的手段。启动完成后用docker ps检查六个容器是否都处于Up状态。如果某个容器启动后又退出了用docker logs redis-x查看日志多半是配置文件路径写错或者数据目录权限问题。3.3 使用redis-cli创建集群容器起来之后随便进入一个节点用redis-cli的集群创建命令初始化集群。docker exec -it redis-1 redis-cli -a yourpassword --cluster create \ 172.28.0.11:6379 172.28.0.12:6379 172.28.0.13:6379 \ 172.28.0.14:6379 172.28.0.15:6379 172.28.0.16:6379 \ --cluster-replicas 1命令中--cluster-replicas 1表示每个主节点配备1个从节点。Redis会自动把前三个IP设为主节点后三个IP设为对应的从节点。如果你想手动指定主从关系可以在创建成功后用cluster replicate命令进行调整但初始创建时用这种方式最省事。执行后redis-cli会输出一份哈希槽分配方案大致如下 Performing hash slots allocation on 6 nodes... Master[0] - Slots 0 - 5460 Master[1] - Slots 5461 - 10922 Master[2] - Slots 10923 - 16383 Adding replica 172.28.0.14:6379 to 172.28.0.11:6379 Adding replica 172.28.0.15:6379 to 172.28.0.12:6379 Adding replica 172.28.0.16:6379 to 172.28.0.13:6379这是一份需要人工确认的方案输入yes后集群开始初始化。过程包括槽位分配、节点间握手、为从节点设置复制关系等步骤通常几秒内完成。如果没有任何报错最后一行会显示[OK] All 16384 slots covered说明16384个哈希槽全部被覆盖集群创建成功。这里我加一句实操经验创建命令里最好使用节点的真实IP而不是容器名。虽然redis-cli在Docker网络内也能解析容器名但解析后写进nodes.conf的是容器名而其他容器拿到这个名字后的解析行为取决于DNS解析顺序有一定的不确定性。直接用IP路径最短、问题最少。3.4 验证集群状态集群创建完成后必须做一轮完整的验证确认集群真的可用。进入任意节点执行docker exec -it redis-1 redis-cli -a yourpassword cluster info输出里重点看这几个指标cluster_state:ok集群状态正常。cluster_slots_assigned:16384所有槽位已分配。cluster_known_nodes:6集群感知到6个节点。cluster_size:3有3个主节点。再看节点角色和主从关系docker exec -it redis-1 redis-cli -a yourpassword cluster nodes输出示例172.28.0.11:637916379 myself,master - 0 0 1 connected 0-5460 172.28.0.12:637916379 master - 0 0 2 connected 5461-10922 172.28.0.13:637916379 master - 0 0 3 connected 10923-16383 172.28.0.14:637916379 slave 172.28.0.11:637916379 0 0 4 connected 172.28.0.15:637916379 slave 172.28.0.12:637916379 0 0 5 connected 172.28.0.16:637916379 slave 172.28.0.13:637916379 0 0 6 connected这里有两点需要解释。第一16379是集群总线端口的表示节点间通信走这个端口它必须和数据端口一样在网络内可达否则节点间无法交互。第二从节点的输出里没有显示槽位范围因为在正常情况下从节点不服务任何读取请求除非设置readonly模式它们的作用是完整复制主节点的数据等待晋升。最后做一次读写验证docker exec -it redis-1 redis-cli -c -a yourpassword set foo bar-c参数表示以集群模式连接客户端会自动处理密钥的哈希槽重定向。如果返回OK再执行docker exec -it redis-1 redis-cli -c -a yourpassword get foo如果输出bar说明整个集群的读写链路已经打通。注意用-c模式写入时即使foo这个键被重定向到另外的节点客户端也会自动跟随MOVED重定向指令去目标节点执行不需要手动切换。3.5 故障转移演练集群的可高可用性需要实际演练验证不能等到故障发生了再临场反应。我们做一个简单但关键的故障转移测试。先找出一个主节点比如172.28.0.11假设它对应容器redis-1。手动停止这个容器docker stop redis-1等待几秒钟cluster-node-timeout设定的5秒到期后集群会开始故障转移流程。此时进入另一个节点查看集群状态docker exec -it redis-2 redis-cli -a yourpassword cluster nodes正常情况下172.28.0.14会从slave角色变为master并接管原来属于172.28.0.11的槽位。这个过程中你可能会看到cluster_state:fail的短暂状态——这是正常现象故障转移尚未完成时集群处于不可用状态。等新的主节点完成槽位接管后集群状态自动恢复为ok。这个演练的意义在于确认你的集群在面对真实宕机时能自动恢复。而且从这次切换中你可以直观感受到cluster-node-timeout参数对恢复时间的影响5000毫秒意味着至少5秒的不可用窗口如果你对高可用要求更严格需要调低这个参数。故障转移演练完成后重新启动redis-1容器它会以从节点身份重新加入集群从当前主节点同步数据。这是Redis Cluster设计好的行为原主节点恢复后不会抢回主角色而是乖乖当从节点避免脑裂和频繁的主从切换。4. 常见问题与排查技巧实录4.1 容器启动失败与配置排查我在实际搭建过程中遇到过不少问题把最常见的几类整理出来按出现频率排序。第一类是容器启动后立即退出。通过docker logs查看日志最常见的错误是# Fatal error, cant open config file /usr/local/etc/redis/redis.conf原因是挂载路径写错或配置文件不存在。注意-v挂载的宿主机路径必须是绝对路径如果用相对路径Docker会创建一个目录而不是挂载文件导致Redis读取不到配置。另一个常见原因是配置文件权限问题容器内Redis进程以redis用户运行宿主机配置文件权限过严会导致读取失败。第二类是cluster-enabled配置未生效。如果不是通过命令行加载配置文件而是直接启动redis-server不带参数Redis会使用默认配置集群模式不会开启。我见过有人把配置文件放进了容器但启动命令还是用的redis-server不带配置文件路径结果集群创建命令直接报Node ... is not empty、ERR This instance has cluster support disabled之类的错误。确保你的容器启动命令是redis-server /usr/local/etc/redis/redis.conf而不是裸的redis-server。第三类是节点间通信失败。表现是集群创建命令卡在Waiting for the cluster to join然后报[ERR] Sorry, cant connect to node。主要排查点有两个。第一检查容器是否在同一个Docker网络上跨网络的IP无法互通第二检查集群总线端口16379是否可访问Redis节点间不仅需要数据端口通信还需要总线端口传Gossip消息。如果你在防火墙只放行了6379集群一样起不来。4.2 槽位分配异常处理有时候集群创建后会出现cluster_state:fail、cluster_slots_assigned小于16384的情况。这通常是因为某个节点上的nodes.conf残留了旧的集群信息。一个典型的场景你之前创建过一个集群后来没有清理干净数据目录再次启动容器时旧节点的nodes.conf里保存了已废弃的集群ID。把这些节点强行加入新集群时Redis检测到节点已经属于其他集群直接拒绝握手。处理方法是清空数据目录中的nodes.conf和相关持久化文件让节点以全新身份启动rm -rf /data/redis-cluster/redis-*/data/*然后重新启动容器、重新创建集群。注意这个操作会清空所有数据只适合用于测试环境或者数据可丢弃的集群。如果是有数据的集群需要通过官方迁移工具先备份数据。槽位未完全覆盖的另一种情况是创建集群时某个节点不可达。比如你写了172.28.0.16但redis-6容器其实分配的是其他IP。这种故障最好定位在宿主机上用docker inspect redis-6 | grep IPAddress查看容器真实IP再修正创建命令即可。4.3 容器重启后集群失效问题这是所有Docker化Redis Cluster里被问得最多的问题。现象容器重启前集群一切正常重启某个或全部容器后发现集群状态异常节点之间互相不认识槽位也丢了。根本原因容器重启后IP地址变化或者nodes.conf文件没有持久化。前面说了我们用固定IP就是为了避免IP变化问题但如果你用的是默认bridge网络的自动IP分配重启后容器极有可能拿到不同的IP。此时就算nodes.conf完整保留里面的IP记录也已经失效。解决方式有三条路创建自定义网络并用--ip指定固定IP这是最推荐的做法。使用--network host模式让容器直接使用宿主机网络IP天然固定但牺牲了端口独立性和外部访问灵活性。如果你用docker-compose管理也可以给每个服务配置IP。每次重启后重新执行集群创建命令但这是最不可取的下策因为数据信息会被覆盖无法恢复原集群身份。另外还需要确认数据目录挂载一直在。如果容器是用docker run手动创建的重启时需要显式加-v挂载参数。用docker-compose就方便很多配置写清楚后反复启动都不会丢。4.4 密码配置错误引发的复制失败现象集群能创建但主节点日志不断刷MASTER - REPLICA sync started、Master replied PING to replica之类的信息数据复制始终没有完成。原因requirepass和masterauth不一致。在Redis Cluster中从节点连接主节点进行全量同步时必须带着auth信息。如果masterauth为空或密码与主节点的requirepass不同从节点的SYNC请求会被主节点拒绝复制链路建立不起来。处理方法检查每个节点配置文件里的两个密码是否一致修改后重启容器。这个错误很隐蔽因为故障转移测试时新的主从关系建立也可能因为同样原因失败。建议在创建集群前先逐一验证每个节点能否用密码登录确认无误再执行--cluster create。4.5 问题速查表症状可能原因解决方式容器启动即退出配置文件路径错误或权限不足查看docker logs修正挂载路径或权限集群创建时节点不可达容器不在同一网络、IP写错检查docker network和docker inspect IPWaiting for cluster to join超时总线端口被防火墙拦截放行16379端口确认容器网络连通集群创建报Node is not empty数据目录有残留nodes.conf清空data目录后重新创建主从同步无法完成requirepass与masterauth不一致统一两个密码重启容器节点重启后集群失效IP变化或数据未持久化改用固定IP挂载数据目录客户端连接通过集群命令时报CLUSTERDOWN槽位未完全覆盖执行cluster info确认分配情况必要时重建集群4.6 我踩过的其他坑最后说两个不太容易注意、但影响体验的小问题。第一redis-cli的-a参数会在命令行历史记录里留下密码。我在测试环境里无所谓但如果你在共享机器上操作建议改用REDISCLI_AUTH环境变量export REDISCLI_AUTHyourpassword这样执行redis-cli命令时就不需要每次带密码了也避免密码泄露到shell历史里。第二容器内的appendonly文件增长问题。开启AOF后长期运行的Redis会积累大量AOF历史数据磁盘占用会持续膨胀。生产环境中应该配置AOF重写策略auto-aof-rewrite-percentage和auto-aof-rewrite-min-size或者定期用redis-cli bgrewriteaof手动压缩。这个细节和集群本身无关但会影响容器的生命周期管理。还有一个小经验在docker-compose文件中定义集群时depends_on只能保证容器启动顺序不能保证Redis进程已就绪。如果你想在集群创建前确保所有节点都Ready可以用一个简单的shell循环等待6379端口可连接再进行集群初始化。这个等待逻辑在我自动化部署脚本里是标配能避免90%的创建集群时节点未就绪错误。5. 自动化部署方案扩展5.1 为什么需要自动化手工执行docker run命令适合学习原理和排查问题但如果要把这套集群部署到多台机器或者频繁重建环境手敲命令的效率太低了。我建议至少用docker-compose管理容器生命周期有条件的话写一个初始化脚本把集群创建也自动化。docker-compose最大的优势是把容器的网络、IP、挂载、端口映射全部声明式地写入配置文件团队协作时你只需要把yaml和conf文件交给对方docker-compose up一下就拉起整套集群。对比手工执行六次docker run可读性和可维护性完全不在一个量级。5.2 一条命令拉起整个集群以下是一个可以直接使用的docker-compose简化版本通过YAML锚点避免配置重复x-redis-common: redis-common image: redis:7.2 network: redis-net volumes: - ./redis.conf:/usr/local/etc/redis/redis.conf command: [redis-server, /usr/local/etc/redis/redis.conf] services: redis-1: : *redis-common container_name: redis-1 ipv4_address: 172.28.0.11 ports: - 7001:6379 redis-2: : *redis-common container_name: redis-2 ipv4_address: 172.28.0.12 ports: - 7002:6379 # ... redis-3 到 redis-6 同理 networks: redis-net: driver: bridge ipam: config: - subnet: 172.28.0.0/24在这个配置里每个服务只声明了自己的IP和宿主机端口映射其余公共配置通过YAML锚点共享。如果某个节点需要单独调整参数比如集群超时时间不同可以在该服务下覆盖配置。集群初始化这一步也建议写进脚本。比如用一个init-cluster.sh脚本等所有容器Ready后执行redis-cli的创建命令。脚本里可以加一个简单的就绪检测for i in $(seq 1 6); do until docker exec redis-$i redis-cli -a yourpassword ping | grep -q PONG; do sleep 1 done echo redis-$i is ready done等六个节点全部PONG再执行--cluster create。这样整套集群从零到可用只需要一条docker-compose up加一条bash init-cluster.sh中间的等待和重试全部自动化。5.3 水平扩容思路集群搭好只是开始后续业务增长后很可能需要扩容。Redis Cluster的扩容流程是启动新节点 - 加入集群 - 迁移部分哈希槽到新节点。在Docker环境中新节点同样通过docker run启动固定IP并挂载数据目录然后用redis-cli -a yourpassword --cluster add-node 172.28.0.17:6379 172.28.0.11:6379把新节点加入现有集群。此时新节点是个没有任何槽位的空节点。再把一部分槽从现有主节点迁移到新节点上redis-cli -a yourpassword --cluster reshard 172.28.0.11:6379交互式工具会问迁移多少槽、由哪个节点接收、从哪些源节点迁移。实际操作时要注意一次性迁移的槽位数不宜过大否则会长时间阻塞数据迁移过程中涉及的key访问。我通常每次迁移500个槽左右分批完成把对业务的影响降到最低。扩容过程中我两次踩过同一个坑新节点加入集群后cluster nodes能看到它但它始终没有槽位业务流量也没有被分担。后来发现问题在于我忘了执行reshardadd-node只是让节点加入集群不会自动分配槽位。文档没说错是我自己跳步了。这里写出来提醒一下看文章的你。5.4 安全加固与日常维护集群搭好之后如果部署在云服务器且需要外部访问安全加固是不能跳过的一步。首先protected-mode no的情况下任何人都可以尝试连接你的节点。requirepass虽然能挡住数据访问请求但Redis自身的一些高危命令比如FLUSHALL、KEYS、CONFIG仍然可以被密码用户执行。建议通过ACL为普通业务账号配置最小权限docker exec -it redis-1 redis-cli -a yourpassword \ acl setuser appuser on apppassword ~* read write -dangerous这样业务账号只能进行读写操作不能执行管理命令。管理员账号可以单独保留全部权限。其次如果节点在云环境暴露了公网IP的6379和16379端口建议在安全组或防火墙层面严格限制来源IP只允许应用服务器所在网段访问。Redis不是设计用来对抗公网攻击的软件暴露公共网络端口等于把数据裸奔。日常维护方面我养成了这些习惯每天执行一次redis-cli cluster info确认cluster_state是ok。每周抽查一次cluster nodes确认主从关系没有被异常切换。关注容器日志中的PING超时和SLOWLOG条目这些常常是性能问题或网络故障的先兆。磁盘空间监控不可少AOF文件的持续增长可能撑爆数据目录。做这些巡检不需要专门建监控系统几条命令加上crontab定时执行就能覆盖大部分风险。等到业务量大了再引入专业的Redis监控组件也不迟。结束语到这里一套完整的Docker版Redis Cluster已经真实运行在你面前了从网络规划、配置设计、容器启动、集群创建到故障转移演练、常见问题排查和自动化扩展。踩过那些坑之后我最大的体会是Redis Cluster本身并不可怕难点其实集中在网络层面和管理习惯上——IP怎么固定、nodes.conf怎么持久化、密码怎么统一这三件事解决了集群就像一个普通应用一样好维护。最后再分享一个小技巧容器版Redis Cluster和裸机版最大的不同在于一切配置都是代码化的你的docker-compose文件和redis.conf就是你完整的环境说明书。团队里来了新人把这两个文件发过去不用写文档他自己就能拉起一套一模一样的集群。与其背着Docker部署集群很难的印象不如亲手搭一次你会发现它比你想象的简单得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑