14张图深度解密大厂秒杀系统库存设计,不是所有的库存都能支持高并发!

news2024/9/24 11:54:09

作者:冰河
星球:http://m6z.cn/6aeFbs
博客:https://binghe.gitcode.host
源码获取地址:https://t.zsxq.com/0dhvFs5oR

沉淀,成长,突破,帮助他人,成就自我。

大家好,我是冰河~~

相信很多小伙伴都在大厂的秒杀大促中抢购过商品,那大家有没有想过这样一个问题:在秒杀这种高并发大流量的场景下,商品的库存是如何设计呢?怎么才能抗住瞬时高并发的流量呢?

也有不少小伙伴出去面试时,简历上写了秒杀系统,此时面试官通常也会问这样一个问题:你们的秒杀系统库存是怎么设计的呢?要知道,秒杀系统的库存如果只是简单的按照普通商品的库存进行设计,是根本撑不住瞬时的高并发流量的。

今天,冰河就结合多年参与大厂秒杀大促基础架构设计,以及多次保障大促期间下单扣减库存的核心链路稳定的经验,为大家揭秘大厂秒杀系统是如何设计库存的。当然,大部分架构设计和编码实现以及部署上线等内容也都沉淀在冰河技术知识星球的《高并发Seckill秒杀系统》专栏。

大家可以猛戳链接:https://t.zsxq.com/iG6Fq 学习《高并发Seckill秒杀系统》

一、前言

对秒杀系统数据库的读写操作进行优化,并不是简单的进行主从复制和分库分表。而是需要从秒杀特有的瞬时高并发、大流量的业务场景出发,针对场景进行数据库优化。

对于秒杀这种场景来说,关键是要支撑瞬时的高并发、大流量,大量用户抢购商品下单时,会频繁调用查询和更新商品库存的接口,所以,对于商品库存来说,我们需要增强数据库的读写性能。

在具体设计上,就是要对商品的库存进行分库分表和分桶设计,使得商品的库存不再由单数据库进行存储,扩展成多台数据库,并且在每个数据库中,又对商品的库存进行分桶设计。同时,在缓存层面,也需要对商品的库存进行分桶设计

二、库存优化目标

在正式对商品库存进行分库分表和分桶设计之前,我们先来确定下库存优化的目标,也就是分库分表和分桶设计的目标,这样在后续的实现中更有针对性。这里,我主要把库存优化的目标分成了六点:分库设计、分表设计、分桶设计、缓存设计、一致性设计和兼容性设计,如下图所示。

在这里插入图片描述

  • 根据秒杀商品对库存进行分库设计:使得相同秒杀商品的库存能够路由到同一数据库进行处理。
  • 根据秒杀商品对库存进行分表设计:使得相同秒杀商品的库存能够路由到同一数据库中,然后再进一步根据商品id进行分表。
  • 根据秒杀商品对库存进行分桶设计:对于秒杀系统来说,分库分表主要提升的是多场秒杀活动的并发处理能力,而分桶设计主要解决的是单场秒杀活动的并发处理能力。
  • 根据库存的分库分表和分桶方案,设计对应的库存缓存方案:根据库存的分库分表和分桶方案,为商品的分桶库存设计分桶缓存方案:真正扣减商品分桶库存之前会预扣缓存中的分桶库存数据,以提高系统的并发处理能力。
  • 数据一致性设计:在缓存与数据库的数据一致性层面,基于分库分表和分桶设计,在缓存层面实现弱一致性,数据库层面实现强一致性。
  • 兼容性设计:对于新增的商品库存分库分表和分桶设计,要兼容之前的商品库存设计,能够根据简单的配置进行自由切换。

三、分库分表设计

在分库分表的设计上,这里我们使用了三个库实现(实际场景可以根据具体需要灵活配置分库和分表的数量),默认一个商品库和两个库存库,将商品的库存信息从商品表中独立出来,单独进行分库分表和分桶设计。

  • 商品库:在秒杀下单的过程中,主要以读操作为主,比如获取秒杀商品详情信息等。
  • 库存库:在秒杀下单的过程中,主要以写操作为主,主要是在下单过程中扣减商品的库存,分摊数据库的写压力。

这里需要注意的是:在我们实现的秒杀系统中,使用了一个商品库和两个库存库来实现商品库存的分库分表和分桶设计,在实际场景下,大家可以根据实际的业务需要,灵活配置分库、分表和分桶的数量。

对商品库存进行分库分表设计时,一个很重要的设计就是对分片键的设计。所谓的分片键就是指定一个字段,通过这个字段将数据路由到对应的数据库和数据表中。在秒杀系统分片键的设计上,尽量将同一个用户的同一次事务中的相关操作路由到同一个数据库中,降低跨库操作的事务成本。

对于商品库存进行分库分表之后的示意图如下图所示。

在这里插入图片描述

可以看到,对于商品商品库存来说,分库分表后,会分成一个商品库和两个库存库,其中商品库中存放的是秒杀商品信息,主要在用户抢购下单的业务场景中,以读操作为主。库存库中则存放的是库存分桶数据,每个库存库中存放了三个分桶后的库存信息。这些分库分表的数据,大家可以根据实际需要灵活调整。

对于商品库存的分库分表来说,在实际场景下,可以根据商品id进行分片。也就是说,这里我们选择的分片键是商品的id,同一个商品的库存会被路由到同一个数据库中,不会出现跨数据库的操作。

四、库存分桶设计

在分库分表的基础上,为了进一步提升数据库的并发写性能,可以对商品的库存进行分桶存储。当运营人员在配置库存信息时,可以设置库存的总量和分桶数量,比如,要将1500个商品分配到5个分桶中,则每个分桶中会分得300个商品库存,如下图所示。

在这里插入图片描述

这样,每个分桶就能够承担一部分写压力,从而将商品的库存写压力分担出去,使得秒杀系统的库存数据库能够具备更高的并发写能力。

当用户抢购下单时,会根据分桶的数量对用户的id进行取模来定位对应的库存分桶,比如用户的id为10001,目前库存的分桶数量设置为5,则用户抢购下单时,会将当前用户抢购下单时,扣减商品库存的请求路由到分桶1,如下图所示。

在这里插入图片描述

用户id为10002的用户抢购下单时,扣减商品库存的请求会被路由到分桶2,如下图所示。

在这里插入图片描述

可以看到,用户抢购下单时,扣减商品库存的请求会被路由到不同的分桶中,这样就可以大大降低扣减商品库存的并发写冲突问题,提升扣减商品库存的并发写性能。

这里,还有一个问题就是对商品的库存进行分桶设计后,每个分桶中保存的是当前商品的一部分库存信息,那如何确定商品的总库存呢?其实有两种方案和解决这个问题。

  • 第一个方案就是在商品数据表中存储商品的总库存和分桶数量,每个分桶中存储当前分桶的库存信息即可。

  • 第二个方案就是在多个分桶中选择一个主分桶用来存储商品的总库存。

  • 第三个方案就是在商品数据表中存储商品的总库存和分桶数量,每个分桶中存储当前分桶的商品总库存和当前可用库存。

考虑到对商品库存的并发写操作,以及后续运营人员可能要调整商品的库存信息,这里我们采用的是方案三,也就是在商品数据表中存储商品总库存和分桶数量,每个分桶中存储当前分桶的商品总库存和当前可用库存。如下图所示。

在这里插入图片描述

运营人员在设置商品库存时,将商品的总库存和分桶数量存储到商品库,每个分桶中存储当前分桶的总库存和可用库存。

五、分桶库存扣减策略

我们对库存进行分库分表和分桶设计后,在实际场景中,大部分情况下都是路由到不同库存分桶的流量是存在差异的,这就会导致不同库存分桶中的库存剩余量有所不同,比如,id为10001的用户抢购下单时,会被路由到分桶1,id为10002的用户抢购下单时,会被路由到分桶2。

有可能存在的一种情况是:此时分桶1中没有库存了,分桶2中有库存,那对于id为10001的用户来说,该怎么处理呢?此时,我们可以考虑三种方案:

方案1: 设计库存分桶的“争抢”机制,类似Java中的Fork/Join框架,如果当前分桶中的库存不足,则按照一定的规则“争抢”其他分桶中的库存。

方案2: 每个分桶中预留一些冗余的库存,某个分桶库存不足,向其他分桶借用。

方案3: 路由到不同库存分桶的用户看到的剩余库存量不同,如果某个分桶的库存不足,直接向路由到该分桶的用户提示库存不足。

这三种方案各有利弊,经过对秒杀这种场景的权衡,我们最终采用的是方案3。要知道,在秒杀绝大部分场景下,都是大量的用户去抢购有限数量的商品,大部分情况下,所有分桶的库存会被瞬间抢购一空。

那有没有一些极端情况,某些分桶中的库存无法售罄呢?这种情况不能说没有,有可能会出现,但是概率极低。如果确实存在某些分桶中的库存无法售罄的情况,则可以通过人工干预的方式收缩库存分桶,将没有售罄的分桶库存收缩到一个分桶中,这样将相当于库存没有分桶了,后续所有的请求都会被路由到同一个库存分桶中,最终库存都会被售罄。

方案1和方案2在实现上比较复杂,要充分考虑在高并发、大流量场景下如何实现库存的争抢机制,并要考虑不能出现库存超卖和少卖的问题,无疑是在系统的架构设计和实现层面增加了复杂度。

在这种秒杀场景下,大可不必非要实现方案1和方案3,换个角度思考,对于平台和商户来说,保证所有商品都能售罄,并保证数据一致。对于用户来说,完全必要保证库存数据的强一致性,只要保证用户能看到对应分桶中的库存就可以了,完全没必要保证用户看到库存数据的强一致性。

六、缓存与一致性设计

对于商品的库存在数据库层面进行分桶设计是远远不够的,要知道MySQL单行并发写的TPS大概在300~500之间,即使我们对商品进行了分库分表和分桶设计,如果将秒杀系统扣减库存的流量直接打入数据库,哪怕部署了MySQL集群,估计也很难抗下所有的并发流量。所以,我们同样要对商品库存在缓存中进行分桶设计。

商品库存在缓存层面的分桶设计与在数据库层面的分桶设计规则保持一致,例如,运营人员要将1500个商品分配到5个分桶中,则每个缓存分桶和数据库分桶中都会分得300个商品库存,如下图所示。

在这里插入图片描述

当用户抢购下单时,同样会根据分桶的数量对用户的id进行取模来定位对应的库存分桶,先预扣缓存分桶中的库存,然后进行下单操作,最后扣减数据库分桶中的库存,比如用户的id为10001,目前库存的分桶数量设置为5,则用户抢购下单时,会将当前用户抢购下单时,扣减商品库存的请求路由到分桶1,如下图所示。

在这里插入图片描述

此时,就会将id为10001的用户扣减商品库存的请求路由到缓存分桶1来预扣商品库存,预扣成功就会构建订单数据并保存,最后扣减数据库分桶1中的库存数据。

如果用户的id为10002,目前库存的分桶数量设置为5,则用户抢购下单时,会将当前用户抢购下单时,扣减商品库存的请求路由到分桶2,如下图所示。

在这里插入图片描述

此时,就会将id为10001的用户扣减商品库存的请求路由到缓存分桶2来预扣商品库存,预扣成功就会构建订单数据并保存,最后扣减数据库分桶2中的库存数据。

这里,还有一个问题就是如何同步缓存中分桶中的库存数据与数据库分桶中的库存数据呢?其实,设计起来也比较简单,就是运营人员设置或者调整商品库存和分桶数量时,会将计算出来的商品分桶库存写入数据库,写入成功后,更新缓存中的分桶库存数据即可。缓存中的商品分桶库存保持弱一致性,数据库中的商品分桶库存保持强一致性。如下图所示。

在这里插入图片描述

当运营人员设置商品库存和分桶数量时,会将商品的总库存和分桶数量存储到商品数据表,每个分桶中存储当前分桶的总库存和可用库存,当数据库分桶中的商品库存数据设置成功后,将其同步到缓存中,缓存中的商品分桶库存规则与数据库中的商品分桶库存规则相同,同时,缓存中的分桶库存数据保持弱一致性,数据库中的分桶库存数据保持强一致性。

七、重置和调整分桶设计

运营人员难免会调整秒杀商品的库存信息,比如原来的商品库存为1500,后来想调整成1000或者2000,所以,我们的秒杀系统要支持运营人员动态的调整秒杀商品的库存,以此对秒杀商品的库存进行实时调整,运营人员调整库存时,会涉及到三种情况,分别如下所示。

(1)第一种情况是调整商品库存,但是分桶数量不变,如下图所示。

在这里插入图片描述

(2)第二种情况是商品库存不变,调大或者调下分桶数量,如下图所示。

在这里插入图片描述

在这里插入图片描述

(3)第三种情况是既调整了商品库存,又调整了分桶数量,如下图所示。

在这里插入图片描述

其实,这三种情况在秒杀系统的实现中,本质上就是对商品库存和分桶数量的调整,秒杀系统要支持运营实时调整这些策略。

八、总结

本章,主要对商品的库存进行了分库分表和分桶设计。首先,简单描述了本章的需求。随后,对库存优化的目标进行了阐述。紧接着对库存的分库分表和分桶进行了设计和说明。接下来,对商品库存分库分表和分桶涉及到的缓存数据进行了设计,并对缓存数据与数据库数据的一致性进行了设计。最后,对重置和调整商品库存的分桶数据进行了设计。

好了,今天就到这儿吧,我是冰河,我们下期见~~

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

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

相关文章

应用在多钥匙应用程序-门锁、遥控器等领域的电容式触摸芯片-GT308L

触摸IC是一种集成了触摸感应技术的芯片,具有快速响应、高精准度和耐用性强的优点。可以实现高灵敏度的触控和准确的指令响应。在智能门锁的设计中,触摸IC不仅可以实现密码输入、指纹识别等功能,还可以与智能家居系统进行联动控制,…

【编程底层原理】Java常用读写锁的使用和原理

一、引言 在Java的并发世界中,合理地管理对共享资源的访问是至关重要的。读写锁(ReadWriteLock)正是一种能让多个线程同时读取共享资源,而写入资源时需要独占访问的同步工具。本文将带你了解读写锁的使用方法、原理以及它如何提高…

行人3d目标检测-车辆3d目标检测-3d目标检测(代码+教程)

在计算机视觉领域,准确地识别并定位物体对于多种应用来说至关重要,比如自动驾驶、机器人导航以及增强现实等。其中,三维边界框(3D Bounding Box)估计是一项关键技术,它允许系统不仅能够检测到图像中的物体位…

JavaScript中Windows对象下的属性和方法

1.Windows对象概念 所有的浏览器都支持Windows对象。它表示浏览器窗口 2.Boom概念 Boom:是指浏览器对象模型,它使javaScript有能力与浏览器进行对话 3.DOM概念 DOM:是指文档对象模型,通过它可以访问HTML文档中的所有元素 HT…

达梦-华为鲲鹏ARM架构下性能测试最佳实践

一、测试综述 1.1 测试目的 本次测试的目的是验证达梦数据库,在鲲鹏服务器下,不同服务器参数基于sysbench性能压力测试的表现。本次参数是根据为华为鲲鹏arm服务器调优十板斧内建议值调整 成长地图-鲲鹏开发套件开发文档-鲲鹏社区 1.2 通用指标 指标…

SpringBootWeb响应

2. 响应 前面我们学习过HTTL协议的交互方式:请求响应模式(有请求就有响应) 那么Controller程序呢,除了接收请求外,还可以进行响应。 2.1 ResponseBody 在我们前面所编写的controller方法中,都已经设置了…

华为云长江鲲鹏深度赋能,大势智慧稳居“实景三维+AI”领域排头兵

本文转自长江日报大武汉客户端 走出象牙塔第10年,武汉大势智慧科技有限公司(以下简称“大势智慧”)已成长为国内三维技术创新及应用领域龙头企业,其自主研发的“重建大师”等三维测绘软件系统在各级测绘系统占有率达到87.5%。 这…

NLP 文本匹配任务核心梳理

定义 本质上是做了意图的识别 判断两个内容的含义(包括相似、矛盾、支持度等)侠义 给定一组文本,判断语义是否相似Yi 分值形式给出相似度 广义 给定一组文本,计算某种自定义的关联度Text Entailment 判断文本是否能支持或反驳这个…

Windows系统修改Tomcat虚拟机内存参数

文章目录 I 修改Tomcat虚拟机内存参数基于tomcat管理程序进行配置基于setenv文件进行配置II 查看服务器状态/manager/status 查看服务器状态manager/jmxproxy 查询Tomcat指标I 修改Tomcat虚拟机内存参数 基于tomcat管理程序进行配置 查看堆内存分配情况: jmap -heap pid jst…

【Kubernetes知识点】解读HPA的 thrashing(抖动)问题

【Kubernetes知识点】解读HPA的 thrashing(抖动)问题 目录 1 概念 1.1 什么是 Thrashing 现象?1.2 HPA 中 Thrashing 产生的原因1.3 解决 Thrashing 的优化措施 1.3.1 设置合适的阈值1.3.2 使用自定义指标和基于负载的自动扩缩1.3.3 增加扩…

增强GPT4v的Grounding能力,video-level

开源链接: appletea233/AL-Ref-SAM2: AL-Ref-SAM 2: Unleashing the Temporal-Spatial Reasoning Capacity of GPT for Training-Free Audio and Language Referenced Video Object Segmentation (github.com) In this project, we propose an Audio-Language-Refe…

力扣最热一百题——最小覆盖子串

目录 题目链接:76. 最小覆盖子串 - 力扣(LeetCode) 题目描述 示例 提示: 解法一:滑动窗口 1. 初始化 2. 构建 mapT 3. 滑动窗口 4. checkT 方法 5. 返回结果 Java写法: 运行时间 C写法&#x…

[Python学习日记-29] 开发基础练习2——三级菜单与用户登录

[Python学习日记-29] 开发基础练习2——三级菜单与用户登录 简介 三级菜单 用户登录 简介 该练习使用了列表、字典、字符串等之前学到的数据类型,用于巩固实践之前学习的内容。 三级菜单 一、题目 数据结构: menu { 北京: { 海淀: { …

纯css实现选项卡

<span class"flex tab" ><view :class"tabStyle(1)" click"tabClick(1)">变形监测</view><view :class"tabStyle(2)" click"tabClick(2)">渗流渗压</view></span>tabIndex:1tabClick…

src漏洞挖掘 | 记某学校网站的一次漏洞挖掘

&#x1f497;想加内部圈子&#xff0c;请联系我&#xff01; &#x1f497;文章交流&#xff0c;请联系我&#xff01;&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领…

【附实例】Python字典的各种操作

一、字典理解 Python 字典是一种可变容器模型&#xff0c;且可存储任意类型对象。字典的每个键值对用冒号 : 分割&#xff0c;每对之间用逗号 , 分割&#xff0c;整个字典包括在花括号 {} 中。 二、访问字典 ①.访问键名 my_dict {name: Alice, age: 30, city: New York} k…

显示数量以及坐标区间

import re import numpy as np import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties# 动态加载字体文件 font_path /usr/local/sunlogin/res/font/wqy-zenhei.ttc # 替换为实际字体路径 my_font FontProperties(fnamefont_path)# 定义日志…

【折腾笔记】雷池WAF+FRP+Nginx实现安全可靠的内网穿透

前言 在网上看了许多关于WAFFRPNginx的方式来保护内网穿透的Web服务&#xff0c;但是在网上搜寻的结果都是将WAF部署在了源站上面&#xff0c;由于我的Web服务都是部署在NAS上面&#xff0c;然后使用Frp来穿透访问的&#xff0c;我认为WAF应该部署在服务器上面比较合适&#x…

基于STM32F103C8T6单片机的农业环境监测系统设计

本设计是基于STM32F103C8T6单片机的农业环境监测系统&#xff0c;能够完成对作物的生长环境进行信息监测和异常报警&#xff0c;并通过手机APP来实现查看信息和设定阈值的功能。为了实现设计的功能&#xff0c;该系统应该有以下模块&#xff1a;包括STM32单片机模块、水环境PH值…

css禁止图片保存,CSS中的图片保存方法

“css中的图片”指的就是镶在CSS样式表中的图片。在我们用在浏览器保存网页时&#xff0c;很多时候&#xff0c;下载网页里的图片都下载不到&#xff0c;这样的话就会使网页非常不美观。所以&#xff0c;今天小编就给大家介绍集中保存方法。 以下是几种保存方法。 (一)使用网…