高并发库存秒杀场景,阿里巴巴数据库是这样应对的

简单库存场景的数据库实现

一般来说,从数据库层面讲,库存业务会分为两步,第一步是插入一条记录到扣减明细表inventory_detail,第二步是对库存扣减表inventory的一条记录进行扣减,这两步往往是在一个事务中实现的。

001.jpeg

数据库业务架构图如下,所有的请求均发往同一个Database。

从上文的架构图不难看出,所有的商品的库存信息都存在单一的表和库里,当商品种类繁多或者业务并发请求暴涨时,单实例的数据库显然会成为容量或者性能瓶颈。该数据库架构一般只是功能性的实现,主要用于微型库存系统或者测试使用。

002.jpeg

高并发库存系统的数据库实现

为了解决单实例存在的容量和性能上限问题,阿里巴巴所有的库存系统在十年前就实现了分库分表设计,主要通过数据的水平拆分实现不同商品的库存扣减请求路由到不同的数据库。基本数据库架构图如下

003.jpeg

从上图不难看出,库存扣减表和扣减明细表一般都使用商品id作为片键,这样可以保证满足整个系统在高并发扣减请求的同时,同一商品的库存扣减操作和添加明细操作在同一个事务中实现。如果数据分布和业务请求足够均匀,理论上经过分库分表设计后,整个系统的吞吐量将会是线性的增长,主要取决于分实例的数量。

热点行更新

在电商业务中,商家活动比如秒杀不可避免。秒杀活动会给电商库存系统带来巨大的挑战,尤其体现在数据库层面。因为往往一个商品id对应于数据库的一行记录,所以在DB架构上按照商品维度做了分库分表也是无效的。而更新这行记录时必然需要给这行记录加X锁。热点商品的库存扣减本质上就是热点行更新的能力,高并发的同行更新会造成严重的行锁等待现象,从而导致数据库的threads_running和rt飙升,造成雪崩。在当前的官方mysql中,一般单行更新的QPS在500以内,对于热点商品的秒杀需求,这个量往往是不达标的。

阿里巴巴PolarDB-X数据库团队基于以上场景的需求,针对内核优化,引入了先进的水车模型,在识别出热点SQL后,实现了在内核层面优化处理,相比官方MySQL提高了10倍以上的热点行扣减能力,广泛应用于集团电商库存集群,资金平台,权益发放平台等核心数据库集群。

其主要的核心思想是:针对应用层SQL做轻量化改造,带上"热点行SQL"的标签,当这种SQL进入内核后,在内存中维护一个hash表,将主键或唯一键相同的请求(一般也就是同一商品id)hash到同一个地方做请求的合并,经过一段时间后(默认100us)统一提交,从而实现了将串行处理变成了批处理,让每个热点行更新请求并不需要都去扫描和更新btree。

004.jpeg

类似原理,阿里云RDS数据库团队同样在内核层面针对热点行更新做了大量的优化,核心思路为引入SQL语句的排队机制,将可能存在行锁冲突的语句放在一个组内排序,从而减少行锁冲突带来的额外系统开销。Statement Queque和Inventory Hint可以结合使用,不过在事务中,热点行更新必须是该事务的最后一条记录,因为commit on success的机制存在,一旦该SQL执行成功就会自动提交或自动回滚。简单的使用范例如下


begin;
insert into inventory_detail(inventory_id,user_id) values(1,1);
update /*+ ccl_queue_value(1) commit_on_success rollback_on_fail target_affect_row(1) */ inventory set inventory_count=inventory_count+1 where inventory_id=1 

更多文档参考inventory hint statement queue

业务架构优化

幂等性实现

在库存数据库系统中,一般都会在更新库存记录后,写入一条库存扣减明细的流水记录,用于后续可能存在的查询需求。举个例子,在集团的权益发放平台中,库存流水记录主要用于实现库存扣减的幂等性,即同一个用户只能领取一次权益。在系统的实际运行过程中,可能因为一些网络故障等其他原因,当底层数据库的扣减成功以后并没有成功返回给用户时,用户可能会有重试操作,这时就必须避免库存记录的重复扣减情况。所以针对这些情况,应用在设计时会考虑先查询一遍库存流水记录,如果该用户已经领取过该权益,则不再重复扣减,直接返回。为了实现这种强幂等性的需求,库存扣减和插入流水就必须在同一个事务中,满足同时成功或同时失败。

基于缓存的分桶扣减方案

在更大规模,针对单一商品的超高并发扣减的库存集群中,可能基于数据库内核的改造优化还无法满足业务需求。单一商品的超高并发扣减可能会影响到同一数据库实例上的其他商品扣减,同一个数据库实例上也可能存在多个热点商品造成互相影响,这时就需要考虑在业务和数据库架构上再做一次升级,我们引入基于缓存的分桶扣减方案。

下图为该方案数据库架构图,基于缓存的分桶扣减方案的主要思路为

  • 1、普通的非热点商品,或者并发度不够大的热点商品走强幂等性的分库分表+数据库内核改造优化
  • 2、超大热点商品,针对该商品再做多key拆分,先走弱幂等性的缓存扣减,缓存扣减后,异步往DB写入一条库存流水记录,后续再做缓存与数据库的库存总量同步

005.jpeg

在分桶方案详细落地实现上,需要考虑的细节问题会多很多,比较重要的有以下几点

1、分桶管理

为了更通俗和直观的描述,缓存集群的一个key就对应于于一个"分桶"。要实现一个基于缓存分桶方案的高扩展性的库存系统,分桶的设计至关重要,比如一个热点商品应该对应多少个分桶,分桶的数量能否根据当前的业务变化做到弹性的伸缩

  • 1、分桶预分配库存:当分桶初始化后,每个分桶应该保存多少库存量。不一定在预分配库存阶段将该商品的库存数量从DB全部分配到缓存中,可能是一种渐进式的分配策略,DB作为库存总池子
  • 2、分桶扩容/缩容:分桶数量的变化,扩缩容操作本质上是调整桶映射管理内的信息,加入或者减少桶,桶信息一旦增加或者减少了,扣减链路会秒级感知到,然后将用户流量引导或者移除出去。从上面的DB架构图可以看出,比较简单的实现方式就是根据当前热点商品的桶数量取模
  • 3、桶内库存数量扩容/缩容:即每个分桶内该商品的库存数量变化,扩容场景主要用于当该分桶内库存接近扣减完成时,系统自动去MySQL库存集群总池子里捞一部分过来放进桶内。缩容场景主要场景在于桶下线后将桶内剩余的库存回收到库存总池子中
  • 4、合并展示:在基于缓存的分桶设计中,由于同一种热点商品拆分成了多个key,所以在前端界面展示上同样会带来挑战,需要做库存的合并

2、超卖问题

一个较为简单的处理超卖问题的思路是预留一部分库存,当库存数量低于之前定义的预留值时,直接返回前端库存扣减完毕,从而避免造成超卖。

3、碎片问题

在一些类库存系统的设计中,考虑到系统的兼容性和支持的扣减种类,或许扣减的是商品的库存数量,或许是红包的金额(将带小数的红包金额转换成整型数扣减)。所谓碎片问题,举个例子,假如扣减的是红包金额,假设红包金额至少要发1块钱,换算成整型数也就是100,在多个分桶扣减的情况下,最后部分分桶的剩余库存值可能低于100,而所有分桶加起来的总额又大于100。如果不做处理,就会造成资损。

应对这种极端场景,系统需要在检测到存在碎片时,自动将存在碎片的分桶下线纳入库存总池子,由DB总池子再分出少量的缓存key来进行扣减,多次循环直到不存在碎片为止。或者针对出现这种情况后,由于库存总量已经基本扣减完毕,在纳入DB总池子后直接在DB侧扣减。

原文链接

本文为云栖社区原创内容,未经允许不得转载。

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

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

相关文章

国产数据库存储引擎X-Engine的科研之路

X-Engine是阿里云RDS MySQL 的存储引擎之一,基于Log-structured Merge Tree (LSM-tree),较基于 B-tree 一族的其它存储引擎而言年轻很多,所以在实践中遇到问题也更多,对研究的需求也更大。 LSM-tree是1996 年美国计算机科学家 Pa…

Vue刷新当前页面几种方式

问题: 最近些日子项目中突然碰到了一个需求,再完成编辑操作之后需要进行页面刷新,通过实验有如下几种姿势可以解决需求中的问题,下面进行简单总结如下。 姿势一:this.$router.go(0) 这个姿势是利用了 history 中前进和后退的功能&…

【我想进大厂】Redis夺命连环11问

来源 | 科技缪缪责编 | Jerry说说Redis基本数据类型有哪些吧字符串:redis没有直接使用C语言传统的字符串表示,而是自己实现的叫做简单动态字符串SDS的抽象类型。C语言的字符串不记录自身的长度信息,而SDS则保存了长度信息,这样将获…

因“智”而治,数据库自动驾驶时代大门即将开启!

数据库自治服务DAS即将重磅发布 点我立即预约直播DAS精彩详情 因“智”而治,数据库即将迈入自动驾驶时代4月22日 15:00 — 16:30 期待与你一同见证精彩蜕变 随着云计算的普及,数据库从传统以软件呈现的DBMS走向以服务呈现的云数据库,解决了开…

史上最强《Java 开发手册》泰山版王者归来!

阿里妹导读:潜力修炼一年之久的《Java 开发手册(泰山版)》今天发布!此次共计新增 34 条规约,修改描述 90 处,其中错误码规则更是第一次提出完整的解决方案,大家参考错误码示例表,欢迎…

Java 最高均薪 19015 元! 8 月程序员工资出炉,你拖后腿了吗?

在全员争当码农的时代,如果你也想学一门编程语言,那么,我要告诉你,Java 是编程语言中不可撼动的王者。有点难理解?先看个排行榜???? 来自权威开发语言排行榜 TIOBE 的数据(截止到 2020 年 4 月&#x…

从事前到事后,云数据库 Redis MongoDB 安全体系全揭秘!

作者:陈金元(今远),阿里云管控技术专家 一、整体说明 上图是云数据库Redis&MongoDB的安全体系图,横向是实例控制链路,纵向是实例数据链路,对于控制链路,事前为了避免恶意操作或…

TeaDSL:支持任意 OpenAPI 网关的多语言 SDK 方案

正在上传…重新上传取消 导读 在以云计算为主角的开发者视界中,OpenAPI 是绝对的主角。要发短信,用 OpenAPI;要管理资源,用 OpenAPI;要管理权限,用 OpenAPI。如果一个 OpenAPI 解决不了你的问题&#xff…

Vue如何循环提取对象数组中的值

数据如下,提取name和callcount 第一种: getQueryCallStatistics("sesp1", this.provinceId).then((res) > {let arr [];let arr1 [];let arr2 [];let arr3 [];let arr4 [];this.xunshiMap res.data.callstatistics;res.data.callst…

Node.js 从门详解 (二)

目录1. 模块化的基本概念1.1 什么是模块化1.2 模块化规范2. Node.js 中模块化2.1 Node.js 中模块的分类2.2 加载模块2.3 Node.js中的模块作用域2.3.1 什么是模块作用域2.3.2 模块作用域的好处2.4 对外共享模块作用域中的成员2.4.1 module对象2.4.2 module.exports对象2.4.3 共享…

分享实录 | 阿里巴巴测试环境管理实践概述

正在上传…重新上传取消 【以下为分享实录,有删节】 测试环境管理之困 正在上传…重新上传取消 互联网产品的服务通常是由 Web 应用、中间件、数据库和许多后台业务程序组成,一套运行环境就是一个自成一体的小生态。部署软件产品的正式发布版本&#…

高校毕业生:今年“太惨了”,网友:更惨的可能还在后头!

受疫情影响,今年的就业形势基本上没跑了:“各行各业,大小企业,全面缩招!”据国家统计局7月份的最新数据显示:20-24岁大专及以上人员(主要为新毕业大学生)失业率比去年同期高 3.3 个百…

uniapp利用腾讯地图接口获取当前定位城市及计算两经纬度的实际距离

文章目录一、注册腾讯地图1. 申请开发者密钥(key)2. 开通webserviceAPI服务3. 下载SDK二、导入SDK2.1. 解压复制2.2. 页面导入三、实现3.1. 先创建实例。3.2. 获取经纬度3.3. 监控四、计算二点距离4.1. 官网地址4.2. 代码4.3. 测试一、注册腾讯地图 1. …

Gartner 企业级网络设备市场份额报告:阿里云负载均衡增速全球第一

4月8日,Gartner发布最新的全球企业级网络设备市场份额报告,阿里云负载均衡(SLB)增速全球第一,单季度营收环比增长35.1%,远超欧美传统厂商或是云服务厂商。 负载均衡被誉为IT系统的流量管家,它可…

放弃 Windows 后 ,开源操作系统能成为主流桌面系统吗?

来源 | CSDN责编 | 郑丽媛头图 | CSDN下载自东方IC在近十几年里,总是能听到世界各地的国家或者地方政府在尝试用开源系统代替Windows作为政府办公系统,尤其在今年微软正式宣布停止对Windows 7的更新维护服务后,很多数年来一直使用的Windows 7…

Sentinel 1.7.2 发布,完善开源生态及扩展性

Sentinel 1.7.2 正式发布,带来了 Logger SPI 扩展机制、Zuul 2.x 网关流控、SOFARPC 适配等多项特性和改进。下面我们来一起探索一下 Sentinel 1.7.2 的重要特性。 多样化的适配模块 到目前为止,Sentinel 已覆盖微服务、API Gateway 和 Service Mesh 三…

微信开发者工具:Failed to load font ************** net::ERR_CONNECTION_RESET问题解决办法

如果微信开发者工具前几天用的好好的突然出现 VM541:1 Failed to load font https://img.yzcdn.cn/vant/vant-icon-d3825a.ttf net::ERR_CONNECTION_RESET 这个错误说明。可能原因是微信开发者工具发布了新版本,你需要更新一下开发工具的版本,就能解决这…

从 DevOps 到 NoOps,Serverless 技术的落地方式探讨

Serverless 技术正以一种全新的方式,帮助云上客户进一步节省云的使用成本,实践 NoOps 理念,同时,他也正深刻变革着开发者们的编程模式,所谓“Write locally, compile to the cloud”。 本文将介绍 Serverless 技术来降…

uni-app中使用腾讯位置服务实现小程序地图选点功能

文章目录1. 官方文档2. 小程序添加插件3. HBuilder配置4. 配置代码5. 页面代码1. 官方文档 技术选定(地图选点插件) (对应官网:https://lbs.qq.com/miniProgram/plugin/pluginGuide/locationPicker ) 2. 小程序添加…

8000字 | 32 张图 | 一文搞懂事务+隔离级别+阻塞+死锁

来源 | 悟空聊架构(ID:PassJava666)头图 | CSDN下载自视觉中国事务1.1 什么是事务为单个工作单元而执行的一系列操作。如查询、修改数据、修改数据定义。1.2 语法「(1)显示定义事务的开始、提交」BEGIN TRANINSERT IN…