延迟数据速算表
2010年,Jeff Dean在Google内部做了一次技术分享,标题叫"数字能说话"(Numbers Everyone Should Know)。
他给出了一组数据,在整个业界引发了轰动。
这组数据告诉我们:在计算机世界里,毫秒和纳秒的差距,比你想象的大一万倍。
【架构权衡】
系统设计中最大的误区,就是把CPU运算、内存访问、网络传输、磁盘IO当成一回事。一个P6工程师能在1秒内完成的事,一个P7工程师能看出它需要1小时——差距就在这组数字里。
一、经典延迟数据 🔴
1.1 Jeff Dean 的经典数据(2009)
这些数字在2009年就已经是业界共识,至今依然有效:
1.2 2024年更新版
硬件在进步,但这组相对量级没有变:
核心结论:
- L1缓存比内存快 150倍
- 内存比SSD快 100倍
- SSD比磁盘快 1000倍
- 磁盘比跨机房网络快 5000倍
1.3 量化理解
把这组数字翻译成人类能感知的尺度:
面试中最常见的错误,是把"磁盘IO"和"数据库查询"当成快操作。很多候选人设计方案时写"用MySQL查询",但没考虑到一次磁盘寻道需要10ms,一次普通查询可能涉及十几次磁盘IO。1万次查询就是100秒。这才是系统慢的真正原因。
二、QPS与延迟的关系 🔴
2.1 Little定律
关键洞察:同样的QPS,响应时间越短,需要的并发连接数越少,系统压力越小。
2.2 线程池估算
2.3 真实案例
面试官:你的接口响应时间是200ms,但MySQL查询本身只要10ms,剩下的时间花在哪了?
候选人:好的,我分析一下200ms的构成:
- 网络传输(双向):20ms
- Tomcat线程排队:30ms
- 数据库连接获取:5ms
- MySQL查询:10ms
- 结果集序列化:10ms
- 业务逻辑处理:15ms
- 缓存查询:5ms
- GC暂停:20ms
- 其他开销:85ms
面试官:等等,GC暂停85ms?不可能这么高吧?
候选人:是的,这是我之前踩的坑。生产环境Full GC时最长停顿85ms,主要原因是堆内存设置过大(16G)且对象年龄结构不合理。后来改成4G + G1GC,Full GC控制在50ms以内了。
面试官:那怎么优化到50ms以内?
候选人:进一步优化后,延迟构成变为:
- 网络:20ms(无法优化)
- 线程排队:10ms(加到32线程)
- MySQL:10ms(加索引)
- 缓存:5ms(缩短key长度)
- GC:15ms(G1调优 + 对象池化)
- 其他:40ms(优化锁、无锁化)
实际P99控制在100ms以内。
面试官:很好。
【面试官心理】
能说出延迟分解的候选人,已经超过了90%的竞争者。能说出GC停顿具体数字的候选人,说明他真正在生产环境排查过问题。能给出优化前后对比数据的候选人,基本是P7以上水平。这道题考的不是你知道多少数字,而是你有没有"量化分析"的习惯。
三、各层存储速度对比 🟡
3.1 存储层次图
3.2 各存储层适用场景
3.3 缓存层级设计
四、网络延迟速算 🟡
4.1 机房内vs跨机房
4.2 常用服务的延迟
4.3 一致性级别与延迟
五、面试高频追问 🟡
5.1 为什么L1缓存比内存快150倍?
考察点:硬件原理 + 实际影响
标准回答:
L1缓存是直接集成在CPU核心内部的,访问路径只有不到1mm,晶体管数量少,延迟极低。
内存需要通过DDR总线访问,要经过内存控制器、北桥(部分CPU已集成),物理距离至少10cm以上,延迟本质上是光速限制。
实际影响:一个未命中L1的请求,CPU会空转14个时钟周期等待L2或内存。这在高频交易系统中是不可接受的。
5.2 为什么SSD比磁盘快1000倍?
考察点:IO原理 + 选型依据
标准回答:
机械磁盘的延迟主要来自两部分:寻道时间(平均5-10ms)和旋转延迟(平均4ms),一次随机IO需要15ms。
SSD没有机械结构,基于NAND Flash的电子读写,延迟只有0.1ms级别,且随机读写和顺序读写性能接近。
但SSD有写入寿命(SLC约10万次,QLC约1000次)和读放大问题,不适合写入极其频繁的场景。
5.3 跨机房网络延迟怎么优化?
考察点:架构设计 + 工程权衡
标准回答:
跨机房延迟的主要优化策略:
一是读写分离:写请求发到主机房,读请求就近读取本地副本(最终一致)。
二是异地多活:每个机房都是完整的业务单元,流量就近接入,通过消息同步保证数据最终一致。
三是CDN加速:静态资源部署CDN,用户请求被路由到最近节点,避免跨机房。
四是批量合并:将多个小请求合并为一个大请求,减少RTT次数。
五是连接复用:HTTP/2或gRPC长连接,避免每次请求都建立新连接。
面试中能说出"光速限制"这个概念的候选人,通常会让面试官眼前一亮。这说明你不仅会用工具,还理解工具为什么慢。但在实际工作中,过度优化光速限制是徒劳的——你更应该优化的是代码逻辑、索引设计、缓存策略这些你能控制的东西。
六、速算卡片 🟢
6.1 面试必备数字
6.2 决策速查表
6.3 性能问题自检流程
七、真实面试回放 🟡
面试官:你设计了一个接口,平均响应时间100ms,P99是500ms。怎么优化?
候选人(小林):分三步分析:
第一步,确定瓶颈在哪。P99是500ms,说明有5%的请求耗时超过500ms,这通常意味着:
- GC停顿:JVM堆设置过大导致Full GC时间过长
- 数据库慢查询:缺索引或大表扫描
- 外部依赖超时:第三方API不稳定
第二步,收集数据。我会让运维打开Grafana看板,看:
- GC频率和时长(如果GC超过50ms,说明堆太大或对象分配太快)
- MySQL慢查询日志(如果有超过100ms的查询,需要优化索引)
- 外部API的P99(如果是第三方问题,需要加超时和降级)
第三步,针对性优化:
- 如果是GC问题:减小堆到4G,用G1GC,目标GC时间
<50ms- 如果是数据库问题:加索引或引入本地缓存
- 如果是外部依赖:加超时熔断,服务降级
面试官:如果这些都排除了,还是很慢呢?
小林:那就看是不是热点锁问题。Java里synchronized锁竞争、数据库连接池耗尽、Redis连接池耗尽都会导致请求排队。可以加Pinpoint或Arthas看线程状态。
如果是锁问题:用Redis分布式锁替代synchronized,或者拆分锁粒度 如果是连接池问题:调大连接池,或者用异步HTTP客户端
面试官:你能给个具体数字吗?100ms的接口,你能优化到什么程度?
小林:如果是计算密集型接口,优化到10ms以内是可能的(CPU本地计算+无锁)。
如果是IO密集型(依赖数据库和缓存),P99最低能到30-50ms,因为数据库查询本身就要10-20ms。
100ms优化到50ms,我一般分三步走:
- 加本地缓存(命中率80%),减少80%的数据库查询,P99降为50ms
- 加Redis缓存(命中率90%),减少90%的数据库查询,P99降为30ms
- 加异步化(非关键路径异步处理),用户体验层面P99降为20ms
面试官:可以。
【面试官手记】
小林这场面试的亮点在于两点:第一,能说出P99的含义(5%请求耗时超过500ms),说明理解统计学含义;第二,优化路径清晰(本地缓存→Redis缓存→异步化),每一步都有量化预期。这正是面试官想听到的——不是背书,而是有逻辑的思考过程。
延迟数字不是用来背的,是用来感知系统瓶颈的。
当你看到"100ms"这个数字时,脑子里应该立刻浮现:这是1次跨机房RTT,还是10次内存访问,还是1次磁盘IO?
有了这个感知,你设计方案时就不会乱来:不会用磁盘存热点数据,不会用同步调用跨机房服务,不会忽略本地缓存的价值。
记住:在计算机世界里,知道什么快什么慢,比知道怎么用更重要。