第1关:并发编程的三个概念的定义和区别

接入与开发

给后端新人理清并发、并行、高并发、高可用、分布式之间的关系,配一套自查判断清单与排错顺序,不背定义也能用对。

刚写后端的人常被这几个词绕住:接口文档写「支持高并发」,面试问「并发和并行的区别」,上线又被要求「高可用、可分布式部署」。这篇不堆定义,先把三个层次的问题分开,再给一份自查清单和排查顺序,让你遇到具体需求时能判断该动哪一层、什么情况下这些说法其实不适用。

刚写后端的人常被这几个词绕住:接口文档写着「支持高并发」,面试官问「并发和并行的区别」,上线又被要求「高可用、可分布式部署」。这些词被混着用,导致很多人一遇到性能问题就想着加线程、拆服务,方向从一开始就错了。

这篇不堆定义,先把三层问题分开:代码层的任务调度、系统层的请求规模、部署层的冗余能力。分清楚之后再给一份自查清单和排查顺序,让你遇到具体需求时能判断该动哪一层,以及什么情况下这些说法其实不适用。

先把三层问题分开:语言层的并发、系统层的并发量、部署层的高可用

并发
多个任务在时间上交替推进,单核也能做到,重点是调度而不是同时进行
并行
多个任务在同一时刻真正一起执行,依赖多核或多机资源,是物理事实
高并发
同一时间涌入的请求规模很大,描述的是系统承受的压力,不是代码写法
高可用
部分组件出故障时服务仍能继续提供,靠冗余和切换实现,与流量大小无关
分布式
把系统拆到多台机器上协作,是解决规模和可用性的手段之一,本身不是目标
  • 并发是任务调度的概念,并行是执行资源的物理事实,两者在单核、多核、异步 IO 下会有不同组合;写了异步代码不代表就有并行
  • 高并发描述的是同时涌入的请求规模,落在系统层;单机开很多线程不等于扛得住并发,线程多了反而可能把内存和上下文切换拖垮
  • 高可用讲的是出故障时还能不能提供服务,属于部署与冗余层面,和并发、并行可以彼此独立存在:低流量系统同样需要高可用
  • 分布式是手段不是目的,它引入的一致性、网络分区、链路追踪代价很实在,很多小团队根本用不上,硬上只会先被运维复杂度拖垮

自查清单:你这套系统到底卡在哪一层

判断放在哪一层,别靠感觉,靠几个可观察的信号。先量单请求延迟基线,再统计单位时间的请求量,最后看故障发生的形态,三条线分开看,基本就能定位到层次。

现象更可能卡在哪层先看的动作
单个接口调用本身就慢语言层与下游依赖拆解请求内部耗时,找出慢在哪一段
平时正常,量一上来就超时系统层容量与排队看是否限流排队、共享资源是否打满
周期性整体不可用部署层可用性查健康检查、切换演练、单点依赖
跨机器数据对不上分布式一致性先确认是否真的需要拆到多机
  • 先在 接口测速(/tools/speed-test) 量一遍单请求延迟基线,判断慢是单次耗时问题还是排队问题,两者解法完全不同
  • 看错误码分布:超时、限流、连接被拒往往指向并发与容量,而周期性整体不可用更可能是可用性问题
  • 数一数共享资源:数据库连接池、锁、外部接口配额,绝大多数所谓高并发故障,实际是共享资源被打满
  • 确认团队规模与运维能力:三五人小团队上分布式部署,往往先被运维复杂度拖垮,而不是被流量拖垮

排查顺序:从下往上,别一上来就改架构

  1. 第一步:看单请求耗时把一次请求内部各段耗时打点出来,确认慢在自身逻辑还是下游依赖;慢请求堆着不放手,线程再多也是白搭。
  2. 第二步:看限流与排队检查入口有没有限流、有没有排队策略;缺少排队时并发一冲上来就是雪崩,这时候扩容只是把雪崩往后推。
  3. 第三步:看降级路径确认非核心依赖能不能降级、降级后功能是否还能用;有降级能顶住的前提下,再谈扩容才有意义。
  4. 第四步:才考虑拆分与分布式只有单机容量、可用性冗余都到瓶颈时才值得付出这份复杂度;拆之前先想清楚跨节点一致性和链路追踪怎么收。

放在 Java 语境里看:多线程只是其中一块

Java 里谈并发,容易一上来就想到线程池、锁、异步编排。这些解决的是任务怎么并发跑,属于语言与框架层,不等于系统能扛多大流量。真正决定吞吐的,常常是连接池大小、超时设置、是否阻塞等待这些更朴素的东西。

层面典型手段它不负责的事
语言与框架层线程池、锁、异步编排不决定系统整体容量上限
连接与资源层连接池、超时、队列长度不解决下游本身的能力瓶颈
部署与冗余层多实例、健康检查、切换不优化单次请求的响应速度
  • 线程池、锁、异步编排解决的是任务怎么并发跑,上线前要压测确认瓶颈是在线程、连接池还是下游接口
  • 连接池大小、超时设置、是否阻塞等待,往往比多开线程更能决定实际吞吐,调参前先量基线
  • 涉及外部 API 或中转站调用时,并发上限以服务端实际返回的限流为准,具体数字到 中转站目录(/sites) 与对应说明页核对
  • 把「我用了多线程」当成并发问题已解决,是很常见的误判,压测结果才算数

三个常见误区与对应做法

  • 把并发数当成用户数:并发是同一时刻在处理的任务量,用户总量大但请求稀疏时压力并不高,先分清再定容量目标
  • 把高可用当成加机器:没有健康检查、没有故障切换演练,机器再多也可能一起倒,冗余要配可验证的切换动作
  • 把分布式当成性能优化:单体先压测到瓶颈再拆,拆完要准备好处理跨节点一致性与链路追踪,否则问题只会从一台机器扩散到一群机器
先分清楚是任务调度问题、容量问题还是冗余问题,再决定动代码、动参数还是动架构。
下一步想验证自己这套调用到底卡在哪一层,可以先用测速工具量一遍单请求延迟基线,再去中转站目录核对各家的限流与可用性说明,用真实数字代替感觉。

常见问题

并发和并行到底怎么区分?

并发是多个任务在时间上交替推进,强调调度与切换;并行是多个任务真的在同一时刻由不同执行单元跑,强调物理资源。单核也能写出并发代码,但单核不会有真正的并行。判断时先问「同一瞬间有没有两个任务在算」,答案是有才是并行。

高并发和高可用是一回事吗?

不是。高并发说的是同时来很多请求,考验容量与排队能力;高可用说的是出故障时还能不能用,考验冗余与切换能力。一个系统可能并发能力很强但一挂就全挂,也可能流量很小但做了多活。两者要分开评估,扩容解决前者,冗余和演练解决后者。

小团队一定要上分布式吗?

不一定。分布式主要解决单机容量上限和可用性冗余,代价是一致性、调试和运维复杂度上升。如果业务量还没到单机瓶颈,先把超时、限流、降级、监控做好,收益通常更大。等到单机压测确实顶不住、或者业务要求故障不中断时,再考虑拆。

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