恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
三台虚拟机搭建Redis三主三从集群实战指南
首页
资讯中心
/
三台虚拟机搭建Redis三主三从集群实战指南
三台虚拟机搭建Redis三主三从集群实战指南
发布时间:2026/10/12 15:59:57
1. 为什么要在三台虚拟机上折腾Redis集群先把结论摆在这儿如果你手头只有三台物理机或者三台虚拟机想搭一套能扛住单点故障、读写分离、还能横向扩展的Redis环境那三主三从的集群方案基本就是最优解。它不需要你额外搞一堆机器三台机器每台跑两个Redis实例一个主一个从交叉配对总共六个节点形成一个完整的集群拓扑。这个方案解决的核心问题有三个。第一是单点故障单机Redis挂了业务直接雪崩集群模式下某个主节点挂了它的从节点会自动顶上来业务几乎无感知。第二是容量瓶颈单机内存再大也有上限集群通过分片把数据分散到多个主节点上理论上可以无限横向扩展。第三是读写压力主节点负责写从节点分担读读多写少的场景下吞吐量能翻好几倍。适合谁来参考这篇内容我总结了三类人。第一类是后端开发或者运维工程师公司业务量上来了单机Redis已经撑不住需要一套能落地的集群方案。第二类是正在准备面试或者想深入理解Redis分布式原理的同学光看理论不如自己动手搭一遍踩过坑之后理解会深刻得多。第三类是个人项目或者小团队的技术负责人预算有限只有几台虚拟机想用最低成本搭一套靠谱的缓存层。我自己第一次搭这套环境的时候前前后后折腾了差不多两天踩了不少坑比如集群节点握手失败、槽位分配不均、从节点一直同步不上等等。后面又反复搭了几次把流程和坑点都摸透了现在基本上半小时以内能搞定一套可用的环境。下面我把整个搭建过程拆开揉碎讲清楚包括每一步为什么要这么做、参数怎么算、遇到问题怎么排查。注意本文所有操作基于三台虚拟机操作系统以常见的Linux发行版为例Redis版本选择6.x稳定版。如果你用的是其他版本部分配置项名称可能有差异但核心逻辑一致。2. 搭建前的整体设计与关键决策2.1 三主三从的拓扑结构到底怎么摆很多人一上来就急着装Redis结果节点规划没做好后面槽位分配乱七八糟。我建议先把拓扑想清楚再动手。三台虚拟机假设IP分别是192.168.1.101、192.168.1.102、192.168.1.103。每台机器上跑两个Redis实例端口分别用7001和7002。这样六个节点的分布是这样的虚拟机IP实例端口角色配对关系192.168.1.1017001主节点从节点在102:7002192.168.1.1017002从节点主节点在103:7001192.168.1.1027001主节点从节点在103:7002192.168.1.1027002从节点主节点在101:7001192.168.1.1037001主节点从节点在101:7002192.168.1.1037002从节点主节点在102:7001这个交叉配对的逻辑很关键。你看每台机器上都有一个主节点和一个从节点而且从节点的主节点在另一台机器上。这样即使某一台虚拟机整个挂了它上面的主节点和从节点同时下线但集群里其他两台机器上的主从关系依然完整不会出现主从全丢的情况。如果你把同一台机器的两个实例配成主从关系那这台机器一挂这一对主从就全没了集群的容错能力直接打对折。这是很多人容易犯的错误一定要避开。2.2 为什么选三主三从而不是其他方案Redis集群方案其实有好几种选择我简单对比一下你就知道为什么三主三从是性价比最高的。方案一单机主从哨兵。一主两从加三个哨兵能解决高可用问题但解决不了容量瓶颈所有数据还是在一台机器上。而且哨兵模式下扩容很麻烦不适合数据量持续增长的场景。方案二Cluster模式三主三从。数据分片存储每个主节点负责一部分槽位从节点负责故障转移和读扩展。三台机器就能跑起来资源利用率高扩展性也好。缺点是运维复杂度比主从高一些但对于有经验的工程师来说完全可控。方案三Cluster模式六主零从。性能最强但没有从节点意味着没有故障转移能力任何一个主节点挂了它负责的槽位就不可用了除非你手动恢复。生产环境不建议这么干。所以三主三从是在资源成本、可用性、扩展性三者之间最平衡的选择。三台虚拟机就能搭每台机器跑两个实例资源占用可控同时具备自动故障转移能力。2.3 虚拟机资源怎么分配才合理Redis本身是内存数据库对CPU要求不高但对内存和网络延迟比较敏感。我建议每台虚拟机的配置至少是2核CPU、4GB内存、20GB磁盘。这样每个Redis实例大概能分到1.5GB左右的内存对于测试和小型生产环境够用了。内存分配有个计算公式可以参考单个实例最大内存 (虚拟机总内存 - 系统占用) / 实例数量。比如4GB内存的机器系统占用大概500MB剩下3.5GB分给两个实例每个实例可以设maxmemory为1.5GB留500MB做缓冲。磁盘方面Redis的RDB和AOF文件会占用空间20GB足够跑一段时间了。如果数据量特别大可以适当增加磁盘容量或者配置RDB压缩和AOF重写策略来控制文件大小。网络方面三台虚拟机最好在同一个局域网内网络延迟控制在1ms以内。如果跨机房部署延迟超过10ms集群的 gossip 协议通信会变慢故障转移时间会明显拉长。提示虚拟机网络模式建议用桥接或者NAT确保三台机器之间能互相ping通而且端口7001、7002、17001、17002都要开放。Cluster模式下节点之间需要额外的集群总线端口默认是服务端口加10000。3. 核心细节解析与实操要点3.1 Redis安装与基础配置的坑点安装Redis本身不难但有几个细节不注意后面集群搭建会出问题。第一步下载和编译。我习惯用源码编译安装这样版本可控配置也灵活。命令大概是这样wget https://download.redis.io/releases/redis-6.2.14.tar.gz tar -zxvf redis-6.2.14.tar.gz cd redis-6.2.14 make make install PREFIX/usr/local/redis编译过程中如果报错大概率是缺少gcc或者make工具先装一下依赖就行。编译完成后可执行文件会放在/usr/local/redis/bin目录下。第二步创建配置目录和数据目录。我建议每个实例单独一个目录方便管理mkdir -p /data/redis/7001/{conf,data,logs} mkdir -p /data/redis/7002/{conf,data,logs}这样每个实例的配置文件、数据文件、日志文件都分开存放后面排查问题的时候一目了然。第三步编写配置文件。这是最关键的一步集群相关的配置项一个都不能少。我以7001端口的实例为例配置文件大概长这样port 7001 bind 0.0.0.0 daemonize yes pidfile /data/redis/7001/redis.pid logfile /data/redis/7001/logs/redis.log dir /data/redis/7001/data cluster-enabled yes cluster-config-file nodes-7001.conf cluster-node-timeout 15000 appendonly yes appendfilename appendonly.aof maxmemory 1536mb maxmemory-policy allkeys-lru protected-mode no这里有几个配置项需要重点解释。cluster-enabled yes是开启集群模式不设这个后面没法组集群。cluster-config-file是集群节点信息文件Redis会自动维护不要手动改。cluster-node-timeout是节点超时时间单位毫秒设成15000表示15秒没响应就认为节点挂了这个值可以根据网络质量调整网络差就设大一点。maxmemory-policy我设的是allkeys-lru意思是内存满了之后淘汰最近最少使用的key。如果你的业务数据不能丢那就设成noeviction但这样写入会报错需要提前做好容量规划。注意protected-mode一定要设成no否则集群节点之间通信会被拒绝。这个配置项在单机模式下是安全保护但在集群模式下必须关闭。3.2 集群总线端口的计算与开放Cluster模式下每个节点除了服务端口还需要一个集群总线端口用于节点之间的gossip通信。这个端口默认是服务端口加10000。比如7001端口的实例集群总线端口就是17001。这个端口必须开放否则节点之间无法握手集群永远建不起来。我见过有人只开了7001和7002结果cluster create一直卡在Waiting for the cluster to join这一步排查半天才发现是总线端口没开。开放端口的命令取决于你的系统防火墙。如果是firewalldfirewall-cmd --permanent --add-port7001/tcp firewall-cmd --permanent --add-port7002/tcp firewall-cmd --permanent --add-port17001/tcp firewall-cmd --permanent --add-port17002/tcp firewall-cmd --reload如果是iptables就用iptables的命令添加规则。三台机器都要做同样的操作。3.3 节点握手与槽位分配的原理集群搭建的核心是两步节点握手和槽位分配。节点握手就是让六个节点互相认识。Redis提供了redis-cli --cluster create命令一条命令就能完成握手和槽位分配。但如果你想知道背后发生了什么我简单说一下原理。每个节点启动后会根据自己的cluster-config-file生成一个节点ID。当你执行cluster create时命令行工具会依次连接每个节点发送CLUSTER MEET命令让节点之间建立连接。握手成功后所有节点会形成一个完整的网状网络每个节点都知道其他所有节点的信息。槽位分配是把16384个槽位平均分给三个主节点。16384除以3等于5461.33不能整除所以实际分配是5461、5461、5462。这个分配是自动的你不需要手动算但知道这个数字有助于理解为什么集群最少需要三个主节点。为什么是16384个槽位而不是更多这是Redis作者根据网络带宽和心跳包大小做的权衡。槽位越多心跳包越大网络开销越高。16384在保证分片粒度的同时把心跳包控制在合理范围内。提示如果你想让某个主节点多承担一些槽位可以在cluster create之后用CLUSTER ADDSLOTS和CLUSTER DELSLOTS命令手动调整。但生产环境不建议频繁调整容易导致数据迁移和性能波动。4. 实操过程与核心环节实现4.1 三台虚拟机的环境准备与Redis部署先把三台虚拟机的基础环境搞定。我假设你已经装好了Linux系统并且配置好了静态IP。三台机器的IP分别是192.168.1.101、192.168.1.102、192.168.1.103。第一步在三台机器上分别执行系统更新和依赖安装yum update -y yum install -y gcc make wget第二步下载Redis源码并编译安装。三台机器都要做cd /opt wget https://download.redis.io/releases/redis-6.2.14.tar.gz tar -zxvf redis-6.2.14.tar.gz cd redis-6.2.14 make make install PREFIX/usr/local/redis编译完成后把Redis的可执行文件路径加到环境变量里方便后面直接用redis-cli命令echo export PATH$PATH:/usr/local/redis/bin /etc/profile source /etc/profile第三步创建目录结构。每台机器上都要创建7001和7002两个实例的目录mkdir -p /data/redis/7001/{conf,data,logs} mkdir -p /data/redis/7002/{conf,data,logs}第四步复制配置文件模板并修改。Redis源码目录里有个redis.conf模板复制过来改一改就行cp /opt/redis-6.2.14/redis.conf /data/redis/7001/conf/redis.conf cp /opt/redis-6.2.14/redis.conf /data/redis/7002/conf/redis.conf然后按照前面讲的配置项分别修改两个配置文件。注意端口号、目录路径、集群配置文件名称都要对应改好。4.2 六个Redis实例的启动与验证配置文件改好之后就可以启动实例了。三台机器上分别执行/usr/local/redis/bin/redis-server /data/redis/7001/conf/redis.conf /usr/local/redis/bin/redis-server /data/redis/7002/conf/redis.conf启动完成后用ps命令检查一下进程是否都在ps -ef | grep redis-server正常情况下每台机器应该看到两个redis-server进程。如果少了去日志文件里看报错信息。常见的问题包括配置文件路径写错、端口被占用、权限不足等。接下来验证每个实例是否能正常响应redis-cli -p 7001 ping redis-cli -p 7002 ping如果返回PONG说明实例启动成功。如果返回Could not connect检查一下bind配置和防火墙设置。注意这时候集群还没建起来每个实例都是独立的cluster-enabled虽然开了但节点之间还不认识。你可以用CLUSTER INFO命令看一下集群状态应该是cluster_state:fail。4.3 一条命令组建三主三从集群六个实例都启动成功后就可以组建集群了。Redis 6.x提供了redis-cli --cluster create命令一条命令搞定redis-cli --cluster create \ 192.168.1.101:7001 192.168.1.101:7002 \ 192.168.1.102:7001 192.168.1.102:7002 \ 192.168.1.103:7001 192.168.1.103:7002 \ --cluster-replicas 1这里--cluster-replicas 1的意思是每个主节点配一个从节点。命令执行后Redis会自动完成以下工作节点握手、主从关系分配、槽位分配。执行过程中会有一个确认提示问你是否接受这个配置输入yes回车就行。然后你会看到类似这样的输出 Performing hash slots allocation on 6 nodes... Master[0] - Slots 0 - 5460 Master[1] - Slots 5461 - 10922 Master[2] - Slots 10923 - 16383 Adding replica 192.168.1.102:7002 to 192.168.1.101:7001 Adding replica 192.168.1.103:7002 to 192.168.1.102:7001 Adding replica 192.168.1.101:7002 to 192.168.1.103:7001 Nodes configuration updated Assign a different config epoch to each node Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join... Performing Cluster Check (using node 192.168.1.101:7001) [OK] All nodes agree about slots configuration. Check for open slots... Check slots coverage... [OK] All 16384 slots covered.看到最后那个All 16384 slots covered就说明集群建好了。如果卡在Waiting for the cluster to join不动大概率是集群总线端口没开或者节点之间网络不通。4.4 集群状态检查与读写测试集群建好之后第一件事是检查状态redis-cli -p 7001 cluster info重点关注cluster_state这一行应该是ok。如果还是fail说明有槽位没分配或者节点握手有问题。然后看一下节点列表redis-cli -p 7001 cluster nodes输出会列出所有六个节点的信息包括节点ID、IP端口、角色、负责的槽位范围、主从关系等。你可以对照前面的拓扑表确认主从配对是否正确。接下来做读写测试。注意集群模式下redis-cli需要加-c参数才能自动重定向到正确的节点redis-cli -c -p 7001进入交互界面后设置一个keyset name redis-cluster-test如果key不在当前节点负责的槽位你会看到重定向提示然后自动跳到正确的节点执行。这就是集群模式的正常工作方式。再获取一下get name能取到值就说明读写都正常了。4.5 故障转移测试与验证集群搭好了不测试故障转移等于白搭。我一般会做两个测试主节点宕机和从节点宕机。测试一主节点宕机。手动kill掉101:7001这个主节点redis-cli -p 7001 shutdown nosave然后观察集群状态。等待cluster-node-timeout我们设的是15秒之后它的从节点102:7002应该会自动升级为主节点。用cluster nodes命令查看可以看到102:7002的角色变成了master而且接管了原来101:7001负责的槽位。测试二从节点宕机。kill掉一个从节点比如103:7002redis-cli -p 7002 shutdown nosave这个操作对集群读写没有影响因为从节点只负责读扩展和故障转移。集群状态依然是ok只是少了一个从节点。测试完成后把kill掉的节点重新启动它们会自动重新加入集群。如果是主节点重启它会变成从节点因为它的槽位已经被原来的从节点接管了。这个行为是正常的Redis集群的故障转移是单向的不会自动切回来。提示生产环境做故障转移测试一定要在业务低峰期因为主节点切换的瞬间会有短暂的写入不可用。虽然时间很短通常几秒但对于高并发业务来说还是会有影响。5. 常见问题与排查技巧实录5.1 集群创建卡在Waiting for the cluster to join这是最常见的问题没有之一。我统计了一下十次搭建至少有五次会遇到。现象执行cluster create命令后一直卡在Waiting for the cluster to join...等多久都不动。原因节点之间的集群总线通信被阻断了。可能是防火墙没开总线端口也可能是bind配置不对还可能是节点之间网络本身就不通。排查步骤先确认三台机器之间能互相ping通。在101上ping 102和103反过来也ping一下。检查防火墙规则确认7001、7002、17001、17002四个端口都开放了。用telnet测试总线端口连通性telnet 192.168.1.102 17001如果连不上就是端口问题。检查redis.conf里的bind配置如果是127.0.0.1改成0.0.0.0或者具体的内网IP。检查protected-mode是否设成了no。解决方法根据排查结果对应处理。端口没开就开端口bind不对就改bindprotected-mode没关就关掉。改完配置后重启所有实例重新执行cluster create。5.2 槽位分配不均或者有槽位未分配现象cluster info显示cluster_state:failcluster nodes显示有槽位没有分配。原因可能是cluster create过程中断过导致部分槽位没有分配成功。也可能是手动调整槽位时操作失误。排查步骤用redis-cli --cluster check 192.168.1.101:7001检查槽位覆盖情况。看输出里有没有[ERR] Not all 16384 slots are covered by nodes这样的提示。如果有未分配的槽位记下槽位编号。解决方法用CLUSTER ADDSLOTS命令手动分配。比如槽位0到1000没分配就在对应的主节点上执行redis-cli -p 7001 cluster addslots {0..1000}如果槽位分配不均可以用redis-cli --cluster reshard命令重新分片。这个命令是交互式的会问你移动多少个槽位、目标节点是哪个、源节点是哪些。按照提示操作就行。注意reshard操作会触发数据迁移数据量大时耗时较长建议在业务低峰期执行。5.3 从节点一直同步不上主节点现象cluster nodes显示从节点的link状态是disconnected或者master_link_status是down。原因可能是主从之间的网络问题也可能是主节点设置了requirepass而从节点没配masterauth还可能是主节点的maxmemory满了导致同步失败。排查步骤在从节点上执行redis-cli -p 7002 info replication看master_link_status和master_last_io_seconds_ago。如果master_link_status是down检查主节点的日志看有没有报错。检查主从节点的密码配置是否一致。检查主节点的内存使用情况如果接近maxmemory同步可能会失败。解决方法网络问题就修网络密码问题就统一密码配置内存问题就扩容或者调整淘汰策略。如果是全量同步失败可以尝试在从节点上执行CLUSTER RESET然后重新加入集群。5.4 集群节点无法自动发现新节点现象手动添加了一个新节点但其他节点不认识它。原因新节点的集群总线端口没开或者cluster-enabled没设成yes。排查步骤确认新节点的cluster-enabled配置是yes。确认新节点的总线端口开放。用redis-cli --cluster add-node命令添加节点而不是手动改配置文件。解决方法用官方提供的add-node命令redis-cli --cluster add-node 192.168.1.104:7001 192.168.1.101:7001第一个参数是新节点地址第二个参数是集群中任意一个已有节点地址。添加成功后再用reshard命令分配槽位。5.5 常见问题速查表问题现象可能原因排查命令解决方法卡在Waiting for cluster join总线端口未开telnet IP 17001开放17001/17002端口cluster_state:fail槽位未全覆盖cluster info手动addslots或reshard从节点同步失败密码不一致info replication统一masterauth配置节点无法发现cluster-enabled未开cluster info修改配置并重启写入报CLUSTERDOWN槽位分配异常cluster nodes检查槽位覆盖情况故障转移不触发超时时间太长cluster-node-timeout适当调小超时时间6. 生产环境部署的进阶建议6.1 内存与淘汰策略的实战配置测试环境随便玩玩无所谓但生产环境的内存配置必须认真对待。我踩过最大的坑就是maxmemory设得太大导致系统OOMRedis进程被系统kill掉。我的经验是maxmemory不要超过物理内存的70%。比如4GB内存的机器maxmemory最多设2.8GB。剩下的30%留给系统、RDB/AOF文件缓冲、客户端连接缓冲等。淘汰策略的选择取决于业务场景。如果你的缓存数据可以丢用allkeys-lru内存满了自动淘汰最久未使用的key。如果数据不能丢用noeviction但必须做好容量监控和告警一旦内存接近上限就要及时扩容。还有一个容易被忽略的配置是maxmemory-samples默认是5。这个值越大LRU淘汰越精确但CPU消耗也越高。生产环境建议设成10在精度和性能之间取个平衡。6.2 持久化方案的选择与优化Redis集群模式下每个节点都会独立做持久化。RDB和AOF各有优劣我一般建议主节点用RDB从节点用AOF。主节点用RDB的原因是RDB文件小、恢复快适合做备份和全量同步。从节点用AOF的原因是AOF记录每次写操作数据安全性更高故障转移时从节点升级为主节点AOF能保证数据尽量不丢。RDB的配置建议save 900 1 save 300 10 save 60 10000意思是900秒内至少1个key变化就触发快照300秒内至少10个key变化触发60秒内至少10000个key变化触发。这三个条件满足任意一个就会执行。AOF的配置建议appendonly yes appendfsync everysec no-appendfsync-on-rewrite yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mbappendfsync everysec表示每秒同步一次兼顾性能和安全。no-appendfsync-on-rewrite yes表示重写期间不阻塞同步避免性能抖动。6.3 监控与告警的关键指标集群搭好了不是终点持续监控才是。我总结了几个必须监控的指标集群状态cluster_state必须是ok一旦变成fail立即告警。节点数量正常应该是6个节点如果少于6个说明有节点下线了。槽位覆盖16384个槽位必须全部覆盖有未覆盖的槽位会导致部分key无法访问。内存使用率每个节点的used_memory和maxmemory的比值超过80%就要关注超过90%必须处理。主从延迟master_last_io_seconds_ago正常应该是0或1如果持续大于10说明主从同步有问题。慢查询slowlog里记录的执行时间超过阈值的命令定期分析优化。监控工具可以用Prometheus加redis_exporter或者用Redis自带的INFO命令定期采集。告警渠道根据团队习惯来邮件、短信、即时通讯工具都行。6.4 扩容与缩容的操作要点业务增长了三主三从不够用了怎么扩容标准流程是加节点、分配槽位、迁移数据。加节点用add-node命令分配槽位用reshard命令。reshard的时候要注意一次不要迁移太多槽位建议分批迁移每批1000到2000个槽位观察集群状态稳定后再继续。缩容反过来先把要下线的节点上的槽位迁移走然后用del-node命令删除节点。删除节点前一定要确认它的槽位已经全部迁移完毕否则会导致槽位丢失。提示扩容和缩容都会触发数据迁移对性能有影响。建议在业务低峰期操作并且提前做好数据备份。7. 我踩过的那些坑和最后的经验搭建Redis集群这件事看别人做觉得挺简单自己上手才知道坑有多少。我印象最深的一次是集群建好了读写也正常结果第二天早上发现cluster_state变成了fail。排查了半天发现是其中一台虚拟机的时钟漂移了导致节点之间的心跳超时判断出错。后来把所有机器都配了NTP时间同步这个问题再也没出现过。还有一次是从节点一直同步不上日志里报MASTER timeout查了半天网络没问题最后发现是主节点的maxmemory设得太小写入频繁触发淘汰导致同步缓冲区溢出。把maxmemory调大之后就好了。这些经验告诉我集群搭建不是把命令跑通就完事了细节决定稳定性。时间同步、内存配置、网络质量、监控告警每一个环节都不能马虎。最后分享一个小技巧搭建完成后用redis-cli --cluster check命令做一次全面体检它会检查槽位覆盖、节点连通性、主从关系等输出一份详细的报告。每次变更之后都跑一遍能提前发现很多潜在问题。这套三主三从的方案我从测试环境用到小型生产环境跑了大半年整体稳定性还是不错的。只要把前面说的那些配置项和注意事项都做到位基本上不会出大问题。后面如果业务继续增长可以在这个基础上继续加节点扩容架构不用大改平滑过渡就行。