Shopee物流业务核心数据库架构演变——权衡取舍的艺术

本文首发于微信公众号“Shopee技术团队

摘要

Shopee 供应链主要覆盖卖家发货后,仓库拣选商品、交至第三方物流(3rd Party Logistics,下称 3PL)、送达买家过程中的各种场景。Logistics Channel Service 项目(下称 LCS)是物流履约链路上连接内外的一环,收拢了向 3PL 下单、获取物流轨迹更新等对外交互的业务。

从 2019 年 9 月至今,随着上游系统拆分迁移,越来越多 3PL 进入 LCS 负责范围;并且由于电商业务在 2020 年的飞速发展,系统每月的订单量也在陡增,对数据库的要求和压力随之而来,在短短一年内,数据库架构跟随业务增长进行了多次调整。

本文简要回顾了 LCS 诞生至今的数据库架构变化,并介绍项目组在 2020 年底落地的分库实践,梳理落地过程中踩过的坑和总结的经验、教训和思考。

新方案实践的过程中,有遇到常规库表拆分中共有的问题,也有针对项目场景的“特色”问题,解决它们没有十全十美的方案,而更多是权衡取舍的过程,需要结合业务特性来分析和选择最有利的方式处理。

1. 背景

1.1 项目起源

LCS 是一个基于 Python Django 框架的项目,业务核心是物流订单的履约过程,包括连接上游和第三方物流服务的创建订单、轨迹与运费更新。在部署上,LCS 依据业务所在的市场不同,应用层分市场部署,并使用各自市场对应的数据库。在项目起步初期,这些不同市场的数据库共用同一套物理集群,共享内存和磁盘空间,在资源上看,是足以应付初期流量的。

随着业务的铺开,共用集群的问题慢慢体现了出来。地区与地区之间存在业务差异,订单数量、订单轨迹比例不同,依赖物理集群自身的资源调度不能满足我们的需要,很多时候:

  • 订单量大的地区的数据库读写影响了订单量少的地区的 I/O 资源;

  • 轨迹推送 QPS 远比下单高,大量的轨迹信息读写影响了核心的下单流程。

在尽量不影响业务的情况下,我们先选择了将热点地区的数据库拆分到单独的物理集群上,独占资源,保证自身服务稳定的同时,也减少了对其他地区服务的影响。在这个过程中,由于不同市场使用的是不同的逻辑库,所以切换没有任何的业务改动,在 DBA 的协助下,可以非常迅速地完成这个操作。

面对轨迹推送更高 QPS 的问题,我们使用了临时表和消息队列,让解析轨迹并绑定到对应订单上的过程延迟发生,显著降低了第三方请求我们时感知到的响应耗时。问题在于临时表是设计在业务 MySQL 库中的,尽管异步处理了轨迹更新,但是因为没有做限流,MySQL 受到的峰值压力并没有减少。

因此,在前面的物理集群拆分后,我们又启用了 TiDB 存放临时轨迹数据,一是分离临时数据与业务数据;二是由于临时表按日分表,若使用 MySQL,单机扩容不易,需要定期清理历史数据,产生大量 DELETE 操作影响性能,而产品线内使用的 TiDB 集群能提供超大的容量和易扩展性,后续清理数据改由 DBA 一定时间后通过 DROP TABLE 处理。研发团队认为 TiDB 更适合在这种场景下代替 MySQL。

1.2 面临挑战

尽管已经做了两次拆分和调整,但是随着订单量的持续上涨,又由于物流订单中的信息繁杂,尤其上游早期未加以限制的各种收发货地址、名称、联系方式,以及跨地域运输业务所需要的详细的商品细节,再加上物流轨迹的描述信息,让每个订单的文本类型数据非常多,数据库表的体积容易暴涨。

根据 2020 年下半年的数据统计,业务量较大的地区 MySQL 集群的磁盘空间用量在项目上线极短时间内已突破 30%,剩余空间只能支撑半年左右。并且随着上游流量灰度至本服务的比例上涨,每个月的增量都比以往更大。在灰度结束后,又迎来了下半年几个重要的促销活动时间节点——9.9、11.11、12.12,数据体积进一步增长,仅通过日常的数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值