高并发系统设计原理与实践

接入与开发

给架构师讲高并发系统的工程落地:超时与重试怎么分档、并发与排队怎么设、降级和日志怎么留、上线前怎么压测。

很多人聊高并发只停在「加缓存、加机器、上消息队列」这几句,真到自己系统里,往往是从一次线上抖动开始卡住的:接口批量超时、限流一动就雪崩、日志翻半天看不出是哪一层慢。这篇不重复原理课,只按工程落地顺序,把超时、并发、降级、日志、评测这几件事拆成能直接照着做的清单。

很多人聊高并发只停在「加缓存、加机器、上消息队列」这几句,真到自己系统里,往往是从一次线上抖动开始卡住的:接口批量超时、限流一动就雪崩、日志翻半天看不出是哪一层慢。这篇不重复原理课,只按工程落地顺序,把超时、并发、降级、日志、评测这几件事拆成能直接照着做的清单。

下面按四个环节展开:先把超时预算定死,再谈并发和排队怎么设,然后是降级预案砍哪一块,最后是日志指标怎么留。每一节都给出判断标准和落地动作,并标注什么场景下不适用,方便架构师直接对照自己系统做取舍。

先定超时预算,再谈并发

超时不是拍脑袋填个数字。要把一次请求的总耗时拆成排队、连接、读取、下游调用几段,每段单独设上限。只写一个「总超时」的问题在于,你根本不知道时间花在哪一段,调优时只能靠猜。分段设限后,哪一段先触顶一目了然。

链路分段设限对象触顶后的动作
排队等待线程/连接快速失败,别堆积
连接建立连接重试或切备用节点
读取单次响应读取按业务容忍度设上限
下游调用每个依赖单独设超时即返回兜底值
  • 重试要区分「能重试」和「不能重试」:只读类可退避重试,写类先确认幂等再做,否则越重试越堵;
  • 每段超时值之和要小于上游给你留的总预算,否则上游先断,你的分段再精细也没用;
  • 超时值没有普适答案,先到 /tools/speed-test 量出自己链路的延迟基线,再按基线往上留余量;
  • 不适用的情况:链路里有强一致写、下游本身不稳时,盲目加长超时只是把故障拖长,这时候要改成快速失败。

并发不是越高越好:排队、分批与退避

并发调高不等于吞吐变好。系统真正的「有效并发」是三者的最小值:处理线程数、连接池大小、下游给你的配额。超出这个值的请求,要么排队,要么被拒。盲目加线程只会让上下文切换和下游压力同时上升,最后全线变慢。

  1. 算有效并发把线程数、连接池、下游配额三个数摆出来,取最小值作为并发上限,写进配置而不是记在脑子里。
  2. 给队列设边界队列要有长度上限和等待时间上限,超了直接拒绝,别让队列无限增长把内存吃掉。
  3. 批量任务分批推进每批设上限、批间隔留喘息,失败项单独重投,别让一批拖垮整轮。
  4. 限流后退避触发限流后按指数退避加抖动重试,避让而不是硬顶;恢复节奏写进配置,别写死在代码里。

不适用的情况:面向人的实时交互接口不适合长排队,宁可降级给简化结果,也别让人等几分钟。反过来,后台批处理适合排队,但要控制批大小和重投逻辑,避免失败任务反复冲击下游。

降级预案:先想清楚「砍哪一块」

降级不是「出事了再说」,而是提前把功能按重要性排序,明确哪些可以砍、砍了之后返回什么。最怕的是临时拍板,结果把核心链路一起关了。把可降级项整理成一页开关清单,做到随时能开能关。

功能类别是否可降级降级后表现
核心读服务否报错并告警
非核心推荐是返回缓存兜底结果
统计报表是延迟到低峰计算
涉及资金/权限否明确报错,走人工
日志上报是采样或本地暂存
  • 降级开关要能独立生效、能快速回滚,最好不依赖发布流程;
  • 上游大面积故障时优先保核心链路,非核心功能直接熔断,避免资源被拖光;
  • 每个开关都要有「谁负责开、什么条件下开、开多久」的记录,别让开关状态没人管;
  • 不适用的情况:涉及资金、权限、审计的路径不该做「静默降级」,这类要么明确报错,要么走人工确认。

降级策略本身也要压测。光有开关不代表有效,定期做一次演练:手动断掉某个下游,看核心链路是否还能撑住,非核心功能是否按预期返回兜底值。演练结论要沉淀成清单,下次真出事时直接照着执行。

日志与指标:让慢和贵都能复盘

没有贯穿全链路的标识,排障就是大海捞针。请求入口打一个 trace id,下游每一跳都带上,出问题时能顺着拼回一次完整调用。这是最基础的投入,回报也最直接。

记录字段用途备注
trace id串联全链路入口生成,逐跳透传
耗时分段定位是哪一段慢和超时预算对齐
状态码区分成功/失败/降级别只记 HTTP 码
重试次数判断是否在反复冲击结合退避策略看
消耗量评估成本到站内页面核对当时数字

指标优先看分位数而不是平均值。平均值会把少数极慢请求稀释掉,而用户真实的感受恰恰来自尾部延迟。把 P95、P99 单独拉出来看趋势,比看平均线有用得多。

另外,定期做一次「故障演练加回放」:拿历史慢请求跑一遍新配置,看是否还超时。这个动作能验证超时预算和并发设置是否真的生效,也能把结论沉淀成下一次调优的基线。

下一步把你现在的超时、并发、降级配置和站内整理的中转站与工具数据对照一遍,看看链路上哪一段还没被观测到,再决定先补哪一块。

常见问题

高并发到底该先优化哪一层?

先量再改。按「入口 → 应用 → 下游依赖 → 存储」走一遍,用分位数定位真正的瓶颈点,多数系统的瓶颈在依赖调用和慢查询,而不是应用层算力。先修最慢的那一跳,比凭感觉加机器有效得多。

并发数设多少合适,有没有通用公式?

没有固定值。取线程池、连接池、下游配额三者的最小值作为上限,再按实测的延迟基线往里压。具体配额各家不同,到 /official-api 和 /providers 核对当时的口径,再结合自己压测数据定。

降级和重试会不会互相打架?

会。重试放大流量,降级是减少工作量,两者要配合:先判断能不能重试,不能就直接走降级分支。规则写在同一处配置里,避免一半在代码、一半在网关,出故障时谁也说不清最终行为。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。