京东618:一个中心五个原则,谈谈物流系统的大促优化实践

《京东618:一个中心五个原则,谈谈物流系统的大促优化实践》要点:
本文介绍了京东618:一个中心五个原则,谈谈物流系统的大促优化实践,希望对您有用。如果有疑问,可以联系我们。

京东

作者:者文明

编辑:木环、郭蕾

在京东的订单流链路中,可以简单的划分为订单前和订单后两部分,我们在京东主站上搜索商品、浏览商品详情、把商品加入购物车、提交并支付订单等环节属于订单前,订单提交之后,订单信息流就进入订单后的物流系统部分.每逢 618 大促期间,大家可能会更多的聚焦到网站 PV、秒杀系统、交易数据、广告收入等等.其实对于京东来说,其很核心的优势来源于精准的时效承诺、极速的送货体验和极致的售后服务,在大促期间,其物流系统的表现对客户体验至关重要.

京东物流系统简介

京东物流系统属于订单生产系统,主要包括订单履约、仓储、配送、客户服务和逆向处置中心等等.图 1 示意了一个简单的正向订单生产流程,逆向生产流程主要由逆向处置中心发起,主要包括售后服务单(退换货等)和安装维修单.

流程

图 1 订单生产流程

京东物流系统有如下 3 大特性:

  • 90% 以上为 OLTP 系统,承载着订单生产相关的所有核心交易流程
  • 领域模型和业务逻辑复杂
  • 强依赖关系型数据库

以上特性也决定了物流系统的大促备战和电商网站、订单交易、秒杀、搜索推荐、广告等系统会大有不同,在很大程度上系统 70% 以上的性能(容量)取决于 DB 的性能(容量).因此,DB 是我们每次大促备战的重点.围绕 DB 侧的备战工作,主要聚焦在慢 SQL、垂直和水平拆分、读写分离、生产库和报表库分离、连接池优化、参数调优等方面.

打不死的小强—慢 SQL

记得刚加入京东第一次负责 618 的时候,在 618 当天就遇到了两次业务反馈系统卡顿的现象,紧急排查发现 DB 中大量连接堆积,再通过查看当前线程发现是一个慢 SQL(耗时 10 多秒)导致了连接堆积,后来把慢 SQL 紧急优化上线后系统恢复正常.从那天以后,我深深感受到了慢 SQL 对我们系统的影响,同时也明白了一点,一个慢 SQL 对我们的系统总是致命的,我们不能放过任何一个慢 SQL.为了说明一个慢 SQL 对系统的影响,截取了两张数据库 CPU 使用率在一个慢 SQL 优化前后的对比图(如图 2),从图中也可以看出,前后对比是非常明显的.

SQL 优化

图 2 一个慢 SQL 优化前后 CPU 负载对比

在数据库优化方面,慢 SQL 优化是最重要且效果最好的一项工作,如果要用一个比喻去形容慢 SQL,打不死的小强是再贴切不过的了,慢 SQL 在我们的系统中是灭了一茬又一茬,似乎永远消灭不完.通常情况下,慢 SQL 的出现可能是因为过滤条件中没有索引、SQL 语句写的过于复杂、表中数据量过大,做了全表扫描等等,因此我们在进行慢 SQL 优化时,优先会通过添加索引解决,索引解决不了的才会去优化语法,拆解 SQL 语句,将大事务化小,通过适当冗余来减少关联,优化数据模型,通过历史数据结转减少数据量等等.总之优化慢 SQL 的方法很多,各系统要根据各自的特性和场景选择最优且成本最低的方案.

近几年来,京东的业务一直处于持续膨胀之中,系统中总会不断涌入很多新的业务需求,这样也就不可避免的引入了新的慢 SQL,所以每次大促,慢 SQL 优化是一大备战重点.

数据库垂直和水平拆分

跟传统的企业应用系统一样,京东的仓储系统也经历过 C/S 和 B/S 时代,V3.0 之前用的是 SQLServer 和.Net 平台,而且整个仓储管理是一个系统,包括基础资料、库存、入库、出库、在库等,随着京东业务规模的迅速增长,每次大促的单量峰值也由早期的万级增长到了现在的亿级,这中间仓储系统进行了垂直拆分,将基础资料、库存、入库、出库、在库等拆分为独立系统独立部署(如图 3) .垂直拆分之后仓储系统一分为多,系统的容量也就成倍上升.

数据库

图 3 仓储系统数据库垂直拆分

除了仓储系统,其他很多系统(包括配送系统)都经历了垂直拆分的过程,垂直拆分不但可以很好的解耦系统,还能成倍提升系统容量.

京东的配送系统流量比仓储系统还要大,垂直拆分之后的系统容量不足以支撑大促期间的单量冲击,于是在垂直拆分的基础上又做了水平拆分,水平拆分除了常用的分库分表之外,还有部分复杂业务表的模型水平拆分,比如运单表,拆分成基础数据、扩展数据和状态管理三个表,有的表也会按读写比例进行拆分,比如将读多写少的列放一张表,读少写多的列放另一张表.图 4 是配送系统进行水平拆分的一个示意图.水平拆分之后,目前系统可以轻松应对大促期间的亿级单量,流量还远远未到系统的容量上限.

数据库

图 4 配送系统数据库水平拆分

分离技术

分离技术也是我们每次大促备战中的常用方法,主要包括读 / 写分离,生产 / 监控分离和在线 / 离线分离.

我们大部分系统读写比例大约 10:1,对于关系型数据库来说,主要消耗来源于查询,尤其是复杂查询,所以为了提升数据库端的总体容量,必须尽可能的将查询 SQL 分离到从库上,主库只提供写服务和一些必要的读服务,图 5 中 B 为备份库,R 为从库,所有从库均可提供读服务,一个主库下可能会挂多个从库,多个从库根据业务场景需求可以做成负载均衡,也可以按业务优先级进行隔离并支持灵活切换.这样主库就只负责生产,避免了那些比较消耗性能的复杂查询影响到生产,同时系统的总体容量也会得到大大提升.

生产 / 监控分离指的是生产报表和监控报表必须分离开来,所谓生产报表就是业务生产过程中强依赖的报表,比如仓储系统中的积压类报表(拣货、复核、打包等各环节积压数量),配送系统中的分拣差异报表、配送差异报表等等.

这两类报表业务优先级不一样,生产报表是要优先保障的,所以在系统中需要将这两类报表进行隔离,避免监控类报表影响到生产类报表.监控报表是一个独立系统,数据来源有两种路径,一种是从生产库通过 binlog 复制过来(我们用的是自研的 Decomb 总线),另一种是从生产库通过消息方式先进入 kafka,再从 kafka 消费到监控系统.因为监控报表业务场景的多样性和复杂性,监控系统的数据库会采用多种技术,比如 MySQL、ElasticSearch、HBase、Cassandra 等等.

在线 / 离线分离指的是在线报表和离线报表分离,在线报表是实时或准实时报表,查看的是 24 小时之内的业务数据,离线报表多为分析类报表,查看的是 24 小时之前的业务数据.因为二者的业务优先级和技术方案都不尽相同,所以必须要进行分离,避免相互影响.

分离技术

图 5 分离技术

DB+ 技术

经历过多次大促备战之后,给我们最大的感触就是业务规模的增长速度总是快于我们系统的迭代速度,业务规模总是在驱动着系统的迭代升级.面对亿级单量,单纯的引入前面提到的技术已经无法让系统容量发生质的变化,系统容量容易受制于数据库,所以,除了通过分库分表来实现数据库写的分布式,还需要引入一些 NoSQL 技术,所谓的 DB+,也就是 DB+NoSQL+ 分布式,主要包括如下几个方面的改进:

  1. 引入 KV 引擎,将一些数据从关系型数据库(MySQL)迁移到 KV 引擎中来存储和处理,这样不仅可以大大降低关系型数据库(MySQL)的负担,还能提升数据的读写性能.京东的物流系统中,引入的 KV 引擎主要包括 Redis、HBase、ElasticSearch 和 Cassandra,Redis 用于缓存相对静态的热点数据,HBase 是存储,主要存储海量的业务数据和历史数据,ElasticSearch 主要存储查询条件相对复杂的数据,Cassandra 主要存储一些日志、流水类数据.
  2. 引入数据库分库分表中间件,实现数据库写的分布式,做到数据库读写的水平可扩展,真正实现从 Scale up 到 Scale out 的转变.
  3. 追求 BASE 模型,容忍分区失败,弱化事务,大事务化小事务,甚至是无事务,舍强一致性取最终一致性.

图 6 能简单说明 DB+ 的基本思路,系统的存储分两部分,一部分是传统的关系型数据库(MySQL),用来存储结构化,强事务数据,数据库做了 Sharding,读写均为分布式,支持弹性扩展.另一个是 KV 引擎,KV 引擎主要包括 Redis、HBase、ElasticSearch 和 Cassandra,Redis 主要用来做热点缓存,HBase 用来存储数据量级大而且 rowkey 又比较固定的数据,ElasticSearch 用来存储查询条件比较复杂的报表、查询类数据,Cassandra 主要用来存储日志、流水类数据,这类数据量级大,读写性能要求也比较高,但是大多都是按 key 查询.

DB技术

图 6 DB+ 技术

思考总结

在经历过多次大促备战之后,最大的感触是每次大促的业务规模总是在驱动着系统的技术不断的升级.不同的业务量级所需要使用的技术也大不一样,前面介绍的都是每次大促备战的一些技术实践.简而言之,对于 OLTP 类系统来说,面对大促的优化可以总结为 一个中心和五个基本原则.

一个中心就是要以数据库为中心,优化数据库性能为先,从数据库端出发来提升系统容量.五个基本原则就是大系统小做原则、大事务化小原则、分离原则、分布式原则和数据库弱依赖原则.下面分别介绍下:

  • 大系统小做讲的就是合理的垂直拆分,将一个业务系统按照合理的领域模型拆分成多个可以独立部署的子系统,一方面解耦,一方面提升系统的容量和可扩展能力.
  • 大事务化小指的是在业务允许的前提下尽可能将大事务拆成小事务,大事务会严重影响数据库的性能而且容易造成死锁;
  • 分离原则就是要根据业务的不通场景和要求和数据的冷热程度等进行数据的分离,避免不同优先级的业务相互影响;
  • 分布式原则主要说的是要将数据库的写进行分布式,并且真正做到写库可动态扩展;
  • 数据库弱依赖原则简单说就是要尽可能减少对关系型数据库的依赖,能用 NoSQL 解决的就不用关系型数据库,能异步写库的就不同步写,能最终一致性的就不追求强一致性等等.

现阶段正处于电商高速发展的黄金时期,业务规模还将持续保持快速增长,京东的物流系统也还将持续迭代和演进.

作者介绍

者文明,京东商城运营研发部首席架构师,中科院硕士,清华大学学士,15 年电子商务 / 企业应用领域研发、架构经验,涉及电子商务、互联网、大数据、人工智能等领域,专注电商物流系统架构、实时大数据、智慧物流等解决方案.2012 年初加入京东,主要负责京东物流系统架构.

原文来自微信公众号:聊聊架构

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


起步 处理器架构,参考 x86是指intel的开发的一种32位指令集 intel和amd早期的cpu都支持这种指令集 AMD比Intel率先制造出了商用的兼容x86的CPU,AMD称之为AMD64 Intel选择了设计一种不兼容x86的全新64为指令集,称之为IA-64,后来支持AMD64的指令集,
pscp pscp -P 22 C:\work\test.txt root@192.168.1.5:/home/data pscp -P 22 root@192.168.1.5:/home/data/test.txt C://work// 检索 find / -name default.config
文件处理 ls -a # 显示所有文件 ls -l # 显示详细信息 ls -d # 显示路径 mkdir /目录名称 # 创建目录 cd /目录名称 # 切换目录 pwd # 显示当前路径 rmdir /目录名称 # 删除目录 cp -rp [目录名称] [目标目录] # 复制目录到目标目录 cp
准备一台电脑(我就用联想拯救者r7000演示) 参考博客制作启动盘 插上U盘,启动电脑,一直按F2 进入如下页面后,将U盘设置为第一启动项,点击exit,保存并退出 之后进入如下页面,选择第三项 进入如下页面,选择第四项 进入如下页面,选择第一项,选中后,先不要点Enter 按e键,将inst.st
认识 Linux系统是参考了UNIX系统作为模板开发的,但没有使用UNIX的代码;是UNIX的一种,但不是衍生版 在Linux内核的基础上开发是发行版 分区 逻辑分区永远从5开始 步骤 挂载:可理解为分配盘符,挂载点即是盘符名;不同之处:Linux中是以空目录名称作为盘符 Hda 第一块硬盘 Hda
文件处理命令 以 . 开头的文件是隐藏文件 以 - 开头表示这是一个文件 以 d 开头表示是一个目录 以 l 开头表示是一个软链接 第一个root是所有者,第二个root是所属组 ls -h 以文件默认大小后缀 显示 ls -i 查看i节点(唯一标识) 所有者:只能有一个,可变更 所属组:只能有一个
参考 01 02 03 前提环境 本地安装VirtualBox,并安装CentOS8,配置网络后,window系统上putty能连接到CentOS8服务器 配置步骤 右键服务器复制 启动复制后的服务器,查看ip和hostname发现和原来的服务器一样,需要修改 hostname # 查看主机名 vi
文件搜索命令 星号匹配任意字符,问号匹配任意单个字符 -iname 根据文件名查找且不区分大小写 -ok 命名会有一个询问的步骤 如果没有找到指定文件,可输入命令:updatedb 更新文件资料库;除tmp目录不在文件资料库收录范围之内 locate -i 文件名 # 检索时不区分大小写 which
安装环境 安装最新版的Virtual Box,点击安装 下载centos8镜像 创建虚拟机,可参考 选择下载到本地的镜像 设置启动顺序 点击启动 启动过程中报错:“FATAL:No bootable medium found!” 1.没有选择iso镜像 2.光驱没有排在第一位置 3.镜像只能选择x8
Linux严格区分大小写 所有内容文件形式保存,包括硬件 Linux不靠扩展名区分文件类型 挂载:将设备文件名和挂载点(盘符)连接的过程 Linux各个目录的作用 bin表示二进制 服务器注意事项 远程服务器不允许关机,只能重启 重启时应该关闭服务 不要在服务器访问高峰运行高负载命令 远程配置防火墙
IDE连接Linux,上传下载文件 参考1 参考2 连接Linux 上传下载文件 本地项目打包后上传 查看是否上传成功,右键下载 补充 后端项目开发完成后,需clean掉临时文件target文件夹,且只推送修改过的文件 前端项目开发的过程中,需要在每个子组件中使用scoped,确保每个子组件中的编码
起步 LTS与普通版本的区别 LTS版本的发布周期更长,更加稳定 安装jdk sudo mkdir /usr/lib/jvm # 在Ubuntu中创建目录 pscp D:\安装包\linux源码包\jdk-8u291-linux-x64.tar.gz chnq@192.168.0.102:/tmp
前言 最近在b站上看了兄弟连老师的Linux教程,非常适合入门:https://www.bilibili.com/video/BV1mW411i7Qf 看完后就自己来试着玩下,正好手上有台空闲的电脑就尝试不使用虚拟机的方式安装Linux系统 安装步骤 制作启动盘 下载ISO镜像,我这里下载的是Cen
新建虚拟电脑 设置内存和处理器 设置硬盘大小 完成 设置 查看光驱 设置启动顺序 点击启动 选择第1项 进入图形安装界面 选择安装位置,开始安装 设置root密码 重启 登录 查看本地文件夹 配置网络,点击设置 查看宿主机ip C:\Users\ychen λ ipconfig 无线局域网适配器 W
源码包安装需手动下载后安装 二进制包则在package目录下 rpm命令管理rpm包 若某个rpm包依赖于某个模块,需要到网站www.rpmfind.net查询该模块依赖的包,安装这个包后自动安装模块,之后就能安装rpm包了 安装升级时使用包全名 查询卸载时使用包名 虚拟机中的Linux系统安装rp
首先进入命令模式,再输入以下命令 命令模式用于输入命令 插入模式可对文件编写操作 编辑模式下的命令是在冒号后输入 :12, 15d # 删除指定范围的行,这里是删除12到15行 :n1,n2s/old/new/g ## 表示从n1行到n2行,old表示旧的字符串 vim使用小技巧:自定义快捷键,如快
使用源码包安装,需要自己指定安装位置,通常是 /usr/local/软件名/ linux中要想启动执行文件,应使用绝对路径 /绝对路径/rpm包名 start ## 执行方式一 service rpm包名 start ## 执行方式二 使用源码包安装后,由于自定义安装路径,就不能使用service命
网络命令 在收邮件的用户中,输入 mail 可查看邮件信息,输入序列号查看详细信息 在mail命令下,输入h 查看所有邮件的列表 输入:d 序列号 # 删除邮件 last # 统计所有用户登录或重启时间,用于日志查询 lastlog # 显示包括未登录用户的登录时间 lastlog -u 用户id
若要使用yum管理,必须能连接网络,首先配置网络IP 进入yum源文件中启动容器 使用yum源头安装rpm包不需要进入package路径,同时也不需要使用包全名,会有yum自动管理 安装软件组
简介 client即是本机安装的docker,相当于git Docker_host相当于centos系统 registry则是docker仓库,相当于GitHub 镜像用于创建docker容器,一个镜像可以创建多个docker容器 容器是由镜像创建的运行实例,(镜像相当于类,容器相当于类创建的对象)