当删除请求量达到10k QPS时,如何保证亚秒级延迟?
解读
面试官把场景限定在“删除”这一写操作,且并发高达10k QPS,同时要求P99 延迟 <1 s。国内互联网场景下,这类需求常见于:
- 社交平台内容审核通过后批量清理缓存
- 电商大促时违规商品下架
- 云盘秒级清空回收站
删除链路往往要同步做物理删除、索引更新、缓存失效、搜索引擎踢词、风控日志落盘等多件事,任何一环放大延迟都会导致超时。因此考点是:在高并发写、数据一致性、可观测性与成本控制之间给出可落地的国内架构方案,并能自证P99<1 s。
知识点
- 分片与热点隔离:按user_id 哈希分片+热点 key 单独队列,避免单台机成为瓶颈。
- 异步化与最终一致:把强同步路径缩到最短,非强一致步骤丢给可靠消息队列(RocketMQ/RabbitMQ),利用批量 ACK降低毛刺。
- 缓存双 key 策略:逻辑删除+懒物理删除;先给缓存置短 TTL 墓碑值,再异步刷 DB,读链路永不穿透失效主键。
- 批量提交与管道:MySQL 采用批量 delete + 分段 limit + 自旋索引;Redis 用UNLINK非阻塞删除+Pipeline打包。
- GC 与内核调优:Linux 开启multi-queue SSD+noop 调度器;JVM 用ZGC并把最大停顿目标设为 50 ms,防止 Full GC 拖尾。
- 限流与降级:Sentinel配置关联限流——当缓存失效 QPS>12k 时,降级为先标记后删除,保证核心链路不崩。
- 可观测:P99 延迟通过Prometheus+Grafana秒级拉取,TraceId全链路透传,SLS实时告警>800 ms 的慢请求。
答案
“我在上一家公司做过 12k QPS 删除场景,P99 稳定在 600 ms 以内,核心思路是把同步路径做短,把异步路径做稳:
- 接入层:OpenResty+Lua做一致性哈希分片,把 10k QPS 均摊到 20 台 API 网关,单节点 500 QPS,CPU 占用 <30%。
- 缓存层:
- 采用Redis 6.2 集群,单分片 8 线程 IO,开启UNLINK非阻塞删除;
- 对热点 key 再拆逻辑桶,每个桶限制 1k QPS,超量时返回 202 Accepted,客户端指数退避重试。
- 存储层:
- MySQL 8.0 分库分表按user_id 取模 64 库,单库 150 QPS;
- 删除 SQL 采用批量 delete … where id in (…) 每次 200 行,二级索引用覆盖索引避免回表;
- 开启binlog_group_commit与组提交,把磁盘 fsync 次数降到 1/10。
- 异步链路:
- 写RocketMQ顺序消息,单 Topic 20 队列,批量攒 5 ms或者 512 条提交一次;
- 下游搜索、风控、日志等系统并行消费,失败时重试队列+死信队列保证最终一致。
- 观测与兜底:
- Prometheus 每 5 s 拉一次,P99>800 ms 立即短信告警;
- 若缓存节点失连,Sentinel 在 50 ms 内触发降级逻辑:只写标记表,后台Cron 每 500 ms 批量删除,保证可用性。”
拓展思考
- 如果业务要求强一致而非最终一致,可把缓存与 DB 的删除放在同一分布式事务:用Seata AT 模式或NewSQL(如TiDB)的Percolator 事务,但要接受吞吐下降 40% 的代价。
- 当数据量达到千亿级,可引入分层存储:热数据在Redis+SSD,冷数据下沉到S3 类对象存储,删除时仅标记元数据,物理空间回收由后台GC Agent 在低峰期扫描,以节省 IOPS。
- 未来演进可让Agent 系统自主调参:通过强化学习实时观测P99、CPU、IO 三维指标,动态调整批量大小、线程数与限流阈值,实现延迟自优化,把 P99 压到400 ms 以内而无需人工干预。