高并发秒杀系统实践

高并发场景

最近在慕课网上发现了一个高并发秒杀系统课程,学习了一下,对最后一章节里的场景分析和优化学习过程做了一个记录,分享一下,感觉这个老师讲的挺好的。

以一个秒杀场景为例,秒杀功能包括:
秒杀接口暴露(不到秒杀时间不允许用户访问)
执行秒杀
相关查询

高并发具体业务(秒杀)场景流程

红色部分可能会发生并发操作,绿色部分不会有并发操作

在这里插入图片描述

下面具体分析并发场景各个节点的优化

1.详情页

在这里插入图片描述

解决方案
  • 提供一个CDN节点,把静态资源(html ,JavaScript等)存储上去,实际上在并发操作过来的时候,用户访问的不再是服务器系统上的资源,而是CDN上的资源,这就避免了对服务器造成压力
  • 拿系统时间还是需要去服务器秒杀系统上拿
什么是CDN?
  • CDN 内容分发网络,加速用户获取数据的系统
  • 部署在离用户最近的网络节点上(通过运营商接口访问城域网最近的节点)
  • 命中CDN就不需要访问后端服务器了,大互联网公司都有自己的CDN集群,或者租用CDN集群

2.为什么访问内存时间不用优化?

访问一次内存只需要10ns,很快

3.秒杀地址接口优化

难点
  • 无法使用CDN缓存(只在一定时间内有效)
  • 适合存在服务器端中的redis中,可以抗很高的QPS(十万百万级)且一致性维护成本低
解决方案

在这里插入图片描述

这里要注意双写一致性问题
  • 双写一致性问题
    • 先更新数据库,再更新缓存
      • 更新数据库的操作顺序到更新缓存时顺序不一定一致,会造成脏数据
      • 写请求很多,读请求很少,频繁更新缓存却没发挥缓存的效果
    • 先更新数据库,再删除缓存
      • 缓存删除失败时,其他用户读到的仍然是旧的缓存数据
    • 先删除缓存,再更新数据库
      • 删除缓存失败,但更新数据库成功,会造成脏数据
    • 都无法保证任何场景下数据库与缓存数据完全一致

  • 主流方法基本上都采用第二或第三种,或者用以下解决方案
  • 解决方案
    • 将数据库缓存更新和读取操作进行串行化
    • 项目里维护一组线程池和内存队列
    • 更新数据时,根据数据唯一标志将请求路由到一个jvm队列中,然后更新,请求结束
    • 读数据时,先查缓存,数据不存在,根据唯一标志路由,发送到同一jvm队列中,重新读取后更新缓存
    • 由于都在同一队列中,执行顺序具有先后性

4.秒杀操作优化

难点
  • 无法使用CDN缓存
  • 后端缓存困难:库存问题(不同用户访问redis同时命中,会产生不一致)
  • 一行数据竞争:热点商品
解决方案
方案一

在这里插入图片描述

  • 原子计数器:redis实现,记录商品的库存,减库存操作保证原子性
  • 记录行为消息:谁减了库存?生产此条消息放入分布式消息队列中
  • 消费消息并落地:消费消息记录到MySQL数据库中
痛点

运维成本太高,都依赖于分布式的NoSQL和MQ

开发成本太高,数据一致性不好保证,回滚方案设计复杂

幂等性难保证,重复秒杀问题

为什么不能直接用MySQL?

因为低效率

一条update压力测试结果: 4W QPS,一秒种商品可以更新4W次,那为什么效率还低?

在这里插入图片描述

  • update insert 等操作会有网络延迟和GC操作(由于Java的特性)
  • 事务阻塞十分严重

优化方向:

减少行级锁持有时间

把客户端逻辑放到MySQL服务端,避免网络延迟和GC影响(比如判断是否更新成功)

在这里插入图片描述

总结

在这里插入图片描述

附上慕课网课程地址:
https://www.imooc.com/learn/632

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值