
扛住 10000 QPS 秒杀的高并发系统设计五层缓冲与限流熔断落地指南【免费下载链接】geektime-books:books: 极客时间电子书项目地址: https://gitcode.com/GitHub_Trending/ge/geektime-books秒杀活动开闸的第一秒1 万个用户同时点下抢购按钮。如果请求一个都不拦数据库连接数会瞬间冲上万MySQL 当场趴下。这篇文章用极客时间《88-高并发系统设计40问》里的真实例子把高并发系统设计的分层削流量思路拆开讲流量要分五层消化每一层拦什么、怎么配、配错会踩什么坑。 场景走读一次秒杀请求的完整旅程先把全景建立起来。用户从点按钮到看到抢购中的提示请求依次穿过五道关卡CDN 层商品页里的图片、视频这类能被静态化的数据直接命中 CDN 节点根本到不了服务器。缓存层用户查的是同一批热点商品书里的做法是让 Nginx 直接访问分布式缓存节点把请求挡在 Tomcat 之前。网关限流层同一用户、同一 IP、同一设备的短时间重复请求在这里直接丢弃。队列层真正要下单的写请求全部塞进消息队列排队响应立刻返回结果正在计算中。数据库层落到 MySQL 的并发量等于队列处理程序的线程数是一个你说了算的固定值。五层里前四层都在做同一件事让尽可能少的请求以尽可能平的速率摸到数据库。难点拆解四层缓冲各自的配置要点限流算法怎么选窗口、漏桶、令牌桶的取舍现象限流明明开了大促时照样被打穿或者限流一开正常请求的延迟肉眼可见地变高。成因按书中的说法问题多半出在算法选型和实现位置。固定窗口计数每分钟记一次数超了就拒实现最简单但挡不住短时间的集中流量而把限流放在单机上多机部署时每台机器各限各的总流量照样超标。解法四种主流算法的对比如下算法核心思路适用场景固定窗口计数每个时间窗口记一次数超阈值拒绝下个窗口清零粗略控制实现成本最低滑动窗口计数把窗口切成多个小格分别计数平滑边界峰值对精度要求较高的入口漏桶算法请求先堆进桶里出口按固定速率匀速放出必须把流量整形成平流的链路令牌桶算法像售票处的取票机按固定速率放票桶里可囤票应对小高峰API 网关、接口限流实际项目中最常用书里更倾向令牌桶漏桶把突发流量缓存在桶里会拉长用户等待时间和互联网业务低延迟的诉求相悖令牌桶则允许桶里暂存一批令牌突来一波小高峰能直接发出去。另一个容易忽略的点分布式环境下令牌数量通常存在 Redis 里每次只取一个令牌每个请求就多跑一趟 Redis。折中办法是一次取一批令牌本地用完再去取把 Redis 往返次数压下去。为什么一个慢服务能拖垮整个系统熔断与降级现象大促复盘时发现挂掉的不是数据库而是整条调用链——明明只有推荐服务响应变慢下单接口却跟着超时了。成因分布式系统最怕的从来不是某个服务宕机而是它响应变慢。书里给了一个很典型的雪崩链路A 调 BB 同时调核心服务 D 和非核心服务 C。流量上涨时团队只给 A、B、D 扩容C 没跟上处理变慢。B 调 C 的请求全部阻塞住等结果线程被占满B 的线程池队列积压反过来把 A 拖死。一个非核心服务的慢响应放大了整条链路。解法思路只有一个——检测到依赖服务响应异常时快速失败把占住的资源立刻还回来。具体手段对比手段核心思路适用场景熔断失败次数超阈值就断开电路后续请求直接返回错误定时器周期性探测探活成功才恢复依赖服务、Redis 节点出现慢响应或持续失败开关降级代码里预埋开关值放配置中心开关一拨就跳过远程调用、返回兜底数据非核心功能整体放弃保主流程限流降级入口拒绝超出承载能力的请求峰值流量超出预估保核心接口熔断的实现可以理解为每个被调服务维护一个三态状态机关闭正常调用→ 失败数攒够阈值切到打开拒绝请求→ 计时器到期切到半开放少量试探请求→ 累计成功则回到关闭再失败则重新打开。这套逻辑不只用于微服务团队给 Redis 客户端也封装了一份Open 状态下用定时器 ping 节点探活熔断期间操作直接返回空值。消息队列削峰处理程序开几个才够现象库存只剩 1000 件消息队列里的下单请求却堆了几万条用户等了半分钟还是看不到结果。成因队列处理程序开太少消化速度跟不上。书里给了一笔很实用的账单件商品下单处理耗时 500ms1 个处理程序清完 1000 件要 500 秒开到 10 个总耗时压到 50 秒同时打到数据库的并发也只剩 10压力完全可控。解法先做容量评估商品数 × 单条处理耗时 ÷ 可接受的等待时间再定处理程序数量。处理程序数量1000 件全部处理的耗时数据库同时承压的并发1 个500 秒18 个400 秒810 个50 秒10注意两个边界库存扣完之前队列里堆积的多余请求可以直接丢弃不必处理但让用户等结果只适用于秒级到几十秒的量级等太久用户会怀疑活动有猫腻。哪些步骤能扔进异步砍掉流程里的陪跑耗时现象压测显示单次下单要 500ms其中生成订单和扣库存才是主角剩下的时间花在了不重要的事上。成因下单成功后的发优惠券、加积分各占 50ms却和主流程串行执行等于每次下单都多陪跑 100ms。解法把这类次要逻辑挪到另一个队列处理程序里异步执行。整条链路从 500ms 缩到 400ms性能提升 20%前面算的 10 个处理程序直接省出 2 个。判断标准就一条这一步慢一点用户当下感不感知感知不到就异步。踩坑与排障三个哪里出了问题的真实案例坑一限流阈值没设错但限流就是没生效现象压测报告显示每秒进来 20 个请求超过了每秒 10 个的限流阈值却被放行了。根因用的是固定窗口。前 10 个请求集中在第 1 秒的最后 10 毫秒后 10 个出现在第 2 秒的前 10 毫秒窗口一换各自计数都没超20 毫秒内的瞬时冲击就这么溜过去了。修复换用滑动窗口或令牌桶这类能感知窗口边界的算法阈值别拍脑袋放在配置中心里靠定期压测出来的实际承载能力来定方便动态调整。坑二扩容做了雪崩照样发生现象大促当天流量翻倍核心链路跟着超时事后发现源头只是反垃圾服务响应变慢。根因扩容只覆盖了核心服务非核心服务没跟上调用方对慢依赖没有快速失败机制线程被慢请求一路占住。修复给所有外部依赖包括 Redis 这类组件加熔断器响应时间异常就快速返回失败非核心功能预留降级开关必要时从配置中心一键关闭不重启服务。坑三单机限流上了分布式性能反而变差现象多机部署后把令牌桶改到 Redis 上每个请求多一次 Redis 往返网关整体延迟涨了数毫秒。根因进程内的令牌变量在机器之间不共享改造时图简单做成了每请求取一个令牌。修复改为每次从 Redis 批量领取一批令牌在本地消费取令牌的频率降了一个数量级Redis 压力和请求延迟同时回落。落地清单按活动节奏逐项核对活动前压测定阈值对整条链路和每个服务做压力测试拿到实际承载能力据此设置限流阈值热点数据预热秒杀商品数据加载进缓存静态资源确认走 CDN熔断参数就位每个依赖的失败阈值、探测间隔、半开成功次数逐一配置监控就位按 RED 指标体系请求量、错误、响应时间覆盖核心接口组件层盯缓存命中率、主从延迟、队列堆积活动中盯队列堆积堆积量持续上涨就临时加队列处理程序别等用户投诉盯限流阈值阈值放配置中心误伤正常请求或拦不住时都能秒级调整盯熔断状态确认熔断只打开在预期内的节点上核心链路没有被误伤活动后对账与恢复核对订单与库存数据队列里未处理的过期请求及时清理数据复盘数据团队直接订阅队列里的购买数据做活动分析不用业务系统再额外推送回收配置限流、降级开关恢复日常值压测数据归档为下一次活动留基准高并发设计没有银弹本质是拿分层消化把瞬时洪峰摊平CDN 挡静态、缓存挡热点、限流拒超额、队列排队列、异步砍陪跑。每一层都留了可调节的阀门阈值、开关、并发数全部可动态调整系统才有底气面对超出预估的流量。延伸阅读仓库内电子书10-如何设计一个秒杀系统.epub46-Kafka核心技术与实战.epub146-Redis核心技术与实战.epub你上次踩限流的坑是阈值拍错了还是算法选错了欢迎在评论区聊聊。【免费下载链接】geektime-books:books: 极客时间电子书项目地址: https://gitcode.com/GitHub_Trending/ge/geektime-books创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考