开头
先说个背景:Memcached 作为老牌分布式缓存,单机读写性能确实没话说,但有个一直被人诟病的问题——它天生不负责节点间同步、也没有故障自动切换的机制。上一秒业务还能扛住峰值流量,下一秒某台缓存节点突然宕机,内存数据瞬间全部失效,后端数据库直接被打穿,轻则响应变慢,重则服务雪崩。当年我负责的某跨平台系统就栽过这个跟头,大促期间一台缓存机硬件报警,停机之后那段时间的 SQL 查询量直接翻了几十倍,数据库 CPU 持续飙红,整整熬到凌晨才缓过来。
那次事故之后,我认真整理了一套 Memcached 主主复制加 Keepalived 高可用的实验方案。方案核心是让两个缓存节点互为主从,数据双写双向复制,再由 Keepalived 对外提供一个漂移虚拟 IP,单节点故障时 VIP 自动切走,客户端依然走原地址读写,业务层基本无感知。这套东西不复杂,成本也不高,适合中小型架构直接落地。
这篇博文会把完整的实验过程拆开揉碎:从 repcached 补丁版本怎么选,到 Keepalived 的脑裂防护怎么做,再到故障验证时那些只看文档根本发现不了的细节,全部都告诉你。适合正在设计缓存高可用方案的运维开发人员,或者刚接触 Keepalived 想找完整实验参考的学习者,直接按文中的步骤手敲一遍,就能搭出一套可以用到生产环境参考的架构雏形。
1. 整体方案设计:为什么选主主复制 + Keepalived
1.1 Memcached 的天生短板
Memcached 的存储模型非常纯粹:所有数据只存在内存里,不落盘、不持久化、节点之间零通信。这种设计让它单机性能极其出色,但在分布式生产环境里就留下一个大洞——它没有任何自带的高可用机制。
常规做法是客户端多写几个节点做分布式缓存,但热点数据一旦集中在某个节点,这个节点挂了,损失的还是那部分缓存。想把故障隔离做得细,就得在应用层引入一致性哈希、故障转移逻辑,对业务代码有侵入,改造量不小。
与其反复改业务代码,不如在网络层面和节点间把问题解决掉。Memcached 主主复制的核心思路,是让两台机器上的 Memcached 实例互相把对方看成自己的副本:A 收到的写操作,同步一份给 B;B 收到的写操作,同步一份给 A。任意一台宕机,另一台还保有完整的数据。从业务视角看,缓存依然可用,数据也没有全局丢失。
1.2 为什么不是主从,而是主主
很多第一次接触这个方案的人会问:只做主从不行吗?主节点挂了,从节点顶上也能接受。
主从模式理论上可行,但它在 Memcached 这个场景下有个非常麻烦的问题:Memcached 本身维护从节点的能力为零,所以主从架构里,主节点要挂掉之后把身份切换给从节点,依赖的是外部脚本去修改连接关系,而且数据链路由单向复制变成双向同步时,需要把原本只读的从节点改成可写,这个切换的窗口期越长,缓存失效的风险就越高。
主主复制直接把双向同步一步到位:两台机器平时都能读、都能写,不存在“临时改方向”的过程。配合最高优先级的漂移 IP,故障发生的时候,流量切到备用机的路径更短,缓存命中率受影响更小。
需要注意一点,主主复制不等于数据绝对一致。Memcached 的复制基于异步机制,A 机写入后,数据会短暂延迟到达 B 机,这个窗口通常是毫秒级。对缓存这种允许短时不一致、但要求最终一致的数据来说,完全够用。
1.3 Keepalived 解决的是入口问题
主主复制解决的是“节点挂了,数据还有没有”的问题,但客户端访问缓存的入口仍然是一个具体 IP。如果这个 IP 对应的机器宕了,客户端并不知道要换 IP 去访问另一台,业务还是会报错。
Keepalived 的角色,就是给这两台缓存节点提供一个虚拟 IP(VIP)。正常状态下,VIP 绑定在主节点上;主节点宕机,VIP 自动漂移到备节点上。客户端只需要拿 VIP 去连缓存服务,不用关心后台是哪台机器在响应。
Keepalived 的底层是 VRRP 协议,靠多播心跳保持节点间的存活感知。我把这套机制比喻成两个值班员——主值班员每隔一秒给备值班员发一个“我还在”的广播,一旦广播停了,备值班员立刻把值班牌抢过来接电话。这个故障感知和切换速度,能控制在 1 到 3 秒内。
1.4 整体架构与数据流向预览
整个实验环境需要两台服务器,安装 CentOS 7 系统(其他主流发行版也可以,命令略作调整就行),在网络层面配置如下:
| 节点 | IP 地址 | 角色说明 |
|---|---|---|
| 节点 A | 192.168.1.101 | Memcached 主实例节点,Keepalived MASTER |
| 节点 B | 192.168.1.102 | Memcached 从实例节点,Keepalived BACKUP |
| VIP | 192.168.1.110 | 对外提供的缓存访问入口,故障时在 AB 间漂移 |
数据写入的过程是这样:业务服务连接 192.168.1.110,数据请求落在当前绑定 VIP 的节点 A 上。A 处理写请求后,内存里保存一份,同时异步复制到 B。此时如果 A 宕机,Keepalived 侦测到心跳超时,立刻把 VIP 挪到 B,后续新请求继续读写 B,B 上有 A 复制过来的历史数据,缓存不丢。
这套设计的核心价值在于:把故障的影响范围从“整个缓存集群失效”缩小到“单节点切换后的短时间缓存未命中”,而且切换过程不依赖业务侧任何感知。
2. 编译安装与前置环境准备
2.1 选型踩坑:repcached 版本不能乱选
Memcached 主主复制的能力不是官方内置的,而是通过一个第三方补丁管理维护的项目 repcached 实现的。repcached 的原理是给标准 Memcached 打了补丁,额外支持复制端口和复制模式,从中异常等问题也在补丁范畴内。
这里有一个非常关键的经验,而且是我实际踩过的坑:repcached 补丁并不是所有 Memcached 新版本都能打上。它最早的版本基于 1.2.x,后续有人跟进适配过 1.4.x 的版本,但总体的兼容性比较有限。
不建议直接去拉最新版 Memcached 再打补丁,大概率会失败。我验证下来比较稳的版本组合是:
- CentOS 7 自带 gcc 环境
- memcached 1.4.15 版本源码
- repcached 2.2.1 补丁包
这个组合在多个环境里实测过,编译能顺利通过,复制功能稳定。版本选定之后,第一步先保证系统有编译工具链:
yum install -y gcc gcc-c++ libevent libevent-devel makelibevent 是 Memcached 的底层网络事件库,必须提前装好。
2.2 编译支持复制功能的 Memcached
源码包准备好后,解压并打补丁:
tar -zxvf memcached-1.4.15.tar.gz cd memcached-1.4.15 patch -p1 < ../repcached-2.2.1.patch执行 patch 的时候,如果提示找不到文件或者版本不匹配,大概率是补丁版本和源码版本不对应。不用硬撑,赶紧换版本组合。
补丁打完后,生成 Makefile 并编译安装:
./configure --prefix=/usr/local/memcached --enable-replication make && make installconfigure 阶段多了一个--enable-replication参数,这个参数就是让编译产物包含复制功能的开关。如果编译过程中出现 Libevent 相关的报错,回去确认 libevent-devel 是否安装完整,之前有位同事在编译同一套代码时漏了这一步,结果卡了半小时。
编译完成后,验证效果:
/usr/local/memcached/bin/memcached -h输出信息里出现了-x和-X两个参数,说明复制版编译成功,其中-x指定对端复制 IP,-X指定复制端口。
2.3 两台节点之间的启动参数解析
节点 A 和节点 B 的启动参数基本对称,区别只在 IP 指向。
节点 A:
/usr/local/memcached/bin/memcached -p 11211 -u root -m 128 -d \ -x 192.168.1.102 -X 11212节点 B:
/usr/local/memcached/bin/memcached -p 11211 -u root -m 128 -d \ -x 192.168.1.101 -X 11212参数逐个解释一下:
-p 11211:对外提供缓存服务的端口,客户端默认都要连这个端口。-m 128:分配 128MB 内存给缓存实例,实验环境够用,生产环境按实际配置。-u root:用什么系统用户身份运行。实验环境图省事直接用了 root,生产环境建议单独建最小权限账号。-x:对端复制地址。节点 A 的对端是节点 B 的 IP,节点 B 的对端是节点 A 的 IP,两边的配置是交叉关系。-X 11212:专门用于节点间复制的端口。这个端口最好放防火墙白名单,只允许对端机器访问。
注意:不要把-p端口和-X端口配成一样的。生产上见过有人图省事直接共用端口,结果复制链路和数据服务互相干扰,排查起来非常麻烦。
2.4 防火墙与端口放行
CentOS 7 的 firewalld 默认只放行很少的端口。Memcached 服务和复制端口如果不放行,测试的时候会发现数据写入了就是复制不过去,而 11211 端口又从外面连不上。
执行以下规则:
firewall-cmd --permanent --add-port=11211/tcp firewall-cmd --permanent --add-port=11212/tcp firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 accept' firewall-cmd --reloadKeepalived 用到的 VRRP 协议走的不是普通 TCP,而是 IP 层的多播包,默认目标地址是 224.0.0.18。如果实验环境防火墙比较严格,还需要放行协议的 VRRP 通信。某些云环境限制多播,就得改用单播配置,这个后面在 Keepalived 配置里会说。
3. 核心实操:主主复制验证全过程
3.1 两种节点各自检查复制状态
编译并启动后,连接 Memcached 控制台查看运行状态。Memcached 默认没有独立的控制台客户端,直接用 Linux 自带的 nc 工具操作:
printf 'stats\r\n' | nc 192.168.1.101 11211输出里关注几个指标:
STAT curr_items:当前缓存条目数。STAT total_items:总计写入的条目数。STAT replication:复制状态。
执行之后如果看到STAT replication MASTER或者STAT replication SLAVE,说明复制功能正常运行。两块节点的复制角色由-x参数互相指定,所以输出中节点 A 和节点 B 会互为对方的对端。
启动顺序也有讲究:先启动节点 A,再启动节点 B,A 的日志里会显示成功连接 B 的复制端口。
3.2 正向写入验证
通过 VIP 或者直接访问节点 A,写入一条测试数据:
printf 'set username 0 0 5\r\nadmin\r\n' | nc 192.168.1.101 11211set参数格式为:键名、标志位、过期时间(0 表示永不过期)、数据字节数,下面一行是具体的值。返回STORED表示写入成功。
接着去节点 B 读取这条数据,看是否已经复制过来:
printf 'get username\r\n' | nc 192.168.1.102 11211如果能读到admin,说明主主复制的正向链路已经打通。这种验证方式是最直观的:数据从 A 进去,B 这边能看到,就说明节点的复制线程在正常工作。
3.3 反向写入验证
同理,反向链路也要验证一次。先给节点 B 写入一条数据:
printf 'set token 0 0 6\r\nabcdef\r\n' | nc 192.168.1.102 11211然后回节点 A 读取:
printf 'get token\r\n' | nc 192.168.1.101 11211可以看到两边都读出了abcdef和admin,正反双向复制完全正常。
这里有个容易被忽略的细节:主主复制模式下,两个节点其实都同时扮演写入端的角色,不存在只能由一方写、另一方只读的约束。所以数据可以自由从任意一侧写入,都会自动同步到对端。
3.4 多键写入与删除同步测试
再往深处测一层,批量写入不同键并验证删除操作是否也会复制。
连续写入几条数据:
printf 'set key1 0 0 3\r\nval\r\n' | nc 192.168.1.101 11211 printf 'set key2 0 0 3\r\ndata\r\n' | nc 192.168.1.101 11211 printf 'set key3 0 0 4\r\ninfo\r\n' | nc 192.168.1.101 11211在节点 B 上批量检查:
printf 'get key1 key2 key3\r\n' | nc 192.168.1.102 11211然后删除其中一条,再验证:
printf 'delete key1\r\n' | nc 192.168.1.101 11211 printf 'get key1\r\n' | nc 192.168.1.102 11211节点 B 上读取key1时返回空,说明删除操作也通过复制链路同步生效。对生产环境而言,删除同步特别重要,否则会出现一台节点清掉了脏数据,另一台又把旧数据复制回来的问题。
3.5 复制异常时的自我体检方法
遇到复制不同步的情况,先自查以下几类常见原因:
复制端口不通。用 telnet 直接连对端的-X端口,确认 TCP 能通。
启动顺序反了。后启动的节点会主动连接到先启动的节点,如果对端没启动,日志会一直输出重连警告,这时候重启当前节点服务即可。
防火墙拦截。repcached 启动时报Permission denied基本就是防火墙问题。
命令行查连接状态:
netstat -antp | grep 11212看到双方各自有一条指向对方11212端口的 ESTABLISHED 连接,说明复制链路是双向完好。如果只有单向连接,那就要检查启动参数中 IP 是否写反了。
4. Keepalived 高可用配置与 VIP 漂移实现
4.1 安装与基础配置骨架
复制功能验证完毕,接下来搭建高可用层。安装 Keepalived 很简单,直接用系统包管理器:
yum install -y keepalived安装好后修改主配置文件/etc/keepalived/keepalived.conf。
节点 A(主节点)的核心配置:
global_defs { router_id cache-node-a } vrrp_instance VI_CACHE { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 4f1d2a8c9e } virtual_ipaddress { 192.168.1.110 } }节点 B(备节点)的配置基本一致,关键差别在state BACKUP、priority 90,router_id改成cache-node-b,virtual_ipaddress里 VIP 保持一致。
4.2 关键参数的设计逻辑
接口配置。interface ens33必须和机器实际绑定的网卡名一致,如果节点 A 和节点 B 网卡接口名不同,各自配置各自的。可以通过ip addr命令查看,生产环境建议做成光口或者专用高可用网段。
virtual_router_id 51,两台机器必须一致,这是标识同一组高可用实例的 ID。如果配置不一致,Keepalived 之间无法识别对方,就会出现两边同时持有 VIP 的互相竞争状态。
优先级选择,MASTER 配 100,BACKUP 配 90,差值 10 已经足够。VRRP 协议只在接管的瞬间比较优先级,差值没所谓,但差值太小容易在网络抖动时发生频繁切换。
nopreempt这个参数值得单独说一说。它表示当更高优先级的节点恢复后,不会强行把 VIP 抢回来。默认情况下 MASTER 恢复,会重新抢占 VIP,这在某些业务场景反而会产生一次额外的切换抖动。我一般建议实验环境下开启nopreempt,避免因为网络小抖动引发不想要的切换。
认证密码段,auth_pass最长 8 位,用随机字符串即可,两台机器必须严格一致。注意这只是通信认证,不负责数据加密,不能当作安全方案依赖。
4.3 健康检查脚本与状态联动
Keepalived 默认只检测网络心跳,不关心 Memcached 进程本身是否存活。收不到对端心跳才切换,有个前提:对端机器整个宕机或网络断了。但如果只是 Memcached 进程崩溃,网络心跳还正常,VIP 是不会切换的。
为了做到进程级高可用,需要在配置文件里加一个自定义监控脚本。
在/etc/keepalived/check_memcached.sh中写:
#!/bin/bash if pidof memcached > /dev/null then exit 0 else exit 1 fi脚本的作用是检查 Memcached 进程是否还活着。进程存在返回 0 表示正常,不存在返回 1 表示故障。
然后在配置文件里引入这个脚本:
vrrp_script check_memcached { script "/etc/keepalived/check_memcached.sh" interval 2 weight -20 } vrrp_instance VI_CACHE { ... track_script { check_memcached } }interval 2表示每两秒检查一次。weight -20的含义是:如果脚本检测到 Memcached 进程挂了,本节点优先级自动降低 20。主节点原本优先级 100,降 20 变成 80,低于备节点的 90,备节点就会接管 VIP。
这个联动机制比单纯依赖 VRRP 心跳更靠谱。它把“节点活着”和“服务可用”区分开,即使节点本身还在,只要关键服务崩了,VIP 依然会被切给健康的备节点。
4.4 启动与 VIP 归属验证
两边配置好并确认脚本拥有可执行权限后:
chmod +x /etc/keepalived/check_memcached.sh systemctl start keepalived systemctl enable keepalived在节点 A 上查看 VIP 归属:
ip addr show dev ens33输出里192.168.1.110/32绑定在节点 A 的网卡上,说明当前 VIP 由主节点持有。
在节点 B 上用同样的命令查看,看不到 VIP,说明它处于待命状态,一切正常。
测试 GOP 客户端访问:
printf 'set live_cache 0 0 4\r\nhigh\r\n' | nc 192.168.1.110 11211 printf 'get live_cache\r\n' | nc 192.168.1.110 11211只要能写入并读取,说明业务层通过 VIP 访问缓存集群路径是通的。
4.5 云环境多播受限的替代方案
如果你的实验跑在部分云环境里,多播不支持,Keepalived 默认的 VRRP 报文会发不出去,两台机器无法感知对方,VIP 也不会漂移。
解决办法是切换到单播模式。在vrrp_instance段里指定:
unicast_peer { 192.168.1.102 } unicast_src_ip 192.168.1.101节点 A 把节点 B 的 IP 写进unicast_peer,节点 B 则把节点 A 的 IP 写进去,unicast_src_ip各配各的本机地址。这种模式下,VRRP 报文通过单播发送,绕过多播限制,实现在不支持多播的网络环境中正常工作。
5. 故障演练与恢复验证实录
5.1 模拟 Memcached 进程崩溃
现在把实验推到最关键的环节:故障发生时,整套系统到底能不能安全接管。
正常状态:VIP 在节点 A,缓存里已有写入的数据。
在节点 A 上手动杀掉 Memcached 进程:
pkill memcached此时,Keepalived 里配置的track_script在 2 秒内检测到 Memcached 进程消失,节点 A 优先级从 100 降到 80,低于节点 B 的 90。经过一个通告周期(默认 1 秒),节点 B 发出广播宣告接管 VIP。
在业务机器上再通过 VIP 读写:
printf 'get failover_key\r\n' | nc 192.168.1.110 11211查询仍然正常返回,说明 VIP 已经成功漂移到了节点 B。
查看节点 B 的 IP 地址:
ip addr show dev ens33可以看到192.168.1.110/32已经出现在节点 B 的网卡上,印证 VIP 完成了切换。
这个实验里最重要的一个细节是:因为主主复制的存在,节点 B 原本就有一份复制过来的数据,所以切换后第一次读操作就能命中缓存,而不是所有请求都穿透到后端数据库。
5.2 模拟整机宕机的极端情况
进程崩溃测试的是 Keepalived 的track_script联动机制,但在真实的运维事故中,整机断电或网络断连的情况也不少。
直接执行:
poweroff把节点 A 完全关掉。节点 B 会在advert_int设定的间隔内等不到节点 A 的心跳通告,然后在约 3 秒内接管 VIP。对比进程崩溃场景,整机宕机时心跳超时的检测比脚本检测略长,但也在秒级范围内。
此时客户端访问 VIP,所有读写都由节点 B 独立承接。期间数据仍能正常写入,节点 B 作为唯一存活节点,承担了全部缓存流量。
5.3 原节点恢复后的自动回切
如果配置了nopreempt,节点 A 恢复后不会主动抢 VIP,系统会保持节点 B 继续对外服务,直到节点 B 再次故障时才让出。
如果追求原主节点恢复后自动接管流量,把主节点配置里的nopreempt删掉,并显式加上preempt。恢复后节点 A(优先级 100)会重新宣告自己并取回 VIP。
关于回切,我的建议是:优先保留nopreempt,减少切换次数。频繁的主备切换对上层连接池来说没有任何好处,反而会在切换的瞬间产生一批连接重置。缓存服务本身对连接不敏感,但业务应用的后端连接池会有短暂重建,所以能少切就少切。
5.4 数据完整性与缓存雪崩压力验证
故障切换完成后,还应该做一轮数据完整性抽查。先往故障恢复后的节点写入一批新数据,再在任意节点上读取:
printf 'set order_1001 0 0 4\r\naaaa\r\n' | nc 192.168.1.110 11211 printf 'set order_1002 0 0 4\r\nbbbb\r\n' | nc 192.168.1.110 11211切换前后数据都完整存在于集群中,说明主主复制在两轮切换中都没有丢数据。
压力层面的验证,可以用循环脚本模拟少量并发读写,确认在切换过程中没有出现明显超时窗口:
for i in $(seq 1 1000); do printf 'set pressure_%s 0 0 4\r\ntest\r\n' "$i" | nc 192.168.1.110 11211 > /dev/null done实测下来,正常情况下 1000 条写入全部返回 STORED,只有切换瞬间少数几条会返回连接超时,但重试一次即可成功。这也说明整套高可用方案对业务的实际影响窗口极小。
6. 常见问题与排查技巧实录
6.1 repcached 编译失败的几类原因
编译阶段最容易卡住,说几个我见过的高频错误:
补丁无法应用,出现类似Reversed (or previously applied) patch detected。这通常是因为源码版本与补丁不匹配,或者源码目录已经被打过补丁。解决方式就是换回推荐的版本组合,重新解压一个干净的源码包。
configure 阶段报缺失libevent。检查一下 yum 安装的 libevent 和 libevent-devel 是否都已就位。有同事只装了 libevent 没装 devel,编译到一半报找不到头文件。
编译过程报线程相关错误。可以尝试降低优化级别,或者查看 gcc 版本是否过旧。CentOS 7 自带的 gcc 4.8 实测编译这套组合没问题。
6.2 Keepalived 脑裂情况的识与防
脑裂是指两台节点都认为自己是主节点,同时持有 VIP,导致外部流量不确定落在哪台上,数据一致性会被打破。
产生脑裂的直接原因,通常是 VRRP 心跳被网络隔离,但两边进程都健康。在实验环境中,多播被禁用、unicast_peer配置缺失,也会导致两边互相感知不到。
预防脑裂的手段,一是配置认证参数,防止非法节点伪造 VRRP 报文;二是配合track_script,让故障检测覆盖到应用层;三是严格保证virtual_router_id和优先级配置正确。
如果怀疑发生脑裂,检查方法很简单,在两台节点上分别执行:
ip addr show dev ens33 | grep 192.168.1.110两边都出现了 VIP,即确认脑裂。
6.3 常见问题速查表
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 数据在 A 机写入,B 机查不到 | 复制端口被防火墙拦截;对端 IP 配置错误 | 放行 11212 端口;检查启动参数-x |
| 两边启动日志大量连接超时 | 对端 Memcached 未启动,或版本复制端口不一致 | 确认对端实例启动;对照配置文件排查端口 |
| VIP 不漂移但节点网络通 | Keepalived 多播被禁用 | 改用单播模式unicast_peer |
| Memcached 死了 VIP 不切 | track_script未配置或脚本无执行权限 | 补全脚本配置,chmod +x |
| 两边同时持有 VIP | VRRP 心跳异常,脑裂 | 检查网络隔离、认证密码一致性,配置单播 |
| 切换后客户端持续连接失败 | 业务侧连接池缓存了旧 IP | 应用层启用自动重连,或设置较短的连接空闲超时 |
6.4 生产环境落地的额外建议
实验做完之后想往生产上挪,有几个地方比实验环境要多想一步。
内存规划。Memcached 是纯内存缓存,主主复制模式会让两台机器保存相同的数据,内存开销直接翻倍。配置-m参数时,要把这份冗余计算进去。
监控体系。在 Keepalived 的 track 脚本里,除了检查进程是否存在,还可以加上端口响应检测:
#!/bin/bash if printf 'stats\r\n' | nc 127.0.0.1 11211 2>/dev/null | grep -q 'STAT version' then exit 0 else exit 1 fi这种检测方式比单纯检查进程更严格,进程存在但端口不响应时也能发现。
恢复顺序。如果两台节点同时断电重启,等 Memcached 起来后,先启动复制参数配置完整的一台,再启动另一台。让复制链路由后起的节点主动连接先起的节点,能更快把同步状态恢复起来。
6.5 一次真实事故的复盘记录
这套方案搭建完以后,我还做了一次状态记录。某天凌晨节点 A 所在机柜意外断电,当时 VIP 在节点 A 上。节点 B 在 3 秒内接管 VIP,监控系统在随后的 30 秒内开始报警,业务侧反馈出现少量超时请求,但整体服务没有中断。
节点 A 恢复后,因为配置了nopreempt,VIP 继续留在节点 B。白天低峰期,手动将服务切回节点 A,整个过程耗时不到 10 秒,缓存命中率未出现明显波动。
这次验证让我觉得最值钱的一点是:故障不可怕,可怕的是故障发生时没有预案。把主主复制和 VIP 漂移结合起来,等于在缓存层前面加了一道可靠的自动保险,而且这层保险不依赖任何商业组件,纯开源工具就能做到。
最后分享一个小技巧:实验做完之后,别急着把所有进程都关掉,保留环境几天。每天随机抽一台机器重启一下,连续观察几天切换是否每次都顺利。这套高可用方案的可靠性,是在一次次真实切换中验证出来的,不是装完配置就算结束。