库存合并扣减:一种基于分布式缓存的强一致性热点库存扣减方案

简介: 本文介绍了一种基于Redis分桶扣减与DB合并提交的强一致库存扣减方案,适用于热点商品高并发抢购场景。通过Redis实现高性能扣减计数,结合数据库明细保障数据准确,既避免超卖少卖,又显著提升TPS与系统稳定性,有效支撑直播等大流量业务需求。

前言

本文主要介绍了针对热点深库存下单抢购场景,库存团队设计并实现的一种基于Redis分桶扣减计数和合并提交扣减DB的方案;该方案基于分布式缓存实现,但也能做到不超卖不少卖,在保证扣减强一致性的同时,也提升了库存热点扣减TPS和扣减稳定性。


背景介绍

自库存团队成立以来,随着业务的不断发展,库存扣减性能优化一直是库存团队不断面临的挑战;近几年,库存和数据库团队一起,从数据库内核优化、到应用层优化、再到扣减架构升级,持续的提升库存DB扣减的性能。在前述优化的基础上,库存数据库的整体性能得到了很好的提升。

然而随着直播业务的发展,热点扣减的场景越来越频繁,对于深库存热点扣减的场景,日常我们只能通过限流的方式来保护DB,库存合并扣减就是在这样的背景下提出的,我们希望继续优化热点扣减的性能,使库存扣减不成为热点下单链路的瓶颈所在。


方案调研

传统的提高热点扣减的方案都是通过分布式缓存实现,该类方案通过将库存从 MySQL 划分到多个Redis分桶,扣减的时候直接走Redis进行扣减,分析此类方案,我们会发现:

1. 该类基于缓存的扣减方案确实能够大幅提升扣减的性能;

2. 但是这个库存扣减方案在实际应用中也会存在一些问题:

  • 无法避免库存少卖:针对Redis失败(如超时)的场景,应用层实际并不知道Redis库存是操作成功还是操作失败。为了避免库存超卖,对于扣减超时的场景,应用层只能默认当做失败处理;对于库存回补的场景,应用层只能默认当做成功处理。此时整体是业务有损的,所以Redis分桶扣减方案一般是用在卖家限购、权益这类非实物类库存扣减的场景,这类场景业务接受少卖
  • 对于稍微复杂的库存扣减模型无法支持:Redis库存扣减方案中使用incr和decr实现库存的加减,利用lowBound防止库存减到负数,value即是剩余的库存数量;这个方案只支持库存记录仅包含一个数值的库存模式, 对于sq- 同时wq+ 这种模式无法支持。
  • 库存扣减完全依赖Redis:当前扣减方案需要强保障Redis的稳定性,如果Redis异常则整个扣减链路异常。

我们想利用Redis提升扣减性能,但是我们的库存扣减模型相对更加复杂、同时我们的业务场景对于库存数据准确性要求更高,绝对不允许超卖少卖;传统的基于redis分桶扣减的方案并不完全适合我们的业务场景。


合并扣减方案

介绍合并扣减详细方案之前,先简单说明下库存域的几个基本概念,方便大家更好理解后续的内容。

1. 库存核心字段:

  • 可售库存:sq,实际可售的库存数量;
  • 预扣库存:wq,用户下单后,库存sq转向wq;
  • 占用库存:oq,货品仓库存模式,付款之后,库存从wq转向oq。

2. 库存扣减明细(也叫单据):是库存扣减的快照,明细是不可或缺的。明细的作用:

  • 记录扣减信息:下单是交易会告诉我们扣多少库存,后续付款或者订单取消时,上游不用关心库存的回补数量,库存内部从明细恢复;
  • 用于分布式系统交互过程中的幂等实现:同一个单据调了两次扣减;单据回补超时,重试可幂等;
  • 负责库存扣减生命周期状态流转。

整体思路

我们既想利用分布式缓存(Redis)提升扣减性能,但同时又不能直接依赖Redis作为库存存储介质;因此我们的方案里面,Redis只用来做扣减计数以防止超卖,实际扣减是否成功以库存扣减明细为准。 整体思路如下:

1. DB行的库存提前预留(锁)一部分,锁的这个库存还在DB行上,同时也初始化到redis里面用于扣减计数;

2. 合并扣减下单过程中,先扣减redis库存,redis库存够扣的情况下,再往DB插入扣减明细,明细插入成功最终才算扣减成功;

3. 应用层的合并扣减管理模块,热点下单延迟1s后,通过扫描扣减明细,计算实际应该扣减的数量,一次提交库存变更到DB。

接下来介绍各个分模块的设计。

锁库存模块

1. 锁库存模块将DB行库存从sq字段(可售)锁到lq字段(预锁库存),同时锁库存单据;

2. 锁库存核心实现,不是通过将sq减去然后加到lq,而是sq不动,锁库存直接加到lq;DB扣减时通过 where sq-lq>0 控制最终sq的数量不能小于lq。这个设计使得锁库存之后,库存展示链路完全不受影响,查询可售库存时也完全不需要关心锁的库存值,大大的降低整个链路上的复杂性,这是一个非常重要的设计。

3. 每次锁定的lq数量,初始化到Redis里进行扣减计数。

多个redis分桶通过redis分桶缓存进行索引:

下单扣减模块

先扣redis分桶库存,成功则继续插入DB明细;失败则兼容走老的DB扣减流程:

合并提交模块

1. 先失效合并提交对应的redis分桶,防止后续继续有交易流量扣减此redis分桶;

2. 根据分桶key扫描此分桶关联的所有扣减明细,计算库存扣减数量,合并扣减DB。

  • 实际Redis分桶扣减的库存数量,以合并下单明细为准,通过扫描明细上的扣减库存总和得到;
  • 这里我们针对数据库明细表,设计了覆盖索引(invId,lockOrderId,quantity),通过sum(quantity) 走索引就能直接得到每个Redis分桶实际扣减的库存;压测和线上效果都表明,此扫描单据的SQL对DB热点扣减的性能影响非常小。

库存回收模块

1. 库存回收指将预锁定的库存释放回收到可售卖的状态,以下几种场景需要回收库存:

  • 商家编辑场景,直接走的DB扣减,redis有剩余库存,而商家编辑时将总库存编辑成0,此时我们需要先释放预锁库存;
  • 临界场景:Redis分桶只有1件库存,DB两件库存,下单两件库存库存,此时将Redis的库存回收到DB后继续扣减。

2. 库存回收在实现上可以直接通过调用分桶合并提交来完成。

防超卖少卖设计

1. 前面锁库存模块也已经提到过,DB可售sq锁到lq,扣减SQL层直接通过 set sq = sq -δq where sq-lq - δq> 0 的方式保证DB不超卖。

2. 而Redis扣减,分桶的剩余库存值不能小于0,保证不超卖;同时如果Redis数据丢了,实际这个Redis分桶库存扣减了多少,以DB合并下单明细为准,也不会少卖。

3. 高并发场景下,下单扣减和合并提交单据扫描并发的情况下,可能会出现少扫描了单据,如果少扫描单据了,则会超卖;我们通过Redis扣减屏障防止此并发场景下的超卖;具体链路如下:

自动锁库存模块

通过热点识别能力,感知交易相关系统的热点品库存查询,提前将满足条件的商品库存进行自动锁库存;只要一开始提前锁了任意数量的库存,后续下单扣减过程中,则会继续自动触发锁库存。

性能优化效果

接下来我们看下合并扣减的效果:

压测效果

从压测效果上看,单行热点扣减场景下,非合并扣减tps峰值约1.4w,合并扣减峰值3.2w;整体提升1倍以上扣减性能(实际线上场景,由于入口做了限流,所以线上达不到压测的流量峰值)。

线上效果

线上由于入口开了限流,库存扣减峰值tps都在7k+,差异体现在扣减成功率和耗时上:

走到合并扣减的热点品,库存扣减成功率在100%,接口扣减耗时7ms+;未走到合并扣减的热点品,库存扣减成功率在80%上下,接口扣减耗时15ms+。


结语

以上则是基于分布式缓存的强一致库存扣减方案的全部内容,欢迎感兴趣的同学一起交流。


来源  |  阿里云开发者公众号

作者  |  聆枫

相关文章
|
23天前
|
消息中间件 人工智能 NoSQL
AgentScope x RocketMQ:打造企业级高可靠 A2A 智能体通信基座
Apache RocketMQ 推出轻量级通信模型 LiteTopic,专为 AI 时代多智能体协作设计。它通过百万级队列支持、会话状态持久化与断点续传能力,解决传统架构中通信脆弱、状态易失等问题。结合 A2A 协议与阿里巴巴 AgentScope 框架,实现高可靠、低延迟的 Agent-to-Agent 通信,助力构建稳定、可追溯的智能体应用。现已开源并提供免费试用,加速 AI 应用落地。
268 36
AgentScope x RocketMQ:打造企业级高可靠 A2A 智能体通信基座
|
16天前
|
人工智能 监控 架构师
AI架构师的诞生:AI+传统DDD模式 = 实现开发效率提升75%
本文以淘宝闪购服务包系统为案例,探索如何借助 AI 技术辅助领域驱动设计(DDD)落地。
AI架构师的诞生:AI+传统DDD模式 = 实现开发效率提升75%
|
11天前
|
存储 缓存 NoSQL
即将开源 | 阿里云 Tair KVCache Manager:企业级全局 KVCache 管理服务的架构设计与实现
阿里云 Tair 联合团队推出企业级全局 KVCache 管理服务 Tair KVCache Manager,通过中心化元数据管理与多后端存储池化,实现 KVCache 的跨实例共享与智能调度。该服务解耦算力与存储,支持弹性伸缩、多租户隔离及高可用保障,显著提升缓存命中率与资源利用率,重构大模型推理成本模型,支撑智能体时代的规模化推理需求。
|
30天前
|
移动开发 weex Android开发
极致体验无小事:Weex购物车基础优化实践
手机淘宝购物车团队在完成Weex技术升级后,聚焦基础体验精细化治理,覆盖暗黑模式适配、热区对齐、皮肤样式优化、适老化改造与多终端兼容。通过舆情、数据与用户视角三轨驱动,实现从功能交付到体验交付的思维升级,打造更流畅、包容、个性化的购物体验。
|
16天前
|
SQL 存储 关系型数据库
从一条慢SQL说起:交易订单表如何做索引优化
本文首先以淘天电商交易订单表线上一条非典型慢 SQL 的深入剖析为切入点,示范如何系统地分析与排查慢 SQL;接着详尽归纳了索引分类、B+Tree 与 B‑Tree 的结构差异、B+Tree 高度估算方法、EXPLAIN 与 Query Profile 等诊断工具的使用,以及索引下推与排序的执行流程等索引优化理论;最后结合日常实践经验,提出了适用于大规模线上集群的索引变更 SOP,并总结了常见的慢 SQL 成因与相应的解决策略。
209 36
从一条慢SQL说起:交易订单表如何做索引优化
|
2天前
|
存储 人工智能 IDE
AI Coding 长文分享:如何真正把工具用起来,从原理到实践
本文从原理到实践系统地分享了如何高效使用AI编程工具。涵盖其底层机制(如Token计算、工具调用、Codebase索引与Merkle Tree)、提升对话质量的方法(如规则设置、渐进式开发)、实际应用场景(如代码检索、绘图生成、问题排查),并推荐了结合AI的编码最佳实践,包括文档、注释、命名规范和安全合规,旨在帮助不同经验水平的开发者真正把AI工具用好。
AI Coding 长文分享:如何真正把工具用起来,从原理到实践
|
10天前
|
数据采集 人工智能 运维
AgentRun 实战:快速构建 AI 舆情实时分析专家
搭建“舆情分析专家”,函数计算 AgentRun 快速实现从数据采集到报告生成全自动化 Agent。
374 30
|
16天前
|
人工智能 搜索推荐 算法
AI热点选品:当推荐系统遇上“热点”,我们需要一场变革
针对传统推荐系统滞后于外部热点的问题,我们构建了“热点AI选品”自动化系统。通过小时级感知、LLM驱动的热点理解与需求推理、多模态素材召回、三级机审过滤及话题聚合技术,实现从热点捕捉到商品分发的端到端闭环,显著提升信息流的新鲜感与用户参与度。
130 12
AI热点选品:当推荐系统遇上“热点”,我们需要一场变革
|
2月前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
924 242
|
2月前
|
机器学习/深度学习 人工智能 算法
PAIFuser:面向图像视频的训练推理加速框架
阿里云PAI推出PAIFuser框架,专为视频生成模型设计,通过模型并行、量化优化、稀疏运算等技术,显著提升DiT架构的训练与推理效率。实测显示,推理耗时最高降低82.96%,训练时间减少28.13%,助力高效低成本AI视频生成。
310 22