阿里的库存秒杀是如何实现的?

一、阿里的库存秒杀的实现

阿里有很多业务,几十上百个业务线,各自都有一些需要做抢购、秒杀、热点扣将的场景。他们都用哪些方案呢?
我看了很多资料,也找了很多人做交流,最终得到的结论是啥都有,主要总结几个主流的,在用的一些方案(主要是整体方案的介绍,具体细节就不展开说了,有的是太敏感不方便讲,有的是太复杂了先把主要的说了,后续需要的再展开):
你比如说,一些并发量没那么高,比如只有几千的,基本上是用mysql在抗的。但是你要是以为这个mysql和你用的mysql是一样的,那你会发现热点行更新在几百QPS的时候CPU就直接被拉满了。
那我们的mysql呢,是加了个自研了一个补丁(就是下面这篇文章中的技术方案),这个补丁可以识别出热点行及热点SQL,再给这些SQL分组,然后一个组内的多个SQL就可以减少加锁次数、减少B+树的遍历、以及通过组提交减少事务提交次数。就能扛更高的并发

但是如果有些场景的QPS达到数万级别了,只靠数据库肯定是不行了。于是有一些营销平台或者额度系统,就会采用分桶的策略。就是将单个1000的库存拆分成10个100的库存,这样就可以把并发提升10倍。当然,这里还需要考虑如何均匀分配,如何解决碎片,如何做分桶间调度以及如何做动态扩容等问题。然后有些团队就专门研发了库存调度系统来解决这些问题。

另外,在一些本地生活类的电商场景,比较常用的方案就是缓存+数据库的策略,也就是在缓存做预扣减,然后异缓存的不可用等问题。步通知到数据库再做扣减。这种方案就是需要考虑数据的一致性、

那对于那种需要抗几百万QPS的电商大促场景,基本上就是各种方案的结合了。热点库、SQL合并执行、缓存、以及分桶基本都是结合着来的。而且这里的缓存,又有分布式缓存、本地缓存,以及把分布式缓存和服务器部署在一起搞一个近端缓存。总之就是各种方案每一个抗一点并发,加到一起抗的就多了。

我还了解到还有一些物流的仓库管理场景,设计了自己的分布式事务+应用层排队框架,来减少在数据库层面的热点更新,方案听上去也挺牛逼的。
看了这么多之后,到底哪种方案最好?又经过77四十九天的研究,我终于悟了,适合的才是最好的。
根据具体的业务形态、并发量、团队成员的技术能力、基础建设的情况等等选择相对合适的就行了。但是不管咋说,复杂度和并发量一定是成正比的。


二、阿里的数据库能抗秒杀的原理

其实,在阿里电商的秒杀等(据我了解,淘宝、天猫、猫超、大麦等都是这么干的)场景中,主要还是基于MySQL数据库在做扣减的,主要是因为这样做最可靠了(避免了redis扣减方案中的数据不一致、少卖等问题)
但是我们都知道,数据库是抗不了热点行的并发更新的,于是阿里内部就对MSQL做了patch.
这个方案其实云上数据库RDS也支持了,所以我就可以讲了。(没开放的技术确实不敢讲,怕被请喝茶。。。)
这个技术叫做Inventory Hint,其实就是一个补丁。

(官方介绍:https://help,aliyun.com/zh/rds/apsaradb-rds-for-mysql/inventory-hint )
PS:这里主要是介绍通过lnventory Hint来提升热点更新的并发,但是并不意味着内容只用这个方案来抗热点并发,但是这个是基础,先把这个讲清楚。后续其他的方案,我也会挑一些能讲的介绍。

1、使用方法

他的用法很简单,只需要在正常的update语句中增加上特殊的hint语句就行了,如:

UPDATE /*+ COMMIT ON SUCCESS ROLLBACK ON FAIL TARGET AFFECT RON(1)*/ T
SETC=C-1
WHERE id = 1;

这里面的 COMMIT ON SUCCESSROLLBACK ON FAIL和TARGET AFFECT ROW 都是一些Hint语法:

  • COMMIT ON SUCCESS:当前语句执行成功就提交事务上下文。
  • ROLLBACK ON FAIL:当前语句执行失败就回滚事务上下文。
  • TARGET AFFECT ROW(NUMBER):如果当前语句影响行数是指定的就成功,否则语句失败。

hint:MySQL 中的"Hint"是一种特殊的语法,允许开发者向数据库引擎提供如何执行特定查询的额外信息或建议。这些提示不改变查询的结果,但可以影响查询的执行路径,比如如何选择索引、是否使用缓存等。使用Hint 的目的是为了优化查询性能。

很显然,前面我们提到的这几个hint是阿里自己支持的。所以只有内部的数据库,或者阿里云的RDS才支持。

2、原理介绍

当我们是使用 COMMIT ON SUCCES5 等hint标记了一条SOL之后,就相当于告诉MySOL内核,这行可能是热点更新。
于是,MySQL的内核层就会自动识别带此类标记的更新操作,在一定的时间间隔内,将收集到的更新操作按照主键或者唯一键进行分组,这样更新相同行的操作就会被分到同一组中。

为了进一步提升性能,在实现上,使用两个执行单元。当第一个执行单元收集完毕准备提交时,第二个执行单元立即开始收集更新操作;当第二个执行单元收集完毕准备提交时,第一个执行单元已经提交完毕并开始收集新批的更新操作,两个单元不断切换,并行执行。

根据热点行做了分组之后,就可以作进一步优化了,这个过程主要有3个关键的优化点:

3、关键优化点

3.1、减少行级锁的申请等待

在同一组中,需要更新的都是同一条记录,那么根据SQL的提交顺序,就可以排队了
然后我们只需要在第一条更新SQL(Leader)执行的时候,尝试去获取目标行的锁,如果获取成功,则开始操作。
然后这一组中后续的更新操作(Folower)也会尝试获取锁,但是会先判断是不是已经被第一条更新操作获取到了,如果是的话,那么就不需要等待,直接获取锁。
这样就可以大大降低行级锁的申请的阻塞等待时长,

3.2、减少B+树的索引遍历操作

MySQL是以B+索引的方式管理数据的,每次执行查询时,都需要遍历索引才能定位到目标数据行,数据表越大,系引层级越多,遍历时间就越长。
如果针对热点行更新操作做了分组之后,我们只需要在每组的第一条SQL执行过程中,通过遍历索引定位数据行之后就可以把这些数据行缓存到Row Cache中,并且在Row Cache进行修改。
在同组的后续操作时,也不再需要进行数据索引了,直接从Row Cache获取数据并修改就行了
这样就大大降低了B+树的索引遍历操作的耗时

3.3、减少事务提交次数

如果是没有用这种方式,我们的多条update语句会是多条事务,那么每一个事务都要单独做一次提交。
有了分组、排队、组提交之后,就只需要一组中的并发操作都执行完,然后做一次组提交即可,大大降低提交次
数。


对此,您有什么看法呢?评论区留言讨论哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/563072.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React系列 之 React进阶 含源码解读 (一)事件合成、state原理

资料来源:掘金课程 https://juejin.cn/book/6945998773818490884?enter_fromcourse_center&utm_sourcecourse_center 记录一些笔记 事件合成 React的事件其实是React重新实现的一套事件系统。目标是统一管理事件,提供一种跨浏览器一致性的事件处…

怎么拆解台式电脑风扇CPU风扇的拆卸步骤-怎么挑

今天我就跟大家分享一下如何选购电脑风扇的知识。 我也会解释一下机箱散热风扇一般用多少转。 如果它恰好解决了您现在面临的问题,请不要忘记关注本站并立即开始! 文章目录列表:大家一般机箱散热风扇都用多少转? 机箱散热风扇选择…

AbstractQueuedSynchronizer 独占式源码阅读

概述 ● 一个int成员变量 state 表示同步状态 ● 通过内置的FIFO队列来完成资源获取线程的排队工作 属性 AbstractQueuedSynchronizer属性 /*** 同步队列的头节点 */private transient volatile Node head;/*** 同步队列尾节点,enq 加入*/private transient …

专业矢量绘图设计软件:Sketch for mac 中文激活版

Sketch for Mac 是一款专业的矢量图形设计工具,主要用于 UI/UX 设计、网页设计、图标设计等领域。它的界面简洁、易用,功能强大,可以帮助设计师快速创建高质量的设计作品。 人性化界面 Sketch的界面非常简洁。最顶端的工具箱包含了最重要的操…

Oracle Data Guard部署

Oracle的主备DG搭建 1. 修改主机名,同步时间 主库IP:192.168.100.137 备库IP:192.168.100.138配置主机名(主库) Hostname zygjpdb vim /etc/hosts 192.168.100.137 zygjpdb 192.168.100.138 zygjsdbvim /etc/sysconfig/network HOSTNAMEzygjpdb ------…

【项目自我反思之vue的组件通信】

为什么子组件不能通过props实时接收父组件修改后动态变化的值 一、现象二、可能的原因1.响应式系统的限制2.异步更新队列3.父组件和子组件的生命周期4.子组件内部对 props 的处理 三、组件通信的几种场景(解决方案)1.子组件想修改父组件的数据2.子组件传…

win10开启了hyper-v,docker 启动还是报错 docker desktop windows hypervisor is not present

问题 在安装了docker windows版本后启动 docker报错docker desktop windows hypervisor is not present 解决措施 首先确认windows功能是否打开Hyper-v 勾选后重启,再次启动 启动后仍报这个错误,是Hyper-v没有设置成功 使用cmd禁用再启用 一.禁用h…

RuleApp资源社区,知识付费社区,可对接typecho的小程序APP

强大的文章/社区/自媒体客户端,支持打包为安卓,苹果,小程序。包括文章模块,用户模块,支付模块,聊天模块,商城模块等基础功能,包含VIP会员,付费阅读等收费体系&#xff0c…

计算机网络——26通用转发和SDN

通用转发和SDN 网络层功能: 转发: 对于从某个端口 到来的分组转发到合适的 输出端口路由: 决定分组从源端 到目标端的路径 网络层 传统路由器的功能 每个路由器(Per Route)的控制平面 (传统) 每个路由器上都有实…

创建vue3项目并集成cesium插件运行

创建vue3项目并集成cesium插件 一、vue项目创建 1、前期准备 node.js&npm或yarn 本地开发环境已经安装好。 参考安装 2、安装vue-cli,要求3以上版本 #先查看是否已经安装 vue -V#安装 npm install -g vue/cli4.5.17 示例:Idea工具 页面 Termin…

CSK6 接入聆思平台(LSPlatform)

一、开发环境 硬件:视觉语音大模型AI开发套件 二、使用大语言模型 官方指导文档: 开始使用 | 聆思文档中心 获取API密钥 | 聆思文档中心 1、注册 提交申请之后需要将注册电话号码通过微信发送给聆思科技工作人员,工作人员授权后&#xff…

章节10实验--Ubuntu18.04 Qt MySQL libqsqlmysql.so

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容,所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者:房胜、李旭健、黄…