库存预占架构升级方案设计-交易库存中心
背景介绍
伴随物流行业的迅猛发展,一体化供应链模式的落地,对系统吞吐、系统稳定发出巨大挑战,库存作为供应链的重中之重表现更为明显。近三年数据可以看出:

接入商家同比增长37.64%、货品种类同比增长53.66%
货品数量同比增长46.43%、仓库数量同比增长18.87%
通过分析过往大促流量,分钟级流量增长率为75%,大促仓内反馈三方订单下传不及时,库存预占吞吐量和性能是导致订单积压因素之一。目前库存使用mysql数据库作为接单预占的扛量手段,随着一体化供应链建设以及重点KA商家不断接入,现有库存架构在业务支撑上存在风险和缺陷。
此外未来3到5年业务增长、流量增长预计增长5-10倍。为避免系统性能和技术架构缺陷导致业务损失,轻量级库存架构势在必行。
// 名词解释:
库存预占:是指消费者拍下商品订单后,库存先为该订单短暂预留,预留的库存即为预占库存。
架构原则
架构:是⾯向问题,解决问题的手段。 库存系统的问题: 非功能性:1.高并发 2.系统稳定性(容灾) 3.数据一致性 功能性: 1.业务复杂 2.数据一致性
系统设计
设计思路
1.当前库存系统瓶颈在哪里?
1.抗写流量,数据库成为瓶颈点。
2.如何解决系统瓶颈?
1.由高并发组件Redis替代数据库。
3.利用Redis需要解决哪些问题?
1.防超卖,异步写数据库保证最终一致性。

总体设计
•扛量部分:库存性能瓶颈在预占,传统架构主要依靠数据库事务保持数据一致以及数据读写;新版架构设计将数据扛量部分移植到Redis,利用Redis高性能吞吐解决高并发场景下数据读写。
•数据回写:Redis进行扛量削峰,后续数据仅用于记账,最终牺牲数据的短暂一致性达到削峰的目的。
•差异部分:老版本库存预占设计仅依靠数据进行数据处理,新版设计依靠切量配置建数据切换到Redis,利用Redis高读写进行削峰操作。

详细设计
•主流程:

•库存初始化:竞态条件利用Redis watch命令来实现锁等待,解决并发场景数据不一致问题。
•LUA执行器:将原子操作指令/复用指令封装到LUA脚本中以减少网络开销。
•补偿机制:i> 执行流程中所有业务异常发生时会同步发起反向操作请求;ii> 反向操作执行异常后会提交异步反向操作任务;iii>异步任务执行异常后,依赖监q控系统扫描异常单据或异常库存并修改异常库存量

•回溯回写:任务落库后发出mq组装参数调用数据回写服务,数据回写服务操作库存数量;同时回写redis数据,释放预占量库存数据;更新任务库数据状态

数据结构
•库存记录索引:{deptNo|goodsNo|warehouseNo}|stockStatus|stockType|goodsLevel
•hashTag:{deptNo|goodsNo|warehouseNo}|stockStatus|stockType|goodsLevel
•可售库存数量:usableKey:{库存记录索引}
•扣减库存量:usableSubtractKey:{库存记录索引} ,记录Redis到DB执行期间减库存量
•预占防重key:operateKey:{库存记录索引:单号} 防重key防并发重复请求
•回滚防重:rollbackOperateKey:{库存记录索引}
•缺量预占库存量:ullageOperateKey:{库存记录索引}
•扣减库存单据记录:hSetrecord: {库存记录索引}
| key | 预占 | 缺量预占 | 回滚 | 回写 |
| 可售库存数量 | - | - | + | 不变 |
| 扣减库存量 | + | + | - | - |
| 预占防重key | + | + | - | 不变 |
| 回滚防重 | 不变 | 不变 | + | 不变 |
| 缺量预占库存量 | 不变 | + | 反向 | 不变 |
| 扣减库存单据记录 | + | + | - | - |
Redis&DB
•首先进行redis&从库数据比对,若存在差异则对主库进行校验
•比对过程中,DB中sku明细行进行锁定(for update),比对逻辑为DB可用库存量==(Redis可用库存量+Redis预占量)
•有差异,报警且触发SDK可用量过期,同时矫正预占量

容灾方案

// 对系统容错/降级、监控机制(空间换稳定性,两份redis,故障3次丢数),流量分布材料,618流量大、峰值数据切量。数据不一致,多个商家,不能超过5分。
预占任务持久化:mysql需要将核心属性字段数据持久化:事业部,商品编码,仓编码,等级,库存类型,库存状态,预占库存量,任务状态;调度执行完成后需要更新stockTask状态为完成
初始化:
(1) lock db
(2) sum stockTask
(3)使用DB可用库存初始化Redis可用库存,stockTask预占量初始化Redis预占量
(4)Redis库存回滚,如果预占量key不存在,该key不需要回滚
性能结果

23年618大促


切量细则
切量细则
冷热数据
OMS库存冷热装置
预占架构升级切量重点key监控
库存预占架构升级切量商家
架构升级切量商家明细2
已切量商家
反向切量
原有设计中存在以下名单 禁止切量商家:优先级较高,一旦在名单中,禁止切量 批次库存商家:批次库存管理商家,目前该部分能力尚未建设 动态质押商家:物流金融业务,目前该部分能力尚未建设 切量名单商家:该部分为切量商家 原有切量流程:!禁止切量->!批次库存->!动态质押->切量名单中,通过以上校验为切量商家。 原有流程在增量商家中需要手动将商家配置到切量名单中才可进行切量操作,对于新增商家场景操作不变,且原有流程中逻辑库存名单为痛点:逻辑库存的启用配置在事业部主数据中,不在库存侧。 新版切量流程中对切量名单进行优化,将原来切量名单商家拆分成非逻辑库存名单、逻辑库存两个名单,其中: 非逻辑库存名单:包含可切量商家 逻辑库存名单:逻辑库存商家,该部分不可切量
原流程新流程对切量商家名单进行优化,拆分成非逻辑库存名单、逻辑库存两个名单
构建模型(批次库存&内存模型待续)

Redis存储数据结构
•MD生成规则工具集
◦逻辑库存MD5工具
StringBuffer md5Key = new StringBuffer();md5Key.append(logicWarehouseStock.getGoodsNo()+"_"+logicWarehouseStock.getWarehouseNo()+"_"+logicWarehouseStock.getOwnerNo()+"_"+logicWarehouseStock.getDeptNo()+"_"+logicWarehouseStock.getStockType()+"_"+logicWarehouseStock.getGoodsLevel());if(StringUtils.isBlank(logicWarehouseStock.getFactor1())){md5Key.append("_0");}else {md5Key.append("_"+logicWarehouseStock.getFactor1());}if(StringUtils.isBlank(logicWarehouseStock.getFactor2())){md5Key.append("_0");}else {md5Key.append("_"+logicWarehouseStock.getFactor2());}if(StringUtils.isBlank(logicWarehouseStock.getFactor3())){md5Key.append("_0");}else {md5Key.append("_"+logicWarehouseStock.getFactor3());}if(StringUtils.isBlank(logicWarehouseStock.getFactor4())){md5Key.append("_0");}else {md5Key.append("_"+logicWarehouseStock.getFactor4());}if(logicWarehouseStock.getYn()== null){md5Key.append("_1");}else {md5Key.append("_"+logicWarehouseStock.getYn());}md5Key.toString().hashCode()
•批次库存MD5工具
public void fillMd5Value(){StringBuffer md5Key = new StringBuffer();md5Key.append(warehouseNo);md5Key.append("_");md5Key.append(goodsNo);md5Key.append("_");md5Key.append(goodsLevel);md5Key.append("_");md5Key.append(stockType);//遍历类字段不遍历map是为了控制MD5的组成顺序Class clazz = BatchAttrStock.class;Field[] fields = clazz.getDeclaredFields();try {int batchFieldCount = 0 ;for (Field field : fields){BatchAttrEnum attrEnum = BatchAttrEnum.batchFieldEnumMap.get(field.getName());//不是批属性的字段不进入MD5的组成if (attrEnum == null){continue;}batchFieldCount ++;field.setAccessible(true);Object value = field.get(this);if (value == null ){md5Key.append("0");continue;}if(field.getType().toString().contains("String")){md5Key.append(value);continue;}if(field.getType().toString().contains("Date")){Date timeField = (Date) value;md5Key.append(timeField.getTime());continue;}throw new RuntimeException(attrEnum.getField()+"填充MD5异常");}//默认50个批属性长度,长度不够0补齐int remainLength = 50 - batchFieldCount;String str = String.format("%0"+remainLength+"d", 0);md5Key.append(str);}catch (Exception e){throw new RuntimeException("填充MD5异常.");}md5Key.append(yn);String md5Value = MD5Util.md5(md5Key.toString());setMd5Value(md5Value);}
•MD&ID&属性保存工具
待续。。。。
相关文章:
库存预占架构升级方案设计-交易库存中心
背景介绍  伴随物流行业的迅猛发展,一体化供应链模式的落地,对系统吞吐、系统稳定发出巨大挑战,库存作为供应链的重中之重表现更为明显。近三年数据可以看出:  接入商家同比增长37.64%、货…...
【redis】ssm项目整合redis,redis注解式缓存及应用场景,redis的击穿、穿透、雪崩的解决方案
目录 一、整合redis 1、介绍 1.1、redis(Remote Dictionary Server) 1.2、MySQL 1.3、区别 2、整合 2.1、配置 2.2、文件配置 2.3、key的生成规则方法 2.4、注意 二、redis注解式缓存 1、Cacheable注解 2、CachePut注解 3、CacheEvict注解…...
chatGPT对英语论文怎么润色呢?
chatGPT对英语论文怎么润色呢? 回答1: 润色英语论文是一项重要的任务,它有助于提高论文的质量、语法准确性和清晰度。以下是一些关于如何润色英语论文的建议: 语法和拼写检查: 使用拼写和语法检查工具,如…...
【机器学习4】降维
常见的降维方法有主成分分析、 线性判别分析、 等距映射、 局部线性嵌入、 拉普拉斯特征映射、 局部保留投影等。 1 PCA最大方差角度理解 PCA无监督学习算法。 PCA的目标, 即最大化投影方差, 也就是让数据在主轴上投影的方差最大。 在黄线所处的轴上&…...
注册商标有助于企业拓展市场渠道
拓展市场渠道 注册商标有助于企业拓展市场渠道。在商业合作和交易中,消费者往往更加倾向于选择有知名度和信誉的品牌。通过注册商标,企业可以树立自己的品牌形象,提高品牌知名度和美誉度,从而更好地开拓市场和拓展业务。同时&…...
推荐能用ios端磁力下载工具
关于ios端磁力下载工具,之前的文章给大家介绍过2个,分别是雷电下载和闪电下载。但是如今因为不可抗力和苹果商店对于磁力下载和云盘功能的限制,目前这两款工具已经不能够使用了。也就是说免费的下载工具已经没有了,毕竟实现ios端这…...
网页文档阅读的学习笔记
1. 阅读邮件 我是一名人工智能专业的博士生,请你帮我总结此页面的要点...
mysql图书管理系统(49-56)源代码
-- 九、 子查询 -- 无关子查询 -- 比较子查询:能确切知道子查询返回的是单值时,可以用>,<,,>,<,!或<>等比较运算符。 -- 49、 查询与“俞心怡”在同一个部门的读者的借…...
使用Docker部署开源分布式任务调度系统DolphinScheduler
🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 使用Docker部署开源分布式任务调度系统DolphinScheduler 文章目录 使用Docker部署开源分布式任务…...
光猫桥接与直接拨号的对比
近期搬家,经历了一次拉宽带,换光猫,购置路由器的过程,有一些总结记录下来,备忘 装宽带之前已经知道桥接的好处就是可以路由器拨号,避免拉胯的光猫拖慢网速,但具体有什么坏处也不清楚࿰…...
使用cpolar配合Plex搭建私人媒体站并实现远程访问
文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频,已经算是生活中稀松平常的场景了,特别是各…...
Web APIs——综合案例
1、学生就业统计表 2、渲染业务 根据持久化数据渲染页面 步骤: ①:读取localstorage本地数据 如果有数据则转换为对象放到变量里面一会使用它渲染页面如果没有则用默认空数组[]为了测试效果,可以先把initData存入本地存储看效果 ②&…...
2023.10月考试战报|华为认证HCIP考试100%通过
相关文章: 考试战报|2023.7月-8月思科认证、华为认证-CSDN博客 2023.4月及5月最新HCIP 考试战报来袭_厦门微思网络的博客-CSDN博客 HCIP 3-4月考试战报_厦门微思网络的博客-CSDN博客 2023年HCIP/CCNP考试战报_厦门微思网络的博客-CSDN博客 2023年10月࿰…...
Oracle 三种分页方法(rownum、offset和fetch、row_number() over())
Oracle的三种分页指的是在进行分页查询时,使用三种不同的方式来实现分页效果,分别是使用rownum、使用offset和fetch、使用row_number() over() 1、使用rownum rownum是oracle中一个伪劣,它用于表示返回的行的序号。使用rownum进行分页查询的方…...
13. 一文快速学懂常用工具——Kubernetes 命令
本章讲解知识点 Kubernetes 基本命令本专栏适合于软件开发刚入职的学生或人士,有一定的编程基础,帮助大家快速掌握工作中必会的工具和指令。本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同进步。…...
【Linux】shell执行文件清理
#!/usr/bin/env bash ################################################################################# # 程序名称: AutoClearFiles.sh # 创建日期: 2022-11-16 # 作者: evens # 使用说明: …...
Android MotionLayout
MotionLayout exends ConstraintLayout(动画框架 过渡) View动画 API1 属性动画API11 过渡动画API18 root.width RootViewWidth TransitionManager.beginDelayedTransition(view) 过渡动画 可以改变其大小和流畅性 Fade 可以改变透明度 通过TrasitinManager管理 Go:动态替…...
50基于matlab的传统滤波、Butterworth滤波、FIR、移动平均滤波、中值滤波、现代滤波、维纳滤波、自适应滤波、小波变换
基于matlab的传统滤波、Butterworth滤波、FIR、移动平均滤波、中值滤波、现代滤波、维纳滤波、自适应滤波、小波变换,七种滤波方法,可替换自己的数据进行滤波,程序已调通,可直接运行。 50matlabButterworth滤波 (xiaohongshu.com)…...
【2021研电赛】基于深度学习的蛋白质与化合物结合性质预测
本作品介绍参与极术社区的有奖征集|分享研电赛作品扩大影响力,更有重磅电子产品免费领取! 获奖情况:三等奖 1.作品简介 针对药物发现过程中的药物筛选问题,本设计基于深度学习提出新的神经网络结构和数据处理方式用于预测蛋白质与化合物之…...
物联网中的毫米波雷达:连接未来的智能设备
随着物联网(IoT)技术的飞速发展,连接设备的方式和效能变得越来越重要。毫米波雷达技术作为一种先进的感知技术,正在为物联网设备的连接和智能化提供全新的可能性。本文将深入探讨毫米波雷达在物联网中的应用,以及它是如…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
