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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 作者:胡刀,阿里云数据库运维专家

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

一般来说,从数据库层面讲,库存业务会分为两步,第一步是插入一条记录到扣减明细表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侧扣减。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
26天前
|
存储 Oracle 关系型数据库
Oracle数据库的应用场景有哪些?
【10月更文挑战第15天】Oracle数据库的应用场景有哪些?
151 64
|
12天前
|
缓存 关系型数据库 MySQL
高并发架构系列:数据库主从同步的 3 种方案
本文详解高并发场景下数据库主从同步的三种解决方案:数据主从同步、数据库半同步复制、数据库中间件同步和缓存记录写key同步,旨在帮助解决数据一致性问题。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
高并发架构系列:数据库主从同步的 3 种方案
|
19天前
|
缓存 监控 Java
Java 线程池在高并发场景下有哪些优势和潜在问题?
Java 线程池在高并发场景下有哪些优势和潜在问题?
|
24天前
|
NoSQL Java Redis
京东双十一高并发场景下的分布式锁性能优化
【10月更文挑战第20天】在电商领域,尤其是像京东双十一这样的大促活动,系统需要处理极高的并发请求。这些请求往往涉及库存的查询和更新,如果处理不当,很容易出现库存超卖、数据不一致等问题。
42 1
|
25天前
|
供应链 数据库
数据库事务安全性控制有什么应用场景吗
【10月更文挑战第15天】数据库事务安全性控制有什么应用场景吗
|
26天前
|
缓存 弹性计算 NoSQL
新一期陪跑班开课啦!阿里云专家手把手带你体验高并发下利用云数据库缓存实现极速响应
新一期陪跑班开课啦!阿里云专家手把手带你体验高并发下利用云数据库缓存实现极速响应
|
2月前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
391 15
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
1月前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
56 4
|
1月前
|
Java Linux
【网络】高并发场景处理:线程池和IO多路复用
【网络】高并发场景处理:线程池和IO多路复用
40 2
|
1月前
|
Java Linux 应用服务中间件
【编程进阶知识】高并发场景下Bio与Nio的比较及原理示意图
本文介绍了在Linux系统上使用Tomcat部署Java应用程序时,BIO(阻塞I/O)和NIO(非阻塞I/O)在网络编程中的实现和性能差异。BIO采用传统的线程模型,每个连接请求都会创建一个新线程进行处理,导致在高并发场景下存在严重的性能瓶颈,如阻塞等待和线程创建开销大等问题。而NIO则通过事件驱动机制,利用事件注册、事件轮询器和事件通知,实现了更高效的连接管理和数据传输,避免了阻塞和多级数据复制,显著提升了系统的并发处理能力。
55 0