大厂采用漏斗式拆解法搭建秒杀系统,可将十万瞬时流量层层过滤至几十个请求。
CDN 前置缓存:将网页图片等静态资源部署在离用户最近的 CDN 节点,避免请求直达主服务器。
前端流量拦截:对用户点击请求按比例丢弃部分,弹出系统繁忙提示,将十万请求缩减至五万。
网关规则过滤:Nginx 网关依据黑名单和限流规则,拦截恶意刷单请求,仅放行一万个请求。
Redis 缓存分流:进入业务服务的请求先读取 Redis 内存缓存的商品信息,不直接访问数据库。
最终流量缩量:经多层过滤后,仅几十个请求可执行扣库存操作,避免数据库崩溃死锁。
秒杀系统的核心逻辑是通过层层拦截过滤,而非硬刚瞬时高并发流量。
Java 单机环境下账户转账存在五个易踩的面试核心坑点。
事务范围控制:需将 A 账户扣款、B 账户加款纳入同一事务,显式指定 rollbackFor 为 Exception.class,避免默认仅回滚 RuntimeException 的遗漏问题,确保操作要么全成功要么全回滚。
余额并发校验:禁止 Java 层先查余额再扣款,需在数据库层面用条件更新语句(where balance >= amount)实现扣款,通过 Java 层判断影响行数确认结果,天然防范并发超扣。
死锁规避处理:针对 A 转 B、B 转 A 的交叉转账场景,按账户 id 排序,统一先锁 id 小的账户,再锁 id 大的账户,消除死锁产生的条件。
幂等性保障:每笔转账携带唯一 requestId,服务端先查流水表判断是否已处理,同时给 requestId 字段加唯一索引,防范网络重试导致的重复扣款。
转账流水记录:每笔转账需落库记录转账双方、金额、操作时间及结果,作为生产环境对账排查的依据。
视频提及后续将讲解跨库转账的分布式事务方案选择。
面试官通过订单接口场景题,考察四年经验后端开发者对事务边界与系统稳定性的理解。
场景问题抛出:设定订单创建接口包含扣库存、生成订单、加积分、调用外部营销接口发优惠券四个操作,开发者用 @Transactional 注解将所有操作包入事务后,因外部营销接口响应从 50 毫秒涨到 2 秒,导致订单接口响应飙升、数据库连接池被打满、所有订单无法创建。
核心原因拆解:外部慢调用拉长事务时间,事务持有的数据库锁无法及时释放,占用的数据库连接无法回收,最终耗尽连接池资源。
三层防御方案:缩小事务边界,仅将扣库存、生成订单等核心数据库操作包入事务,事务提交后再调用外部接口,失败则事后补偿;采用异步化节流,通过消息队列异步处理非核心业务,用本地事件表保证最终一致性,与产品沟通接受短暂不一致;搭建监控与熔断机制,监控事务耗时、连接池状态并预警,外部依赖异常时自动熔断降级,优先保障核心业务。
该面试题重点考察开发者从使用事务到设计事务边界的工程思维。
面试官结合后端面试场景,详解缓存与数据库一致性的三层防御方案。
面试官面试一位自称精通缓存设计、有高并发经验的五年后端开发者,先后抛出缓存一致性基础题、大促脏数据场景题及并发重试场景题,开发者无法完整作答,由此引出系统防御方案。
更新策略保障:需确保删缓存操作可靠,可通过数据库事务结合本地消息表,或订阅 binlog 触发删除,同时设置幂等重试机制。
并发读写控制:针对并发下旧数据写回问题,可采用延迟双删、强制读主库,或引入版本号 / CAS 校验拒绝旧数据。
最终一致性兜底:设计定期对账修复系统,比对库与缓存关键数据;同时设置合理缓存 TTL,作为最后恢复防线。
该问题核心考察开发者的工程化系统思维能力。
腾讯 Java 四面中缓存与数据库双写一致性问题的回答需覆盖操作类型与策略选择两个核心维度。
- 操作类型分析:新增操作不会导致一致性问题;更新操作直接双写缓存与 MySQL 易引发数据不一致;删除操作需关注执行顺序。
- 策略对比:先更新 Redis 再更新 MySQL 会因 DB 异常导致缓存脏数据;先更新 DB 再更新 Redis 存在缓存更新失败风险;删除策略(先删缓存或先更 DB)是更优方向,但需处理并发场景。
- 推荐方案:延时双删策略(淘汰缓存→更新 DB→休眠后再次淘汰缓存)可降低脏数据持续时间,休眠时长需结合业务逻辑耗时设定。
两种常见实现方式
1. 固定延迟删除(线程池 / 定时任务)
- 流程:
-
- 删除缓存 → 2. 更新数据库 → 3. 等待固定时间 → 4. 再次删除缓存。
- 优点:实现简单,无需额外中间件。
- 缺点:延迟时间难以精准预估,可能导致脏数据或系统开销过大。
2. 基于消息队列的异步删除(MQ)
- 流程:
-
- 删除缓存 → 2. 更新数据库 → 3. 发送延迟消息到 MQ → 4. 消费者接收到消息后删除缓存。
- 优点:支持动态调整延迟时间,可靠性高(MQ 保证消息投递)。
- 缺点:需引入消息队列(如 Kafka、RocketMQ),增加系统复杂度。
关键注意事项
- 延迟时间设置:需结合业务逻辑耗时测试调整,避免过短(覆盖不到脏数据)或过长(浪费资源)。
- 重试机制:若第二次删除失败,需添加重试逻辑(如最多尝试 3 次)。
- 降级方案:若延迟任务提交失败,可直接同步删除缓存或记录日志后续处理。
- 适用场景:适合读多写少、对一致性要求较高但允许短暂不一致的场景(如社交动态、余额变动)。
面试官通过真实大促事故案例,考察 4 年后端开发者对消息队列消费性能瓶颈的认知与解决能力。
事故核心表现:双十一物流系统发货延迟 6 小时,RocketMQ 某 Topic 积压 5000 万条消息;设置 8 个消费线程,但 TPS 仅几百。
瓶颈根因定位:每条消息需调用运费接口,大促时接口响应从 20ms 增至 2 秒;消费线程同步等待接口返回,线程再多也只是排队,吞吐量受限于最慢的外部接口环节。
三层解决能力:
根因定位层:用 Arthas 的 trace 命令监控耗时分布,jstack 查看线程状态,通过 RocketMQ 控制台看消息延迟指标,确认瓶颈在下游接口。
事前防控层:压测模拟下游真实响应延迟,设置 P99 处理耗时告警,定期做消息积压混沌演练。
代码防御层:异步化外部调用、批量并行处理、缓存接口结果、设置消费降级。
该案例考察开发者对消息队列端到端性能瓶颈的深度理解,而非基础操作能力。