携程 Java 秋招一面:缓存延迟、订单耗时与系统可靠性
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 项目中怎样使用 Redis,如何保证缓存与数据库一致?
- Canal 同步的 500 毫秒延迟来自哪里,如何优化?
- 需要缓存的数据特别大时怎么办?
- 创建订单耗时很长时,如何定位和处理?
- 下游接口无法降级时怎么办?
- MySQL 有哪些隔离级别,哪些场景会让索引无法有效使用?
- synchronized 和 ReentrantLock 分别做什么,有什么区别?
- synchronized 能锁 String 和 Long 对象吗?
- 类加载有哪些阶段?
- 如何计算一个对象的大小?
- 如何创建类的实例?
- 如何设计一个可靠的系统?
- 项目里如何使用熔断,何时触发,何时恢复?
《参考解析》
500 毫秒先拆成几段
从数据库提交,到变更记录被读取、排队、消费,再到缓存写入,每段都可能引入等待。用同一条记录的时间点计算各段延迟,再检查拉取批次、队列积压、消费速度与网络耗时。若系统时钟不同步,跨机器时间差也可能失真。没有测量前,不能把这 500 毫秒直接归因于 Canal。
订单慢不等于全改异步
先区分数据库锁等待、慢 SQL、外部接口和应用排队。订单是否成立必须依赖的步骤,应有清晰的成功条件;通知等允许延后的工作可以异步执行。关键下游不可用且没有合法降级结果时,可以限流或明确失败,不能返回虚假的下单成功。重试仍应复用同一个业务请求标识。
锁对象要稳定且归自己管理
synchronized 的监视器对象可以是 String 或 Long,但字符串常量可能被其他代码共享,装箱对象也可能来自缓存;给变量重新赋值又可能换掉锁对象。通常用私有且不再替换的锁对象,确保竞争线程锁住的是同一个实例。
熔断恢复需要少量探测
熔断条件应基于时间窗口中的请求量、失败比例或慢请求情况,避免一两次失败就切断服务。打开后等待一定时间,再放行少量请求判断依赖是否恢复;探测失败继续保持熔断。限流、超时和并发隔离也要一起考虑,防止大量等待把调用方拖垮。