Redis 原子计数在主从切换时丢数,我们靠 Lua 脚本加本地缓存兜住了那波被放行的流量
凌晨Redis主从切换导致限流器失效,3秒内多放行近4000请求。问题根源是INCR异步复制导致数据丢失。解决方案分两层:Lua脚本在计数达阈值80%时写入兜底标记key;本地Caffeine缓存异常时接管限流,通过悲观估算控制误放率。压测显示方案将超限从3.2倍降至12%,上线后经历多次故障均未触发告警。
共 52 篇文章
凌晨Redis主从切换导致限流器失效,3秒内多放行近4000请求。问题根源是INCR异步复制导致数据丢失。解决方案分两层:Lua脚本在计数达阈值80%时写入兜底标记key;本地Caffeine缓存异常时接管限流,通过悲观估算控制误放率。压测显示方案将超限从3.2倍降至12%,上线后经历多次故障均未触发告警。
网关层做 gRPC 和 RESTful 协议转换,核心是把路由发现、序列化协商、错误码映射三条链路稳定整合。路由层通过 proto annotation 显式声明 HTTP 映射,用 descriptor 文件构建路由表,Envoy 配置精确控制匹配粒度。序列化层统一字段命名和枚举输出,流式响应需开启 streaming_json。错误码映射自定义 gRPC 到 HTTP 的转换表,用 ErrorInfo 承载业务错误码,保持响应体结构一致。
网关 502 故障暴露了 Tomcat 共用线程池的缺陷:一个慢接口拖垮整个服务。解决方案是实施接口级线程隔离,为不同接口分配独立线程池,并加入带超时的排队机制,避免请求直接失败。配合动态配置、分级监控和上下文传递,成功将故障限制在局部,保障核心链路稳定。
秒杀场景下,Apollo默认5分钟轮询间隔导致配置生效延迟3.2秒,引发数据库连接池打满、Redis CPU飙升。通过将轮询改为长轮询,结合本地缓存和即时生效机制,将平均延迟压至180ms,P99控制在600ms。改造涉及启用长轮询模式、优化限流器动态更新、按需刷新Namespace,并调整服务端线程池和重连策略以保障稳定性。
gRPC 四种服务端类型各有适用场景,选错代价高昂。Unary 适合一问一答,天然支持背压控制;Server Streaming 用于数据推送,但必须配合分页和超时机制防止内存溢出;Client Streaming 适合批量上传,需在收到 EOF 后统一事务处理;Bidirectional Streaming 用于实时双向通信,要严格管理协程生命周期。决策关键在于匹配业务的数据流向和速率特征,避免过度设计。
日均1.2TB日志写入场景下,引入Kafka作为缓冲层后,ES集群CPU使用率从72%降至31%,写入延迟P99从2.3秒收敛到180ms。Kafka利用零拷贝技术,以极低CPU开销实现高效数据转发,核心价值在于削峰填谷,避免ES因写入脉冲与合并操作叠加导致的性能断崖。整体资源账算下来,CPU净省29个核,磁盘成本因使用HDD而几乎可忽略,链路稳定性显著提升。
Sentinel 集群限流依赖的 Token Server 一旦宕机,业务易陷入无保护状态。团队在控制台侧增加健康检查与本地降级逻辑,检测到 Server 不可用时,自动将集群规则转换为单机限流规则并推送至客户端。压测验证显示,该方案能将故障时的错误率从 12% 降至 0.3%,有效防止链路崩溃,且无需改造业务应用。
gRPC 调用中重试、超时、熔断逻辑常被重复编写,导致业务代码臃肿。通过将三者拆分为独立拦截器,并按熔断→超时→重试的顺序串联成链,可形成单向流动的容错链路。熔断器避免无效调用,超时控制整体耗时,重试在时间窗口内执行。最终业务代码大幅精简,系统延迟降低,冗余容错模板被彻底消除。
从业务指标出发,重新定义 Pulsar 容量规划:核心应关注生产延迟、消费积压和分区倾斜度,而非 CPU 或内存。生产延迟揭示 Broker 的 Topic 承载上限与 Bookie 磁盘瓶颈;消费积压增速可反推 Consumer 与分区配比;分区倾斜度则能暴露隐藏热点。三者联动构成决策树,将规划单位从节点细化到分区,能更精准地保障系统延迟与稳定性。
同一套压测条件下,令牌桶 P99 延迟仅 23ms,滑动窗口却飙到 310ms。核心差异在于滑动窗口的刚性时间边界导致请求周期性积压,而令牌桶的连续令牌发放避免了“一刀切”延迟。压测数据、根因分析和 Lua 脚本实现均证实,突发流量场景下令牌桶的延迟分布远优于滑动窗口。