从一个电商平台的库存同步谈性能优化和方案落地-程序员宅基地

技术标签: c#  java  数据库  

目录

下面的案例来自笔者的实际工作经历,涉及到的系统是笔者负责开发和维护的,一个国外的电商平台。

如果你对电商系统有所了解,将有助于你理解下面提到的业务。

如果你没有相关的知识背景,也没有关系,我会尽可能简化地将业务讲给你,并且只要求你理解关键概念即可。

背景

事情的起因是平台的某位高级主管的一封邮件,其中提到商品全量库存的实时性太低,需要各个部门的人协力解决。

库存同步相关概念

先介绍一下电商平台的一些基本概念。

库存就是仓库中某个SKU(最小库存单元)在仓库中实际有量。

比如某型号灰色8核16G内存的笔记本电脑就是一个SKU,在仓库中这个SKU有100台,那么它的库存量就是100。

  • 全量和增量库存

仓库每天都会把自己实际的库存量统计出来,这就是全量库存,仓库把库存量发送给各个销售终端,这就是全量库存同步

同时,为了保证库存的实时性,防止超卖(卖出比实际库存量更多的商品,仓库无法发出货品,有可能导致客诉)和仓库有货但客户买不到的情况,仓库会把库存的变化量也实时分发到各个终端,这个库存的变化量就是增量库存

举例来说,上面的那个SKU笔记本电脑有一台送到摄影棚去拍照了,那么这台就无法销售了,仓库就会推送一个-1的增量库存到销售终端;而如果它收到了消费者的退货,退货入库以后,将会推送一个+1的增量库存。

  • 多店铺与分盘

电商平台一般都会有多个店铺入驻,例如3C这个分类下面,可能有苹果、华为、三星、小米等店铺。

不同店铺的库存是独立的。

有时候一个SKU在多家店铺都有售,iPhone X/太空灰色/256GBXXX苹果平台旗舰店XXX手机大世界店XX苹果折扣店 就是三个不同的库存记录。

这就是多店铺库存

作为分销商,它的仓库中放着不同平台、不同品牌的商品。例如上面的手机,在深圳、广州、上海三个地区仓库都有货,并且是分别卖给天猫和京东的,那么它的库存记录就有6条,分别是:

No. 仓库 渠道
1 深圳 天猫
2 深圳 京东
3 广州 天猫
4 广州 京东
5 上海 天猫
6 上海 京东

这就是分盘库存

  • 库存清点时间和最后更新时间

在实际操作中,为了保证数据的准确性,平台会对库存的时间进行校验。

例如,仓库在凌晨 01:00 清点出某SKU库存量为100,则这条库存记录的库存清点时间就是01:00。

仓库在01:00清点完以后,在02:00收到了一个退货,那么就会推送一个+1的增量到平台。

一般情况下,全量先发出,平台应该先收到全量100,再收到增量+1,最后为101。

但如果由于某个中间环节出了问题,先收到增量+1,在收到全量100,那么最终的库存量将是100。全量库存会直接覆盖平台现在的库存量。

因此,如果有一个最后更新时间,记录是02:00收到的增量,那么当01:00的全量过来的时候,由于比增量时间要早,将被平台视为作废。

库存流转过程

实际的库存数据流转过程往往不是 「仓库——>平台」 这么短的链路,实际链路总是很长的:

不同系统的性能不同,实现方式不同,越长的链路时延问题就越严重。

方案

问题分析

想要解决问题,首先要分析问题。作为平台技术负责人,我先统计了平台最近一个月的库存同步时间,大约是150分钟,并且每隔几天会延长几分钟。

然后我统计了最近一段时间全量库存的数据变化量,仅仅10天就增加了5w。

  • 问题定义: 目前看来,从平台角度来讲,随着库存数据量的增加,处理时间不断延长,再加上整个链路很长,造成全量库存数据的实时性很差。

头脑风暴

分析完问题,我立即召开了团队的人员讨论解决方案,经过大家讨论,可以优化的环节是下面几个:

  1. 提升硬件配置

当你拼命练跑步避免迟到的时候,也许给你一辆车就解决问题了。

部门服务的资源紧张,配置极低。

  1. 修改消息处理逻辑

目前库存数据拆分粒度很细(分店铺分仓库分门店),加上网络时延,会造成处理时间延长。

  1. 优化消息处理的逻辑

库存数据由消息中心统一处理,消息中心会处理订单、商品、价格、会员、库存等等多种类型的数据,效率不高。

  1. 优化全量库存同步

从平台处理数据的代码流程着手优化。

确定方案

对于方案1需要金主批钱,方案2需要多个系统修改,这些不好谈;方案3需要改动整体架构,工作量巨大。

对于解决燃眉之急,方案4的可行性最高,改动量和影响范围最小。

细化方案

方案4优化全量库存同步,具体细化为下面三个方面

  1. 业务精简和标准化
  2. 数据处理高性能
  3. 队列操作高性能

下面在实施的时候一一详细说明。

实施

业务精简和标准化

业务精简和标准化分为下面几个方面:

  1. 全增隔离

目前全量和增量库存同步使用同一个队列名,通过字段判断是全量还是增量。 这样增加了代码的复杂度,而且原子性不好。 全量库存单独队列,与增量同步隔离。

  1. 剥离日志

修改库存以后需要记录详细变更日志,日志的实时性要求不高,将改操作剥离为单独的队列进行处理。

  1. 剥离新建

目前同步库存之前先判断该商品是否存在,如果存在再判断该商品在库存表是否有记录,如果没有则新建记录,有则更新库存。

由于随着数据量的增加,新建的记录(每天1k到3k之间)所占的比重越来越小,因此将新建的操作也单独剥离为一个队列进行处理。

优化消息处理的逻辑

平台为分布式系统,消息处理需要从注册中心调用远程Dubbo服务,首先将数据处理移动到Dubbo服务中完成,避免了频繁调用Dubbo服务,另外使用多线程处理消息,最大限度利用多核心的优势。

关于线程池的使用,可以参考这篇文章:使用ThreadPoolExecutor构造线程池

//构造线程池
private static ExecutorService executorService = new ThreadPoolExecutor(
16,
32,
10L,
TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(
                2048),new ThreadFactoryBuilder()
                     .setNameFormat("BatchSyncFullInventory-Pool-%d").build(),
                     new ThreadPoolExecutor.CallerRunsPolicy());
复制代码

经过上面的优化,目前处理的时间有了大幅度降低:

队列操作高性能

经过上面的优化,发现每处理2k条消息,处理时间在1s以内,但出队时间接近15s。

因此,下面的优化重点是提高队列的操作性能。

由于Redis频繁的操作,会造成RTT(网络时延)不断延长,可以使用管道来降低RTT。

下面是Spring Data Redis使用管道的方式:

//从队列中循环取出消息, 使用管道, 减少网络传输时间
List<Object> msgList = redisTemplate.executePipelined(new RedisCallback<Object>() {
    @Override
    public Object doInRedis(RedisConnection connection) throws DataAccessException {
        for (int i = 0; i < batchSize; i++) {
            connection.rPop(getQuenueName().getBytes());
        }
        return null;
    }
});
复制代码

理论上是这样的,需要有实际的数据支撑,因此需要通过做实验来验证方案的效果。

首先,在测试环境对比了三种不同的出队方式的性能,分别是单线程循环出队、多线程循环出队和单线程管道出队。

测试发现使用管道出队两千次,只需要70毫秒左右。

最终,使用了 管道+多线程,库存消息的处理时间降到了30分钟左右:

关于管道的使用,可以参考这篇文章:Redis管道技术

CPU使用过高

虽然发布到生产以后,处理时间有了大幅度降低,但是经过监控发现,Redis的CPU使用率一直居高不下。

对于监听队列的场景,一个简单的做法是当发现队列返回的内容为空的时候,就让线程休眠几秒钟,等队列中累积了一定量数据以后再通过管道去取,这样就既能享受管道带来的高性能,又避免了CPU使用率过高的风险。

//如果消息的内容为空, 则休眠[10]秒钟以后再继续取数据,防止大批量地读取redis造成CPU消耗过高
if (CollectionUtils.isEmpty(messageList)) {
    Thread.currentThread().sleep(10 * 1000);
    continue;
}
复制代码

总结

  • 方案设计:头脑风暴与可行性评估
  • 逻辑精简化 : 剥离不必要的操作
  • 流程标准化 : 梳理统一业务的流程
  • 线程池实现高性能并发 : Executor Service
  • 管道实现高性能队列 : Redis Pipelining

作为一个工程师,要知道自己能力的边界在哪里,利用有限的资源让方案落地。

这里优化的经历,是想让大家对电商相关的业务有所了解,另外对处理问题的解决思路有所借鉴。

转载于:https://juejin.im/post/5cb5a447e51d456e2b15f5f2

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33829657/article/details/91475540

智能推荐

Fastlane 实现xcode 打ipa包并上传到蒲公英_fastlane 上传蒲公英 get token is failed-程序员宅基地

文章浏览阅读3.7k次。总述:需要的安装的插件:(通过终端安装) :fastlane,Xcode 命令行工具,pgyer;步骤:1:安装fastlane1)首先要安装正确的 Ruby 版本,在终端窗口中用下列命令来确认:ruby-v终端反应:macdeMacBook-Air:Desktop mac$ ruby -vruby 2.3.3p222 (2016-11-21 revision 56..._fastlane 上传蒲公英 get token is failed

机器学习算法汇总_哪些不是机器学习方法的算法-程序员宅基地

文章浏览阅读2.1k次,点赞2次,收藏9次。ML算法模型简单总结一下在学习的过程中对Machine Learning算法模型理解:决策树 ( decision tree)详解集成算法(Bagging,随机森林)集成算法(AdaBoost基本原理)Boosting算法(GBDT,XGBoost,LightGBM)SVM(Support Vector Machin) 支持向量机 详解KNN(k-nearest neighbors..._哪些不是机器学习方法的算法

发展与教育心理学类毕业论文文献有哪些?-程序员宅基地

文章浏览阅读529次。本文是为大家整理的发展与教育心理学主题相关的10篇毕业论文文献,包括5篇期刊论文和5篇专利论文,为发展与教育心理学选题相关人员撰写毕业论文提供参考。1.[期刊论文]浅析高校心理学教育教学的多元化发展期刊:《文化创新比较研究》 | 2021 年第 004 期摘要:心理学课程是各高校中必不可少的一门课程,立足于学生的心理特征,进行正面教育,帮助学生健全人格.心理学教育重在促使学生健康心理的养成,缓解..._发展心理学文献

2022年 maven配置阿里云仓库配置_httpmaven aliyun-程序员宅基地

文章浏览阅读2.6w次,点赞29次,收藏133次。maven配置https阿里云仓库配置_httpmaven aliyun

SPWM与SVPWM的比较_svpwm与spwm的区别-程序员宅基地

文章浏览阅读8.2k次,点赞3次,收藏25次。1 最大线电压峰值: (直流测电压为Vdc)SPWM调制时最大的三相线电压为Vm=1.732Vdc/2SVPWM调制时最大的三相线电压为Vm=Vdc故SVPWM调制时的电压利用率比SPWM大15.5%2 SVPWM调制比M与长度系数M*的关系分_svpwm与spwm的区别

Qt自定义一个下拉框(使用基础组件组合)_qt下滑组件-程序员宅基地

文章浏览阅读9.2k次,点赞5次,收藏60次。Qt提供了一个QComboBox下拉框组件,但是对于一些自定义样式的需求实现起来并不方便,很多东西还得去倒腾源码,还不如直接用基础的组件自己来实现一个下拉框。不过,自己组合的组件要做的细节太多了,所以我只在一些定制化程度高的需求才使用这种方式。_qt下滑组件

随便推点

jSignature 移动端在线签名_jsignature api-程序员宅基地

文章浏览阅读1.8k次。一、基本介绍jSignature是一个jQuery插件,它简化了创建签名捕获场的浏览器窗口,允许用户使用鼠标,笔,或手指画一个签名。jSignature捕捉签名矢量轮廓的笔触。虽然jSignature可以导出大位图(PNG)也一样,提取签名的高度可扩展的行程运动坐标(又名向量图)允许签名呈现更大的灵活性。支持主要的台式机,平板电脑和手机浏览器的支持。HTML5 Canvas元素默认情况..._jsignature api

Pycharm报错:please select a valid interpreter_pycharm apply please-程序员宅基地

文章浏览阅读3.6k次。更改Pycharm的设置 打开settings(CTRL + ALT + S)查找框输入 interpreter 双击 project Interpreter在 Project Interpreter选择编译器,点击apply,重新启动pycharm即可_pycharm apply please

Python机器学习之决策树(使用西瓜数据集构建决策树,并将其可视化,graphviz程序下载)_用信息增益方法画出西瓜数据集的决策树-程序员宅基地

文章浏览阅读7.6k次,点赞16次,收藏85次。最近在搞一些关于机器学习的小东西,其中有一部分就是关于决策树的。过程中遇到了一些小问题,现记录并与大家分享。一、问题描述:使用西瓜数据集构建决策树,并将构建的决策树进行可视化操作。二、问题简析:首先我们简单的介绍一下什么是决策树。决策树是广泛用于分类和回归任务的模型。本质上,它从一层层的if/else问题中进行学习,并得出结论。然后不妨看看下面这个小思考题吧:(故事我瞎编的,看问题就好了嘛)小鹿机缘巧合之下喜欢上了一个只有一面之缘的贝贝(一见钟情嘛)。对吧,爱情的力量是伟大的,小鹿就不顾一切的裸辞叻,_用信息增益方法画出西瓜数据集的决策树

802.11w协议介绍_802.11 协议主要通过对数据报文进行加密的方式解决用户的数据安全问题,加密方-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏16次。802.11w协议介绍转载自http://www.h3c.com/cn/d_201708/1018833_30005_0.htm#收藏 打印 推荐1产生背景相对于有线网络,WLAN存在着与生俱来的数据安全问题。在一个区域内的所有的WLAN设备共享传输媒介,任何一台设备可以接收到其它所有设备的数据,这个特性直接威胁到WLAN接入数据的安全。因此,WLAN协议中定义了安全性的标准802.11i,涉及用户接入控制及身份验证、用户数据加密、密钥管理等多个方面。但是,..._802.11 协议主要通过对数据报文进行加密的方式解决用户的数据安全问题,加密方

【Spring】Spring Framework Reference Documentation中文版23-程序员宅基地

文章浏览阅读1.6k次。26. WebSocket SupportWebSocker支持 This part of the reference documentation covers Spring Framework’s support for WebSocket-style messaging in web applications including use of STOMP as an applica_spring framework reference documentation

颠覆互联网中介模式,他们想通过超级虚拟主机创建开源的商业系统-程序员宅基地

文章浏览阅读649次。本堂茜 渡鸦区块链专栏记者 ‍ 按部就班的普通人可能无法想象丁磊的成长历程。丁磊的父亲观念超前,认为传统教育“浪费时间”,于是从丁磊8岁开始,就引导着他进行高效、自主、超前的学习。8岁时,丁磊已经能够熟练掌握英语,12岁便拿到了上海外国语大学的英语大专文凭;13、4岁他已经能够通过复旦大学计算机专业的本科自学课程;同年,他获得了山东大学计算机信息管理本科毕业证书,毕

推荐文章

热门文章

相关标签