今天我们来探讨一下商城项目当中秒杀的场景,秒杀场景可以说是商城项目当中最难的场景,也是最重要的场景,今天我们对秒杀业务的基本业务做一下梳理,并简单讲解秒杀的代码实现和需要注意的问题。
第一、秒杀业务的梳理。
秒杀模块包括秒杀商品列表,秒杀商品详情,秒杀下单,订单列表查询,订单详情,还有订单支付,我们这里暂时省略关于物流的部分。商品列表和商品详情这都好说,因为普通商城也会有这两个接口,这里比较难的是,秒杀下单。秒杀下单为什么难呢?难的地方有这么几个。
1、秒杀下单时防止超卖又不能影响性能。
我们都知道,秒杀的时候,有大量的请求直接调下单接口,那么如何做好前期的流量削峰呢?当然,入口是商品列表和详情接口,但这两个都只是简单的查询接口,加上缓存和冷热数据分离,性能上还是好解决的。但是下单的时候,出了查询,还有update,insert的操作。而且有一堆各种校验。所以,必须对下单接口进行削峰处理。我们公司采用的方式是用redis进行削峰。举个例子,比如今天这个商品,我们卖100件,那么,我会在redis里存一个商品id的key,value是100,相当于库存。当下单开始,我会创建一个另一个key,是商品id拼接“sale”,相当于销量,每次有一个人进来,我会在sale上加1,把这个值和redis里的库存比较,如果sale的value比库存100大,则直接返回用户,商品已经抢购完。这个过程中,我只要保证sale每次+1的时候,是线程安全的就行。那么怎么保证sale的线程安全呢,就是redis的incr方法,每次增加步长为购买的数量,拿返回值与100对比。当抢到这个订单的用户,没有支付,10分钟后自动取消了,我这个sale的值再减1,这个操作也是线程安全的就可以。这样,后台下单就会很轻松。下单的过程,可以再次削峰,用rabbitmq或者kafka这样的消息队列,通过订阅消息来创建订单,这样通过两个削峰,足够可以解决秒杀的性能问题,而且也不会超卖。
伪代码大致如下
long incr = 0; String skey = Constant.getSeckillStockKey(order.getGoodsId()); incr = redisUtil.incr(skey,order.getNum()); if(CoUtil.isNotEmpty(goods.getSeckillLimitBy())) { if (incr > goods.getSeckillLimitBy()) { // 这个seckillLimitby就相当于库存最大值 redisUtil.decr(stockKey, order.getNum()); throw new Exception("商品足"); } }
2、秒杀下单后支付订单和下单时,同时修改库存,不能出现线程安全问题
当秒杀下单,不管是直接下单还是用mq下单,必然有一个修改库存和销量的动作,而如果同时,有人在操作退货或者支付,也会修改库存和销量,如何保证这时候的线程安全也是很重要的。我们项目中,用的是reddison的分布式锁来解决这个问题的。在修改库存的地方,可以加一个分布式锁。当然,也可以用数据库乐观锁来解决。
第二、秒杀需要注意的问题。
1、秒杀时出现性能问题该如何解决。
我觉得可以从几个方面着手,第一个是代码层面,第二个是服务层,第三个是数据库层。代码层最好是大家一起review代码,集众人的智慧解决问题。服务层可以加内存或者加节点,尤其是用容器化部署的方式,可以通过HPA或者HPC的方式,动态加节点。数据库层面可能是因为数据库的锁导致修改语句排队而延时,影响了性能。
2、秒杀下单中缓存的使用。
秒杀最难的就是性能问题,京东,天猫,淘宝,每年都会有秒杀,这种下单量可以说是巨量。他们是充分的利用了缓存。以后可以细讲的,多级缓存,一级二级缓存,这样的好处是,数据库的压力小了。
关于秒杀下单的内容有很多,商城项目的业务中,秒杀一直是一个重中之重,以后再继续完善。
今天我们来探讨一下商城项目当中秒杀的场景,秒杀场景可以说是商城项目当中最难的场景,也是最重要的场景,今天我们对秒杀业务的基本业务做一下梳理,并简单讲解秒杀的代码实现和需要注意的各方面问题。
今天我们来探讨一下商城项目当中购物车的场景,分析一下商城中购物车场景的业务实现以及要注意的问题。首先想聊一下部分开发同学对购物车业务的一个普遍的误区。部分没有开发过购物车业务的小伙伴会认为,购物车业务有什么好分析的,不就是简单的增删改查吗?一旦听到这样的回答,往往几乎可以断定,这位是没有实际开发过购物车业务,下面,我们来分析一下,购物车有哪些业务,我们需要注意些什么。(因为商品购物车关联的就是商城的订单创建,具体可以查看 商城项目的业务分析创建订单这篇文章。
今天尹白和大家一起分析商城项目中的创建订单的业务.通过这次对商城服务的核心业务中的创建订单的分析和解刨,对商城的订单有一个全面的认识。在商城业务当中,创建订单的接口,可以说是整个商城的业务当中最重要的接口。通过创建订单,真正建立了一个商品与用户的联系。
今天我们分析一下,商城项目的业务中,必不可少的支付环节,现在主流的微信支付,几乎是每一个商城项目都必备的支付方式,我们来分析一下微信支付的业务。项目中的支付,一般都会独立成一个模块,很多时候会独立成一个服务。因为调用支付的业务线一般都有好几条,比如商城下单后支付订单,比如商城购买高级会员或者续费,比如saas服务中购买某个插件或者某些功能等等。这些业务都会用到支付,没必要把支付放到商城模块下,更好的做法是把支付抽离出来,和各个模块形成松耦合。
今天我们聊一聊商城项目的业务中关于缓存的使用。在前面的内容中,我们已经介绍过商城业务中的核心接口,创建订单,https://www.inbai.net/article/141.html,在这篇文章里,我们详细介绍了创建订单的流程,不过我们更多的讨论的是业务分析,而没有深入去研究创建订单的性能。那么,今天我们就关于商城项目的性能方面,展开我们的话题,也就是在合适的地方使用上合适的缓存机制。