Java面试实战:MySQL高并发优化与分布式容灾设计 1. Java实习模拟面试实录博云科技二面技术要点解析上周刚结束博云科技的二面面试官对MySQL高并发、设计原则和分布式容灾的考察相当深入。作为经历过5家互联网公司技术面试的老鸟这次面试的问题设计确实很有代表性。整理出这场技术拷问的核心要点和应对思路给准备Java实习面试的同学参考。这场面试持续了约90分钟全程围绕高并发系统下的MySQL优化展开穿插考察设计模式和分布式容灾方案。面试官明显在考察候选人是否具备从单机到分布式系统的完整知识体系以及面对复杂场景时的设计权衡能力。2. MySQL高并发场景下的优化实战2.1 索引优化与锁机制当面试官问如何解决秒杀场景下的超卖问题时我首先分析了InnoDB的锁机制-- 悲观锁实现方案 BEGIN; SELECT stock FROM products WHERE id1001 FOR UPDATE; UPDATE products SET stockstock-1 WHERE id1001; COMMIT;注意FOR UPDATE会在事务期间持有排他锁要控制事务执行时间避免长事务更优的方案是使用乐观锁配合版本号控制UPDATE products SET stockstock-1, versionversion1 WHERE id1001 AND version当前版本实测发现当并发量超过5000QPS时乐观锁的重试机制会导致数据库连接耗尽。这时需要引入Redis预减库存异步扣减的二级缓冲方案。2.2 分库分表策略当单表数据量达到千万级时面试官追问了分片策略的选择水平分片按user_id哈希分到不同库垂直分片将商品基础信息与详情分离时间分片历史订单归档到单独表推荐使用ShardingSphere实现分片路由配置示例spring: shardingsphere: datasource: names: ds0,ds1 sharding: tables: t_order: actual-data-nodes: ds$-{0..1}.t_order_$-{0..15} table-strategy: inline: sharding-column: order_id algorithm-expression: t_order_$-{order_id % 16}2.3 连接池优化参数在高并发场景下DBCP连接池的关键配置参数推荐值说明maxTotalCPU核心数*2 磁盘数避免连接过多导致线程切换开销maxIdlemaxTotal的50%维持合理空闲连接minEvictableIdleTimeMillis3000005分钟空闲回收testWhileIdletrue定期检测连接有效性3. 设计原则的工程实践3.1 电商系统中的设计模式面试官要求举例说明装饰器模式的实际应用。我以订单价格计算为例public interface PriceCalculator { BigDecimal calculate(Order order); } public class BasePrice implements PriceCalculator { // 基础价格计算 } public class CouponDecorator implements PriceCalculator { private PriceCalculator delegate; public BigDecimal calculate(Order order) { BigDecimal price delegate.calculate(order); return price.subtract(order.getCouponAmount()); } } // 使用组合构建复杂计算逻辑 PriceCalculator calculator new ShippingFeeDecorator( new TaxDecorator( new CouponDecorator( new BasePrice())));3.2 接口设计的SOLID原则当被问到如何设计支付接口时我强调了单一职责支付接口只处理支付不包含风控、通知等逻辑开闭原则通过PaymentStrategy接口支持扩展新支付方式依赖倒置高层模块依赖PaymentService抽象public interface PaymentService { PaymentResult pay(PaymentRequest request); } public class AlipayAdapter implements PaymentService { // 实现支付宝支付 } public class WechatPayAdapter implements PaymentService { // 实现微信支付 }4. 分布式容灾方案设计4.1 MySQL主从切换策略面试官特别关注了主库宕机时的处理流程监控系统检测到主库不可用连续3次心跳超时触发选举协议从从库中选择新主库基于GTID位置通知所有客户端连接切换到新主库原主库恢复后自动降级为从库关键配置参数# MHA配置示例 manager_workdir/var/log/masterha/app1 manager_log/var/log/masterha/app1/manager.log master_binlog_dir/var/lib/mysql usermha passwordmhapass ping_interval34.2 分布式事务补偿机制针对支付成功但库存未扣减的场景我介绍了TCC模式实现Try阶段预留资源冻结库存Confirm阶段确认执行业务扣减库存Cancel阶段取消预留释放库存public interface InventoryTccService { Transactional boolean prepare(String productId, int count); Transactional boolean commit(String productId, int count); Transactional boolean cancel(String productId, int count); }5. 高频问题与避坑指南5.1 MySQL死锁排查实录现场演示了如何分析死锁日志LATEST DETECTED DEADLOCK ------------------------ 2023-08-20 14:23:11 *** (1) TRANSACTION: TRANSACTION 1823, ACTIVE 0 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 15, OS thread handle 1397, query id 224 localhost root updating UPDATE account SET balancebalance-100 WHERE user_id1 *** (1) HOLDS THE LOCK(S): RECORD LOCKS space id 58 page no 3 n bits 72 index PRIMARY of table test.account解决方案统一SQL操作顺序先操作user_id小的记录降低事务隔离级别为READ COMMITTED对热点数据采用队列串行化处理5.2 连接池泄露排查技巧分享一个实际案例应用夜间出现连接池耗尽报警。通过以下步骤定位获取Druid监控数据SELECT * FROM druid_datasource WHERE date2023-08-20分析连接持有时间分布awk {print $4} connection.log | sort | uniq -c最终发现是PDF导出功能未关闭ResultSet。添加资源自动回收后解决try (Connection conn dataSource.getConnection(); Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(sql)) { // 业务逻辑 }这场面试给我的启发是企业级开发不仅要求掌握技术点更需要理解技术决策背后的trade-off。比如选择分库分表策略时要考虑业务增长模式和数据访问特点。在准备面试时建议多思考为什么用这个方案而不是死记解决方案。