秒杀系统流程及并发优化分析

流程分析

之前看了下慕课网的秒杀系统,也动手实战过。分析下常见的秒杀抢购和抢红包系统流程和架构优化。
页面流程
提供给用户的前端页面主要有商品列表页和对应的详情页。登录用户信息这里只是使用了cookie。没有另外数据库层面的存储。

1.列表页

秒杀商品列表页
列表页面比较简单。只是暂时而已。但是有关键的开始和结束时间。这些会存在客户端,以便以后的获取系统时间对比。判断是否开始秒杀所用。

2.详情页

用户标识存cookie
秒杀等待
暴露秒杀接口
秒杀成功
重复秒杀
详情页面流程

我们关注它的核心流程:

1. 客户端进入页面后需要判断是否已经登录(这里使用cookie):

  • 先从kookie判断是否有用户标识的手机号码
  • 有的话下一步,没有填入,然后填写登录(这里没有用到DB),成功后保存该cookie(key-value, expire)

2. 获取服务器系统时间:

  • 因为不同用户客户端的时间可能不同。需要统一从服务器get。然后与列表页获取到的该商品的秒杀开始结束时间对比。
  • 未开始的启动计时器;已结束的不再over,进行中的下一步获取暴露接口

3. 获取暴露的秒杀接口:

  • 这个一般是动态生成的,可以简单对商品id加盐hash即可。
  • 因为已经属于秒杀时间内了,获取到接口,也包含商品目前信息,即库存量,还有则按钮显示可以秒杀。

4. 执行秒杀:

  • 执行秒杀需要给服务端提供(商品id, 用户标识phone,接口hash)。
  • 服务器端对参数验证,如hash是否正确。都🆗执行秒杀操作。减库存+记录用户购买信息。同时按钮变灰,无法再点击。如果重复购买返回错误重复。这些都是封装在个vo/dto中返回即可。

技术分析

  • 前端:Bootstrap + Jquery + Cookie
  • 后端:SSM/Spring Boot + MySQL
  • 模板:Jsp/Thymeleaf + Restful接口
  • 高并发:缓存Redis + 消息队列MQ + 数据库存储过程procedure

高并发优化

详情页逻辑可优化分析
其中红色的是可以考虑优化的部分

1. 页面静态资源

  • 动静态分离,使用CDN或者Nginx服务器

2. 系统时间

  • 这里只是一个接口,return new Date().getTime获取系统时间,一般无需优化。

3. 地址暴露接口

redis缓存方式

  • 因为秒杀的时候用户会大量重复刷新页面,而这个秒杀商品对象的一些信息存在数据库,如库存开始结束时间。比较后正确才能给他生成暴露接口。反正是操作数据库了,这个可以使用Redis缓存这些秒杀对象信息。一致性维护采用超时缓存即可。因为商品信息基本不会短时间改变。
  • 具体可见Redis后端缓存量大的数据库查询

4. 执行秒杀操作

这是优化的重点
事务执行流程
秒杀这些都是一般两个操作: 减库存记录用户购买信息

单条update压力测试
事务处理分析
但是因为update行级锁的影响,一个事务结束才会释放行级锁。加上网络延时和GC,会很慢。如果实现还是在数据库方面,优化主要是减少事务锁的时间。

  • 优化方案1: 可以将事务的两个操作交换顺序,因为行级锁是在update操作中的。放到后面不会整个事务时间都独占,可以稍微快点。
  • 优化方案2: 使用存储过程。把事务的执行移到MySQL服务端执行。可以优化行级锁的持有时间。但是存储过程比较复杂。一般不常用,当然对于逻辑简单秒杀系统来说是可以,用JMeter压力测试可以达到6000QPS。
  • 优化方案3:如下,使用redis缓存库存,可以使用list,因为pop是原子性的。pop成功则记录用户购买行为以信息形式投放到MQ中,异步削峰,再写入MySQL,用的都是集群。整个过程可以非常快。

微信抢红包方案

但是也有问题,虽然解决了MySQL事务性强大的替换。但是如果数据修改了,redis的一致性问题难以保证。而且重复秒杀,redis根本不知道,需要另外使用一个NOSQL集群记录谁购买了维护处理。此外如果MQ错误等,都很难回滚解决,等等
该方案成本分析

优化总结

参考

慕课. Java高并发秒杀API之高并发优化


 上一篇
查找算法总结 查找算法总结
常见的查找算法有7种 1. 顺序查找顺序查找对序列没有排序要求ASL = 1/n(1+2+3+…+n) = (n+1)/2;T((n+1)/2)复杂度为 O(n) 2. 折半查找也叫二分查找,必须是有序的序列。 int binarySear
下一篇 
Redis后端缓存量大的数据库查询 Redis后端缓存量大的数据库查询
需求在秒杀系统中,红色部分是可以优化的,对于地址暴露接口那块,也就是用户根据id客户端访问查看页面是否可以秒杀了,如果可以秒杀,会暴露一个动态hash接口。所有也是刷新很频繁的。 public Exposer exportSeckill
2019-07-18
  目录