1. 上次一面聊了你的项目,能再深入说说项目中遇到的最大挑战吗?
最大的挑战是处理秒杀场景的高并发问题。
当时模拟了一个促销活动,瞬间有几千个请求抢购商品。最初的实现是直接查数据库库存,然后扣减,结果出现了超卖问题,而且数据库压力特别大,响应很慢。
我分析后发现主要有三个问题:数据库成为瓶颈,库存扣减不是原子操作,没有做流量控制。
解决方案是多层优化。首先把库存预热到Redis,用Lua脚本保证扣减的原子性。Lua脚本先判断库存是否充足,充足才扣减,整个过程是原子的。然后在网关层用Sentinel做限流,超过阈值直接拒绝。订单创建改成异步的,扣完库存就返回,通过RabbitMQ慢慢处理订单。
还做了一些细节优化,比如前端按钮防重复点击,Nginx做负载均衡,数据库读写分离。通过JMeter压测,优化后QPS从几百提升到三千多,没有出现超卖。
这个过程让我理解了高并发场景下要从多个层面优化,单点优化效果有限。也学会了用工具定位瓶颈,针对性解决问题。
2. 说说ConcurrentHashMap的实现原理,和HashMap有什么区别?
ConcurrentHashMap是线程安全的HashMap,但实现机制不同。
JDK 1.7用分段锁,把数据分成多个Segment,每个Segment是一个小的HashMap,继承自ReentrantLock。读操作不加锁,写操作只锁当前Segment,理论上支持16个线程并发写。
JDK 1.8取消了Segment,改用CAS加synchronized实现更细粒度的锁。数据结构和HashMap一样,是数组加链表加红黑树。锁的粒度是数组的每个位置,只有hash冲突时才用synchronized锁住链表或红黑树的头节点。使用CAS进行无锁的插入和更新,性能更好。
和HashMap的区别:
线程安全性,HashMap不是线程安全的,ConcurrentHashMap是。如果多线程用HashMap会出现数据丢失、死循环等问题。
null值,HashMap允许一个null key和多个null value,ConcurrentHashMap都不允许,会抛异常。
性能,单线程HashMap更快,多线程ConcurrentHashMap更快。
迭代器,HashMap的迭代器是fail-fast的,ConcurrentHashMap是弱一致性的,不会抛ConcurrentModificationException。
实际使用中,单线程用HashMap,多线程用ConcurrentHashMap。不要用Hashtable,性能差而且过时了。
3. JVM的垃圾回收机制了解吗?有哪些垃圾回收器?
JVM垃圾回收主要针对堆内存。
判断对象是否可回收用可达性分析算法,从GC Roots开始遍历,能到达的对象是存活的,不能到达的是垃圾。GC Roots包括虚拟机栈中的引用、静态变量、常量、本地方法栈的引用等。
垃圾回收算法有几种:
标记-清除,标记存活对象,清除未标记的,简单但会产生内存碎片。
标记-复制,把内存分两块,每次只用一块,垃圾回收时把存活对象复制到另一块,然后清空这一块。不会有碎片但浪费空间,适合新生代。
标记-整理,标记存活对象,然后移动到一端,清理边界外的内存。不会有碎片也不浪费空间,但移动对象有开销,适合老年代。
常见的垃圾回收器:
Serial,单线程,适合客户端应用。Parallel,多线程,吞吐量优先,适合后台计算。CMS,并发标记清除,停顿时间短,但会产生碎片。G1,分区回收,可预测停顿时间,JDK 9后的默认回收器,适合大内存应用。ZGC和Shenandoah,低延迟回收器,停顿时间在10ms以内,适合对延迟敏感的应用。
实际使用中,根据应用特点选择回收器。吞吐量优先用Parallel,延迟敏感用G1或ZGC。通过JVM参数调整堆大小、新生代比例等,使用工具分析GC日志优化性能。
4. 分布式事务有哪些解决方案?你项目中用过吗?
分布式事务是跨多个数据库或服务的事务,保证一致性比较复杂。
常见解决方案:
2PC两阶段提交,协调者先询问所有参与者能否提交,都同意再发提交命令。强一致性但性能差,有阻塞和单点问题,实际很少用。
TCC,业务层面的两阶段提交。Try预留资源,Confirm确认提交,Cancel回滚。需要业务代码实现三个接口,开发成本高但性能好,适合对一致性要求高的场景。
本地消息表,在本地数据库记录消息,事务提交后发送MQ,消费者处理后更新状态。定时任务扫描未发送的消息重试。实现简单,保证最终一致性。
消息事务,RocketMQ支持事务消息。发送半消息,执行本地事务,根据结果提交或回滚消息。消费者处理消息,失败则重试。
Saga模式,把长事务拆分为多个本地短事务,每个事务有对应的补偿操作。某步失败就执行之前所有步骤的补偿。适合长流程业务。
我项目中用的是消息队列保证最终一致性。比如下单后扣库存、扣积分、发通知,这些操作通过Rabb
全部评论
(1) 回帖