一次创业公司的抢购优化

1.优化前的架构


架构简述:
           如图,该架构是创业公司常见的一种垂直架构,业务是all in one的没有做拆分,redis只是用来session读写、验证码读写并没有用做缓存。
业务数据都是从mysql数据库直接取得。
           库存的处理主要是通过事务处理+乐观锁+ update ... where 库存-购买数>0,如果购买数>库存,验证不过,不能下单。

1.1.抢购时出现的问题
  • 数据读取失败,抢购页面进不去
  • 抢购成功率低
  • 后台大量报数据库更新失败
  • 后台大量报数据库连接异常
  • 同平台其他业务挂掉

1.2.为什么会出现上面的问题
  • 把库存的读取和更新直接落到后台的mysql数据库
  • 前端没有做限流,大量的请求都传递到后台,数据库连接数暴增
  • mysql是低速的磁盘IO处理速度慢
  • 行锁的存在,使得线程之间需要进行锁的争夺,一个线程获得行锁以后,其他并发线程就需要等待它处理完成,这样系统将无法利用多线程并发执行的优势,且随着并发数的增加,等待的线程会越来越多,rt急剧飚升,最终导致可用连接数被占满,数据库拒绝服务
  • 乐观锁高并发时抢购的成功率降低
  • 线上业务没拆分

2.优化后的架构

架构简述:
        如图,添加缓存层,把 活动页、商品详情页缓存到redis。 库存在活动开始前同步到redis,并且队列化(list)。 活动结束后redis的库存再同步回mysql(定时任务)

  • 2.1.抢购库存队列的设计


  • 根据库存,创建redis队列,队列长度=库存大小
  •  把mysql的一条资源实例化为一个队列的多个资源
  • 以商品为单位创建队列(key=活动id+商品id)
  • 减库存出队,加库存入队
  • 实时减,异步加
  • 限流,让少量请求落到后端
  • 活动结束redis库存(队列长度)同步到mysql

2.2.抢购流程时序图

如图,商品入库时,库存信息写到mysql,创建抢购活动或编辑抢购活动时库存信息以队列(list)方式写入redis,商品表中的库存减掉本次活动设定的库存。
客户下单时,验证通过后下单减库存,队列出队,库存-1,如果支付失败或发生异常,则还原库存,队列再入队。取消订单、退货、退款、超时未付款都要还原库存。
最后活动结束后,剩余库存同步到mysql,根据redis队列长度更新商品表的总库存和销量。

2.3.超卖与少卖

  • 为什么会出现超卖和少卖
          减库存在redis,下单在mysql,不同库不同事务
          高并发
  • 如何避免
    • 业务层面,取消订单、退货、支付超时、支付失败都还原库存,下单时校验
    •  捕获异常,异常发生时还原库存
    • 双写2个redis,只读一个redis,一个redis坏了,直接切到另一个redis
2.4.如何限流
  • 登陆验证
  • 限购数量检查
  • 库存检查
  • 活动开始后不可以重复提交(5分钟)
  • 每个web服务器设置接受请求的阀值(AtomicInteger),超过阀值就不再接受请求。

2.5.何时减库存
  • 下单减库存
  •  付款成功减库存(第三方支付有可能不能即时返回支付结果,暂未采用)
  •  设置超时时间(30分钟),释放未付款库存

3.未来规划
    经过优化后,每周的抢购都能顺利进行(初创时期,并发数不大),比优化前的架构要好很多。但是随着用户数的增加,优化后的架构还是不能满足高可用、高并发的需求。
 接下来会去做业务的拆分,数据库也按业务拆分,梳理和优化业务,重构代码,把现在的架构改成分布式的微服务架构,并把抢购活动拆分出来。
 从而做到水平扩展,使架构有较强的伸缩能力。










     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值