订单超时取消的设计方案差异能直接反映程序员的实战经验层级。
暴力轮询方案:新手常用 Quartz 或 Spring Schedule 定时扫全表检查未支付订单,高并发下会导致数据库 CPU 飙升、时效性差、锁竞争激烈。
延迟消息方案:下单时发 30 分钟延迟消息,消费者收到后检查订单状态执行取消;进阶用阶梯式检查(如 30 秒→1 分钟→5 分钟),尽早释放已支付订单,但会增加 MQ 消息量。
事务消息方案:下单发送事务消息,本地创建订单后返回 unknown,MQ 定期调用 checkLocalTransaction 回查;回查时若订单已支付则 rollback,未支付且未超时则继续返回 unknown,超时未支付则 commit 触发取消。
第三方确认环节:取消订单前需主动查询微信、支付宝等第三方支付平台的订单状态,避免回调延迟或丢失导致的支付成功但订单被取消的事故。
视频通过方案演进映射程序员从硬刚实现到全局视野的成长路径。
秒杀系统设计需通过多层拦截分散高并发压力,而非仅依赖 Redis 扣库存。
流量削峰:前端页面静态化并推至 CDN,活动前预加载;秒杀按钮置灰防止提前点击;Nginx 层设置连接数和 QPS 上限做兜底保护。
Redis 预扣库存:秒杀前将库存预加载到 Redis,用户请求通过 Lua 脚本原子性判断并扣减库存,扣减成功才进入后续流程。
异步下单:Redis 扣库存成功后,将请求发送至消息队列异步消费,完成订单创建和数据库库存扣减,用户端轮询订单状态。
数据库兜底:数据库写库存时加乐观锁,若更新函数为 0 则回滚,防止超卖。
防刷限流:同一用户 ID 仅允许成功一次,对同一 IP 进行限流,引入人机验证拦截高风险请求。
活动后清理:秒杀结束后 Redis 库存与数据库对账,未完成 MQ 消息设置超时处理机制。这套设计的核心是用多层拦截减少请求量,用缓存承担并发,用 MQ 异步化写操作,用乐观锁保证一致性。
蚂蚁金服二面中,仅会用 jstack 排查死锁但无法给出预防方案的候选人会直接被淘汰。
事故现场:支付系统转账时,用户 A 转 B 与用户 B 转 A 的请求同时触发,系统先锁转出账户再锁转入账户,导致两个请求互相等待对方持有的锁,程序卡死。
排查方法:使用 jstack 命令打印线程堆栈,通过 Deadlock 关键字定位死锁线程及锁持有关系。
死锁条件:需满足互斥、占有并等待、不可抢占、循环等待四个必要条件,破坏任一条件即可预防死锁。
预防方案:固定加锁顺序(按账户 ID 从小到大加锁)、使用 tryLock 超时机制、减少锁的持有时间。
生产建议:转账前检测账户状态、缩小加锁范围、设置超时机制、配置线程等待监控告警。
视频强调,死锁问题的核心考察点是系统设计思维,而非仅工具使用能力。
视频通过三个面试场景,呈现了不同数据类型下 TopK 问题的最优解法选择逻辑。
核心考点:视频以 "10 亿个数字找最大 100 个""10 亿个 URL 找访问频率最高 100 个""10 亿个手机号找重复最多 100 个" 三个场景,展示了分治、堆排序、位图法、桶排序等算法的应用边界。
关键细节:面试官重点考察数据倾斜处理(二次哈希、一致性哈希)、算法时间复杂度(小顶堆 O (NlogK))、内存优化方案(位图法仅需 512MB 处理 32 位整数)。
面试技巧:视频强调需根据数据特征(整数 / 字符串 / 重复率)选择算法,而非仅背诵 "小顶堆" 标准答案。
视频最后总结了不同场景下的 TopK 解决方案,包括内存足够时用堆排序、内存不足时分治归并、整数场景用位图法等。
synchronized和reentrantlock区别? 仅回答关键字与类、隐式与显式锁的区别会暴露知识浅薄、缺乏深度思考等问题,导致面试失败。
相同点:两者核心功能一致,都实现互斥锁,支持可重入性,保证内存可见性。
实现层面:synchronized 是 JVM 层面的内置锁,由底层机制保障;ReentrantLock 是 API 层面的工具类锁,功能强大且可定制性高。
灵活性:synchronized 功能固定,ReentrantLock 支持可中断获取、超时获取、非阻塞获取、公平锁和多个条件变量。
性能:JDK1.6 前 synchronized 性能差,之后 JVM 引入偏向锁、轻量级锁等优化,竞争不激烈时性能更优,性能不再是选择的决定性因素。
选择原则:优先使用 synchronized,因其简单安全;仅在需要高级功能时考虑 ReentrantLock。
视频最后提出问题,询问 ReentrantLock 的可重入性实现方式,以及它与 synchronized 的可重入性实现原理的不同。
实战中 Redis 与 MySQL 数据一致性问题的核心是追求最终一致性而非强一致性。
核心结论:分布式环境下强一致性代价过高,需将数据不一致的时间窗口缩至最短。
常用方案:先更新数据库再删除缓存,通过重试机制或消息队列解决删除失败问题。
兜底方案:延迟双删,先删缓存再更新数据库,异步延迟后再次删除缓存,解决并发导致的脏数据问题。
最稳方案:订阅 binlog 异步删缓存,通过 Canal 等工具监听 MySQL 的 binlog,数据变化时异步删除缓存,与业务代码解耦。
根据业务能容忍的时间窗口选择方案,避开脏数据即可应对面试问题。