互联网大厂Java面试实录电商场景下的技术深度对话与答案解析场景设定面试官资深架构师负责电商平台核心系统求职者谢飞机3年Java开发经验业务场景大型电商平台日均订单量100万用户规模5000万第一轮面试基础技术与并发处理问题1电商平台在秒杀活动中如何保证数据一致性面试官我们平台即将进行双11秒杀活动预计并发量达到10万QPS如何保证库存数据的一致性谢飞机嗯...秒杀嘛我知道可以用Redis来做库存预减然后通过消息队列异步处理订单。数据库可以用乐观锁版本号控制。对了还可以用分布式锁比如Redis的RedLock。面试官具体怎么实现Redis预减库存的流程是什么谢飞机就是先在Redis里设置库存数量用户下单时先判断Redis库存如果大于0就减1然后发送消息到队列后面处理订单创建。如果Redis库存不足就直接返回失败。面试官很好那Redis预减后如果系统崩溃了怎么办如何保证最终一致性谢飞机这个...可以用定时任务定期检查Redis和数据库的差异然后进行补偿。或者用事务消息确保消息一定被消费。面试官思路是对的不过还可以考虑使用Redis的Lua脚本保证原子性以及引入消息队列的死信队列处理异常情况。问题2Spring Boot中如何实现多数据源配置面试官我们的订单系统需要同时读写主库查询只读从库Spring Boot中如何配置多数据源谢飞机可以用Spring的AbstractRoutingDataSource动态切换数据源。然后定义一个DataSourceContextHolder来存储当前数据源key。面试官具体配置步骤是什么谢飞机首先配置多个DataSource bean然后创建RoutingDataSource继承AbstractRoutingDataSource重写determineCurrentLookupKey方法。再配置AOP拦截根据方法注解或者包名来切换数据源。面试官很好那读写分离的延迟问题怎么处理谢飞机可以设置从库的延迟时间或者使用强制走主库的注解。对于实时性要求高的查询直接DataSource(master)。面试官思路清晰还可以考虑使用MyBatis的插件来实现读写分离。问题3JVM内存溢出如何排查面试官线上系统经常出现OOM你有什么排查思路谢飞机首先看日志是堆溢出还是栈溢出。然后可以用jmap导出堆内存快照用MAT工具分析。如果是栈溢出可能是因为递归太深或者线程过多。面试官具体操作步骤谢飞机jmap -dump:formatb,fileheapdump.hprof pid然后用MAT打开查看内存占用大的对象。还可以用jstack导出线程栈分析死锁或者CPU占用高的线程。面试官很好那如果内存泄漏发生在代码层面怎么定位谢飞机可以检查是否有静态集合一直持有对象或者连接池没有正确关闭。还有可能是缓存没有设置过期时间。面试官思路正确还可以考虑使用Arthas等在线诊断工具。第二轮面试微服务与分布式架构问题1电商平台微服务拆分的原则是什么面试官如果我们要把单体电商系统拆分成微服务你会怎么拆分遵循什么原则谢飞机嗯...按照业务边界拆分吧比如订单服务、商品服务、用户服务、支付服务这些。每个服务应该有自己的数据库避免跨服务直接查询数据库。面试官具体拆分策略谢飞机可以按DDD领域驱动设计每个服务负责一个业务领域。然后服务间通过API网关统一对外暴露接口。服务间调用可以用OpenFeign或者gRPC。面试官很好那服务拆分后的一致性问题怎么解决谢飞机可以用分布式事务比如Seata的AT模式。或者最终一致性通过消息队列保证数据最终同步。幂等性也很重要防止重复调用。面试官思路不错还可以考虑Saga模式处理长事务。问题2服务注册发现和负载均衡如何实现面试官微服务架构中服务注册发现和负载均衡是如何实现的谢飞机服务注册可以用Nacos或者Eureka服务启动时注册到注册中心客户端从注册中心获取服务列表。负载均衡可以用Ribbon或者Spring Cloud LoadBalancer。面试官具体配置谢飞机在application.yml里配置服务地址EnableDiscoveryClient开启服务发现。负载均衡策略有轮询、随机、权重等可以配置ribbon.NFLoadBalancerRuleClassName。面试官很好那服务雪崩怎么预防谢飞机可以用熔断器比如Hystrix或者Resilience4j。设置超时时间、重试次数还有降级策略。服务降级就是返回默认数据或者缓存数据。面试官思路正确还可以考虑使用舱壁模式隔离资源。问题3分布式事务如何保证一致性面试官订单创建时需要扣减库存、增加积分、发送通知这些操作分布在不同服务中如何保证一致性谢飞机可以用Seata的AT模式或者TCC模式。AT模式是基于本地事务的TCC需要业务方实现try、confirm、cancel方法。面试官具体实现方式谢飞机Seata的话需要定义全局事务ID各个服务作为分支事务参与。AT模式会自动记录undo和redo日志。TCC模式需要自己实现业务逻辑。面试官很好那性能问题怎么考虑谢飞机可以异步化处理比如非核心流程用消息队列异步执行。或者使用本地消息表先记录本地事务然后异步通知其他服务。面试官思路清晰还可以考虑使用最大努力通知模式。问题4API网关的作用和实现面试官微服务架构中API网关的作用是什么如何实现谢飞机API网关是统一的入口可以做路由转发、负载均衡、认证授权、限流熔断这些。可以用Spring Cloud Gateway或者Zuul。面试官具体配置谢飞机Spring Cloud Gateway可以用RouteLocator配置路由规则支持断言和过滤器。过滤器有全局过滤器和路由过滤器可以做鉴权、限流、日志记录等。面试官很好那网关的性能怎么优化谢飞机可以用Redis做限流避免网关成为瓶颈。静态资源可以直接由网关处理不需要转发到后端服务。还有可以做网关集群水平扩展。面试官思路正确还可以考虑使用响应式编程提升性能。第三轮面试高并发与性能优化问题1Redis在电商中的具体应用场景面试官Redis在电商平台中有哪些具体应用场景谢飞机可以用Redis做缓存存储商品信息、用户信息。还有秒杀时的库存预减用户登录session管理。还可以用Redis做分布式锁防止超卖。面试官具体实现谢飞机缓存可以用String、Hash、List这些数据结构。分布式锁可以用SETNX命令设置过期时间防止死锁。还可以用Redis的Pub/Sub做消息通知。面试官很好那缓存穿透、击穿、雪崩怎么处理谢飞机缓存穿透可以用布隆过滤器或者查询空值也缓存。缓存击穿可以设置互斥锁或者永不过期。缓存雪崩可以设置不同的过期时间或者集群部署。面试官思路正确还可以考虑使用本地缓存Redis多级缓存。问题2Kafka在电商中的应用面试官Kafka在电商平台中如何应用谢飞机可以用Kafka做异步处理比如订单创建后发送消息到队列然后异步处理物流、通知、统计这些。还可以用Kafka做日志收集或者实时数据统计。面试官具体架构设计谢飞机生产者就是业务系统消费者可以有不同的消费组处理不同的业务。比如订单处理组、物流处理组、统计组。还可以用Kafka Streams做实时计算。面试官很好那消息积压怎么处理谢飞机可以增加消费者实例水平扩展。或者优化消费逻辑批量处理。还可以设置重试机制处理异常消息。面试官思路清晰还可以考虑使用死信队列处理异常。问题3MySQL性能优化手段面试官订单表的查询性能很差有哪些优化手段谢飞机可以加索引比如订单状态、用户ID、创建时间这些字段。还有分库分表按用户ID或者时间分片。查询优化避免SELECT *只查询需要的字段。面试官具体操作谢飞机索引要选在经常查询和排序的字段上避免索引失效。分库分表可以用Sharding-JDBC或者自己实现路由逻辑。慢查询可以用EXPLAIN分析执行计划。面试官很好那大事务怎么优化谢飞机可以把大事务拆成小事务或者异步处理。减少事务中的数据操作量及时提交事务。还有可以使用读写分离查询走从库。面试官思路正确还可以考虑使用数据库连接池优化。面试官总结面试官谢飞机今天我们聊了很多电商场景下的技术问题包括并发处理、微服务架构、高并发优化等。你对基础技术掌握得还不错但在分布式事务、性能优化深度方面还需要加强。我们会综合评估有消息会通知你。谢飞机谢谢面试官我会继续学习期待有机会加入贵公司。详细答案解析问题1秒杀活动数据一致性解决方案业务场景双11秒杀活动10万QPS并发保证库存不超卖技术方案Redis预减库存使用Redis的INCR原子操作预减库存// Lua脚本保证原子性 String script if redis.call(get, KEYS[1]) tonumber(ARGV[1]) then return redis.call(decrby, KEYS[1], ARGV[2]) else return 0 end; Long result (Long) redisTemplate.execute(new DefaultRedisScript(script, Long.class), Arrays.asList(seckill_stock: productId), String.valueOf(1));消息队列异步处理使用RabbitMQ/Kafka处理订单创建RabbitListener(queues seckill.order.queue) public void handleOrder(Order order) { // 创建订单逻辑 // 库存最终扣减 }数据库最终一致性使用乐观锁Update(UPDATE product SET stock stock - 1, version version 1 WHERE id #{id} AND version #{version}) int reduceStock(Param(id) Long id, Param(version) Integer version);监控与补偿定时任务检查Redis和数据库差异问题2Spring Boot多数据源配置业务场景订单系统读写分离主库写从库读技术方案配置多个DataSourceConfiguration public class DataSourceConfig { Bean(name masterDataSource) Primary public DataSource masterDataSource() { return DataSourceBuilder.create().url(jdbc:mysql://master:3306/db).build(); } Bean(name slaveDataSource) public DataSource slaveDataSource() { return DataSourceBuilder.create().url(jdbc:mysql://slave:3306/db).build(); } }动态数据源切换public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }AOP切面切换Around(annotation(dataSource)) public Object around(ProceedingJoinPoint point, DataSource dataSource) throws Throwable { DataSourceContextHolder.setDataSourceType(dataSource.value()); try { return point.proceed(); } finally { DataSourceContextHolder.clearDataSourceType(); } }问题3JVM内存溢出排查业务场景线上系统频繁出现OOM排查步骤分析日志确定是Heap OOM还是Stack Overflow生成堆内存快照jmap -dump:formatb,fileheapdump.hprof pid分析内存对象使用MAT工具查看内存占用大的对象线程栈分析jstack -l pid thread_dump.txt在线诊断使用Arthas# 查看内存信息 memory # 查看类加载信息 classloader # 查看对象内存占用 jvm --memory问题4微服务拆分原则业务场景单体电商系统拆分为微服务拆分原则单一职责原则每个服务负责一个明确的业务领域DDD领域驱动设计按限界上下文拆分数据自治每个服务拥有自己的数据库接口设计RESTful API或gRPC拆分示例订单服务订单创建、查询、取消商品服务商品管理、库存管理用户服务用户注册、登录、个人信息支付服务支付处理、退款一致性解决方案Seata AT模式GlobalTransactional public void createOrder(Order order) { // 订单创建 // 库存扣减 // 积分增加 }最终一致性消息队列保证问题5分布式事务业务场景跨服务事务保证一致性技术方案Seata AT模式GlobalTransactional(timeoutMills 300000, name create-order) public void createOrder(OrderDTO orderDTO) { // 1. 创建订单 orderService.createOrder(orderDTO); // 2. 扣减库存 storageService.reduceStock(orderDTO.getProductId(), orderDTO.getQuantity()); // 3. 增加积分 pointService.addPoints(orderDTO.getUserId(), orderDTO.getAmount()); }TCC模式TccTry public void tryCreateOrder(OrderDTO orderDTO) { // 预检查 // 预占资源 } TccConfirm public void confirmCreateOrder(OrderDTO orderDTO) { // 确认提交 } TccCancel public void cancelCreateOrder(OrderDTO orderDTO) { // 取消操作 }本地消息表保证最终一致性问题6Redis缓存优化业务场景防止缓存穿透、击穿、雪崩技术方案缓存穿透布隆过滤器Bean public RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } // 布隆过滤器 Bean public BloomFilterString bloomFilter(RedisConnectionFactory factory) { return new RedissonBloomFilter(factory, config); }缓存击穿互斥锁public String getProduct(Long productId) { String key product: productId; String value redisTemplate.opsForValue().get(key); if (value ! null) { return value; } // 互斥锁 String lockKey lock:product: productId; try { boolean locked redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 10, TimeUnit.SECONDS); if (locked) { // 查询数据库 Product product productMapper.selectById(productId); redisTemplate.opsForValue().set(key, JSON.toJSONString(product), 30, TimeUnit.MINUTES); return JSON.toJSONString(product); } else { // 重试 Thread.sleep(100); return getProduct(productId); } } finally { redisTemplate.delete(lockKey); } }缓存雪崩随机过期时间// 设置随机过期时间 int randomExpire 30 new Random().nextInt(10); redisTemplate.opsForValue().set(key, value, randomExpire, TimeUnit.MINUTES);问题7Kafka消息队列应用业务场景订单异步处理架构设计生产者订单服务发送消息Component public class OrderProducer { Autowired private KafkaTemplateString, String kafkaTemplate; public void sendOrder(Order order) { String topic order-topic; String key order.getUserId().toString(); String value JSON.toJSONString(order); kafkaTemplate.send(topic, key, value); } }消费者多个消费组处理不同业务Component public class OrderConsumer { KafkaListener(topics order-topic, groupId order-process) public void processOrder(String message) { Order order JSON.parseObject(message, Order.class); // 处理订单逻辑 } KafkaListener(topics order-topic, groupId logistics-process) public void processLogistics(String message) { Order order JSON.parseObject(message, Order.class); // 处理物流逻辑 } }消息积压处理水平扩展消费者# application.yml spring: kafka: listener: concurrency: 5 # 增加并发度问题8MySQL性能优化业务场景订单表查询优化优化方案索引优化-- 复合索引 CREATE INDEX idx_user_status_create_time ON orders(user_id, status, create_time); -- 覆盖索引 CREATE INDEX idx_user_status_create_time_covering ON orders(user_id, status, create_time, order_id, amount);分库分表按用户ID分片ShardingTable(orders) public interface OrderMapper { Select(SELECT * FROM orders WHERE user_id #{userId} AND status #{status}) ListOrder findByUserAndStatus(Param(userId) Long userId, Param(status) Integer status); }大事务优化异步处理Transactional public void createOrder(OrderDTO orderDTO) { // 主事务创建订单 Order order createOrderMain(orderDTO); // 异步处理其他业务 asyncOrderService.asyncProcessOrder(order.getId(), orderDTO); }读写分离查询走从库DataSource(slave) public ListOrder queryOrders(Long userId) { return orderMapper.selectByUserId(userId); }通过以上详细的技术方案可以很好地解决电商平台在高并发、分布式架构下的各种技术挑战。
互联网大厂Java面试实录:电商场景下的技术深度对话与答案解析
互联网大厂Java面试实录电商场景下的技术深度对话与答案解析场景设定面试官资深架构师负责电商平台核心系统求职者谢飞机3年Java开发经验业务场景大型电商平台日均订单量100万用户规模5000万第一轮面试基础技术与并发处理问题1电商平台在秒杀活动中如何保证数据一致性面试官我们平台即将进行双11秒杀活动预计并发量达到10万QPS如何保证库存数据的一致性谢飞机嗯...秒杀嘛我知道可以用Redis来做库存预减然后通过消息队列异步处理订单。数据库可以用乐观锁版本号控制。对了还可以用分布式锁比如Redis的RedLock。面试官具体怎么实现Redis预减库存的流程是什么谢飞机就是先在Redis里设置库存数量用户下单时先判断Redis库存如果大于0就减1然后发送消息到队列后面处理订单创建。如果Redis库存不足就直接返回失败。面试官很好那Redis预减后如果系统崩溃了怎么办如何保证最终一致性谢飞机这个...可以用定时任务定期检查Redis和数据库的差异然后进行补偿。或者用事务消息确保消息一定被消费。面试官思路是对的不过还可以考虑使用Redis的Lua脚本保证原子性以及引入消息队列的死信队列处理异常情况。问题2Spring Boot中如何实现多数据源配置面试官我们的订单系统需要同时读写主库查询只读从库Spring Boot中如何配置多数据源谢飞机可以用Spring的AbstractRoutingDataSource动态切换数据源。然后定义一个DataSourceContextHolder来存储当前数据源key。面试官具体配置步骤是什么谢飞机首先配置多个DataSource bean然后创建RoutingDataSource继承AbstractRoutingDataSource重写determineCurrentLookupKey方法。再配置AOP拦截根据方法注解或者包名来切换数据源。面试官很好那读写分离的延迟问题怎么处理谢飞机可以设置从库的延迟时间或者使用强制走主库的注解。对于实时性要求高的查询直接DataSource(master)。面试官思路清晰还可以考虑使用MyBatis的插件来实现读写分离。问题3JVM内存溢出如何排查面试官线上系统经常出现OOM你有什么排查思路谢飞机首先看日志是堆溢出还是栈溢出。然后可以用jmap导出堆内存快照用MAT工具分析。如果是栈溢出可能是因为递归太深或者线程过多。面试官具体操作步骤谢飞机jmap -dump:formatb,fileheapdump.hprof pid然后用MAT打开查看内存占用大的对象。还可以用jstack导出线程栈分析死锁或者CPU占用高的线程。面试官很好那如果内存泄漏发生在代码层面怎么定位谢飞机可以检查是否有静态集合一直持有对象或者连接池没有正确关闭。还有可能是缓存没有设置过期时间。面试官思路正确还可以考虑使用Arthas等在线诊断工具。第二轮面试微服务与分布式架构问题1电商平台微服务拆分的原则是什么面试官如果我们要把单体电商系统拆分成微服务你会怎么拆分遵循什么原则谢飞机嗯...按照业务边界拆分吧比如订单服务、商品服务、用户服务、支付服务这些。每个服务应该有自己的数据库避免跨服务直接查询数据库。面试官具体拆分策略谢飞机可以按DDD领域驱动设计每个服务负责一个业务领域。然后服务间通过API网关统一对外暴露接口。服务间调用可以用OpenFeign或者gRPC。面试官很好那服务拆分后的一致性问题怎么解决谢飞机可以用分布式事务比如Seata的AT模式。或者最终一致性通过消息队列保证数据最终同步。幂等性也很重要防止重复调用。面试官思路不错还可以考虑Saga模式处理长事务。问题2服务注册发现和负载均衡如何实现面试官微服务架构中服务注册发现和负载均衡是如何实现的谢飞机服务注册可以用Nacos或者Eureka服务启动时注册到注册中心客户端从注册中心获取服务列表。负载均衡可以用Ribbon或者Spring Cloud LoadBalancer。面试官具体配置谢飞机在application.yml里配置服务地址EnableDiscoveryClient开启服务发现。负载均衡策略有轮询、随机、权重等可以配置ribbon.NFLoadBalancerRuleClassName。面试官很好那服务雪崩怎么预防谢飞机可以用熔断器比如Hystrix或者Resilience4j。设置超时时间、重试次数还有降级策略。服务降级就是返回默认数据或者缓存数据。面试官思路正确还可以考虑使用舱壁模式隔离资源。问题3分布式事务如何保证一致性面试官订单创建时需要扣减库存、增加积分、发送通知这些操作分布在不同服务中如何保证一致性谢飞机可以用Seata的AT模式或者TCC模式。AT模式是基于本地事务的TCC需要业务方实现try、confirm、cancel方法。面试官具体实现方式谢飞机Seata的话需要定义全局事务ID各个服务作为分支事务参与。AT模式会自动记录undo和redo日志。TCC模式需要自己实现业务逻辑。面试官很好那性能问题怎么考虑谢飞机可以异步化处理比如非核心流程用消息队列异步执行。或者使用本地消息表先记录本地事务然后异步通知其他服务。面试官思路清晰还可以考虑使用最大努力通知模式。问题4API网关的作用和实现面试官微服务架构中API网关的作用是什么如何实现谢飞机API网关是统一的入口可以做路由转发、负载均衡、认证授权、限流熔断这些。可以用Spring Cloud Gateway或者Zuul。面试官具体配置谢飞机Spring Cloud Gateway可以用RouteLocator配置路由规则支持断言和过滤器。过滤器有全局过滤器和路由过滤器可以做鉴权、限流、日志记录等。面试官很好那网关的性能怎么优化谢飞机可以用Redis做限流避免网关成为瓶颈。静态资源可以直接由网关处理不需要转发到后端服务。还有可以做网关集群水平扩展。面试官思路正确还可以考虑使用响应式编程提升性能。第三轮面试高并发与性能优化问题1Redis在电商中的具体应用场景面试官Redis在电商平台中有哪些具体应用场景谢飞机可以用Redis做缓存存储商品信息、用户信息。还有秒杀时的库存预减用户登录session管理。还可以用Redis做分布式锁防止超卖。面试官具体实现谢飞机缓存可以用String、Hash、List这些数据结构。分布式锁可以用SETNX命令设置过期时间防止死锁。还可以用Redis的Pub/Sub做消息通知。面试官很好那缓存穿透、击穿、雪崩怎么处理谢飞机缓存穿透可以用布隆过滤器或者查询空值也缓存。缓存击穿可以设置互斥锁或者永不过期。缓存雪崩可以设置不同的过期时间或者集群部署。面试官思路正确还可以考虑使用本地缓存Redis多级缓存。问题2Kafka在电商中的应用面试官Kafka在电商平台中如何应用谢飞机可以用Kafka做异步处理比如订单创建后发送消息到队列然后异步处理物流、通知、统计这些。还可以用Kafka做日志收集或者实时数据统计。面试官具体架构设计谢飞机生产者就是业务系统消费者可以有不同的消费组处理不同的业务。比如订单处理组、物流处理组、统计组。还可以用Kafka Streams做实时计算。面试官很好那消息积压怎么处理谢飞机可以增加消费者实例水平扩展。或者优化消费逻辑批量处理。还可以设置重试机制处理异常消息。面试官思路清晰还可以考虑使用死信队列处理异常。问题3MySQL性能优化手段面试官订单表的查询性能很差有哪些优化手段谢飞机可以加索引比如订单状态、用户ID、创建时间这些字段。还有分库分表按用户ID或者时间分片。查询优化避免SELECT *只查询需要的字段。面试官具体操作谢飞机索引要选在经常查询和排序的字段上避免索引失效。分库分表可以用Sharding-JDBC或者自己实现路由逻辑。慢查询可以用EXPLAIN分析执行计划。面试官很好那大事务怎么优化谢飞机可以把大事务拆成小事务或者异步处理。减少事务中的数据操作量及时提交事务。还有可以使用读写分离查询走从库。面试官思路正确还可以考虑使用数据库连接池优化。面试官总结面试官谢飞机今天我们聊了很多电商场景下的技术问题包括并发处理、微服务架构、高并发优化等。你对基础技术掌握得还不错但在分布式事务、性能优化深度方面还需要加强。我们会综合评估有消息会通知你。谢飞机谢谢面试官我会继续学习期待有机会加入贵公司。详细答案解析问题1秒杀活动数据一致性解决方案业务场景双11秒杀活动10万QPS并发保证库存不超卖技术方案Redis预减库存使用Redis的INCR原子操作预减库存// Lua脚本保证原子性 String script if redis.call(get, KEYS[1]) tonumber(ARGV[1]) then return redis.call(decrby, KEYS[1], ARGV[2]) else return 0 end; Long result (Long) redisTemplate.execute(new DefaultRedisScript(script, Long.class), Arrays.asList(seckill_stock: productId), String.valueOf(1));消息队列异步处理使用RabbitMQ/Kafka处理订单创建RabbitListener(queues seckill.order.queue) public void handleOrder(Order order) { // 创建订单逻辑 // 库存最终扣减 }数据库最终一致性使用乐观锁Update(UPDATE product SET stock stock - 1, version version 1 WHERE id #{id} AND version #{version}) int reduceStock(Param(id) Long id, Param(version) Integer version);监控与补偿定时任务检查Redis和数据库差异问题2Spring Boot多数据源配置业务场景订单系统读写分离主库写从库读技术方案配置多个DataSourceConfiguration public class DataSourceConfig { Bean(name masterDataSource) Primary public DataSource masterDataSource() { return DataSourceBuilder.create().url(jdbc:mysql://master:3306/db).build(); } Bean(name slaveDataSource) public DataSource slaveDataSource() { return DataSourceBuilder.create().url(jdbc:mysql://slave:3306/db).build(); } }动态数据源切换public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }AOP切面切换Around(annotation(dataSource)) public Object around(ProceedingJoinPoint point, DataSource dataSource) throws Throwable { DataSourceContextHolder.setDataSourceType(dataSource.value()); try { return point.proceed(); } finally { DataSourceContextHolder.clearDataSourceType(); } }问题3JVM内存溢出排查业务场景线上系统频繁出现OOM排查步骤分析日志确定是Heap OOM还是Stack Overflow生成堆内存快照jmap -dump:formatb,fileheapdump.hprof pid分析内存对象使用MAT工具查看内存占用大的对象线程栈分析jstack -l pid thread_dump.txt在线诊断使用Arthas# 查看内存信息 memory # 查看类加载信息 classloader # 查看对象内存占用 jvm --memory问题4微服务拆分原则业务场景单体电商系统拆分为微服务拆分原则单一职责原则每个服务负责一个明确的业务领域DDD领域驱动设计按限界上下文拆分数据自治每个服务拥有自己的数据库接口设计RESTful API或gRPC拆分示例订单服务订单创建、查询、取消商品服务商品管理、库存管理用户服务用户注册、登录、个人信息支付服务支付处理、退款一致性解决方案Seata AT模式GlobalTransactional public void createOrder(Order order) { // 订单创建 // 库存扣减 // 积分增加 }最终一致性消息队列保证问题5分布式事务业务场景跨服务事务保证一致性技术方案Seata AT模式GlobalTransactional(timeoutMills 300000, name create-order) public void createOrder(OrderDTO orderDTO) { // 1. 创建订单 orderService.createOrder(orderDTO); // 2. 扣减库存 storageService.reduceStock(orderDTO.getProductId(), orderDTO.getQuantity()); // 3. 增加积分 pointService.addPoints(orderDTO.getUserId(), orderDTO.getAmount()); }TCC模式TccTry public void tryCreateOrder(OrderDTO orderDTO) { // 预检查 // 预占资源 } TccConfirm public void confirmCreateOrder(OrderDTO orderDTO) { // 确认提交 } TccCancel public void cancelCreateOrder(OrderDTO orderDTO) { // 取消操作 }本地消息表保证最终一致性问题6Redis缓存优化业务场景防止缓存穿透、击穿、雪崩技术方案缓存穿透布隆过滤器Bean public RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } // 布隆过滤器 Bean public BloomFilterString bloomFilter(RedisConnectionFactory factory) { return new RedissonBloomFilter(factory, config); }缓存击穿互斥锁public String getProduct(Long productId) { String key product: productId; String value redisTemplate.opsForValue().get(key); if (value ! null) { return value; } // 互斥锁 String lockKey lock:product: productId; try { boolean locked redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 10, TimeUnit.SECONDS); if (locked) { // 查询数据库 Product product productMapper.selectById(productId); redisTemplate.opsForValue().set(key, JSON.toJSONString(product), 30, TimeUnit.MINUTES); return JSON.toJSONString(product); } else { // 重试 Thread.sleep(100); return getProduct(productId); } } finally { redisTemplate.delete(lockKey); } }缓存雪崩随机过期时间// 设置随机过期时间 int randomExpire 30 new Random().nextInt(10); redisTemplate.opsForValue().set(key, value, randomExpire, TimeUnit.MINUTES);问题7Kafka消息队列应用业务场景订单异步处理架构设计生产者订单服务发送消息Component public class OrderProducer { Autowired private KafkaTemplateString, String kafkaTemplate; public void sendOrder(Order order) { String topic order-topic; String key order.getUserId().toString(); String value JSON.toJSONString(order); kafkaTemplate.send(topic, key, value); } }消费者多个消费组处理不同业务Component public class OrderConsumer { KafkaListener(topics order-topic, groupId order-process) public void processOrder(String message) { Order order JSON.parseObject(message, Order.class); // 处理订单逻辑 } KafkaListener(topics order-topic, groupId logistics-process) public void processLogistics(String message) { Order order JSON.parseObject(message, Order.class); // 处理物流逻辑 } }消息积压处理水平扩展消费者# application.yml spring: kafka: listener: concurrency: 5 # 增加并发度问题8MySQL性能优化业务场景订单表查询优化优化方案索引优化-- 复合索引 CREATE INDEX idx_user_status_create_time ON orders(user_id, status, create_time); -- 覆盖索引 CREATE INDEX idx_user_status_create_time_covering ON orders(user_id, status, create_time, order_id, amount);分库分表按用户ID分片ShardingTable(orders) public interface OrderMapper { Select(SELECT * FROM orders WHERE user_id #{userId} AND status #{status}) ListOrder findByUserAndStatus(Param(userId) Long userId, Param(status) Integer status); }大事务优化异步处理Transactional public void createOrder(OrderDTO orderDTO) { // 主事务创建订单 Order order createOrderMain(orderDTO); // 异步处理其他业务 asyncOrderService.asyncProcessOrder(order.getId(), orderDTO); }读写分离查询走从库DataSource(slave) public ListOrder queryOrders(Long userId) { return orderMapper.selectByUserId(userId); }通过以上详细的技术方案可以很好地解决电商平台在高并发、分布式架构下的各种技术挑战。