慕课网Java高并发秒杀API之高并发优化笔记。
基于该系列课程的Demo。
分析高并发发生在哪里
业务流程分析
详情页
详情页容易出现并发。详情页获取当前的系统时间,如果秒杀没有开启会进入到倒计时;如果秒杀已开启,会调用地址暴露接口,用于获取秒杀地址;接着执行秒杀操作,返回结果。
图中红色代表可能发生高并发的点,绿色的部分表示没有影响。

-
问题:为什么单独获取系统时间?
场景分析:用户在商品详情页中,如果秒杀没有开始,会经常刷新详情页;详情页及静态资源应该部署到CDN节点上,那么访问详情页和静态资源是不需要访问到系统的,这个时候就拿不到系统的时间,需要单独发送请求获取服务器系统时间;其他请求如获取秒杀地址、执行秒杀的操作都对应到秒杀系统中。
详情页
- CDN的理解
1、CDN(内容分发网络)加速用户获取数据的系统。这里的数据可以是静态资源,也可以是动态资源,取决于推送策略。
2、部署在离用户最近的网络节点上。
3、命中CDN服务器后不需要访问后端服务器。 - 获取系统时间不需要优化
访问一次内存(Cacheline)大约10ns。 - 获取秒杀地址接口分析
1、无法使用CDN缓存
2、适合服务器缓存:Redis等
3、一致性成本维护低
秒杀地址接口优化

秒杀操作优化分析
1、无法使用CDN缓存
2、后端缓存困难:库存问题。在缓存中减库存会产生不一致问题,需要使用关系数据库如Mysql事务保证数据一致性。
3、一行数据竞争:热点商品
其他方案分析
原子计数器管理商品库存,保证原子性;记录行为作为消息放入分布式消息队列中;后端服务消费消息并落地到数据库(如mysql)。

为什么不用MySQL解决。
-
测试
同一id执行update减缓存,没有事务支持。发现性能很好,一秒4万QPS。
MySQL压力测试

当有库存的时候执行库存减一,然后插入购买明细;此时另一个用户也执行减库存,该用户会等待行锁,当之前的事务没有回滚或提交,这个行级锁不会被释放。当上一个用户的insert操作commit或rollback后,后来的用户获得锁并继续执行操作。此时再后面进来的用户会继续等待锁,进而产生串行化的阻塞操作。
瓶颈分析
执行update减库存,将SQL语句发送至MySQL服务器有网络延迟,同时还可能伴有GC(Java垃圾回收机制)操作,新生代GC会暂停所有的事务操作。GC不会每次都出现,但一定会出现。性能瓶颈出现在SQL执行时间、网络延迟和GC时间。
优化方向
行级锁在Commit之后释放,所以优化方向主要减少行级锁的持有时间。
网络延迟分析

系统并发越高,GC运行频率越高。
如何判断update更新库存成功
两个条件:
- Update自身没有报错。
- 客户端确认Update影响记录数。
优化思路:
事务竞争优化,减少事务锁时间。
把客户端逻辑放到MySQL服务端,避免网络延迟和GC影响。
如何放到MySQL服务器端
- 定制SQL方案:update /* + [auto_commit] */,需要修改MySQL源码。
- 使用存储过程:整个事务在MySQL端完成。一组SQL组成一个事务在MySQL端完成,避免客户端操作事务造成性能干扰。
网友评论