那天下午,我觉得Redis里缓存了些开发测试数据,想顺手清掉。顺手敲了句docker stop redis,切回浏览器刷新博客,直接弹了个刺眼的502 Bad Gateway。我当时人都傻了,明明只是停个缓存服务,怎么连主站都跟着陪葬了?赶紧翻日志才发现,我的Java代码里写死了Redis地址,连不上直接抛异常,Spring Boot的默认错误页就直接接管了页面。原来缓存断了,居然能把整个网站拖下水。
跑去搜“Redis挂了怎么办”,满屏都是Sentinel和Cluster。一开始我也发懵,后来慢慢看明白了。Sentinel就像给主Redis配了个“备胎司机”。主司机要是”半路抛锚“,备胎立刻坐进驾驶座接着开,对外给的还是同一个车牌号,用户根本感觉不到换人了。它专门解决高可用问题,也就是主节点宕机了,得有机制自动顶上,别让服务开天窗。
Cluster则是另一套玩法,它更像“把货物分到多辆车上跑”。数据被切成一块块,分散存在不同的节点里,每台车只拉自己那部分货。它解决的是容量和性能瓶颈,单机内存塞不下了,或者并发读写太大扛不住,就得靠它横向扩容,把压力摊开。
回头看看我的个人博客,文章就几篇,每天访问量也就几个,数据量连单机内存的零头都占不满。我真正怕的不是装不下,而是服务一挂全站瘫痪。Cluster那种大动干戈的分片方案对我纯属杀鸡用牛刀,运维成本也高。Sentinel这种主备切换的轻量方案刚好踩中我的痛点,简单够用,出了问题也能快速拉起。
说干就干,我直接用最简的docker-compose把环境搭了起来:
version: '3.8'
services:
redis-master:
image: redis:7-alpine
# 主节点,默认就是读写核心
ports: ["6379:6379"]
redis-replica:
image: redis:7-alpine
# 从节点,启动时直接告诉它去同步master,端口6380
command: redis-server --replicaof redis-master 6379
ports: ["6380:6379"]
depends_on: ["redis-master"]
redis-sentinel:
image: redis:7-alpine
# 哨兵节点,专门负责盯梢和指挥切换,端口26379
ports: ["26379:26379"]
depends_on: ["redis-master", "redis-replica"]
# 启动时加载我们自己的哨兵配置文件
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel.conf:/usr/local/etc/redis/sentinel.conf
sentinel.conf里核心就三行配置:
sentinel monitor mymaster redis-master 6379 1 (盯紧名叫mymaster的主节点,只要有1个哨兵同意就执行切换)
sentinel down-after-milliseconds mymaster 5000 (连续5秒收不到主节点心跳,就判定它掉线了)
sentinel failover-timeout mymaster 10000 (整个切换过程最多给10秒,超时算失败)
这次折腾让我彻底搞懂了什么叫单点故障。说白了,就是系统里某个关键组件只有一份实体,它一罢工,整条业务线直接断联。以后不管做多大的项目,只要碰到数据库、缓存这种核心依赖,脑子里都得提前盘算:它要是突然断了,系统能不能扛住?不能的话,高可用方案必须写进设计里。原来是这样,架构从来不是堆砌新技术,而是给意外留好退路。