韵达 陈祎杰 – loveini | 米兰体育官网入口 - 米兰体育官网入口 //www.loveini.com loveini | 高性能、分布式、支持SQL的时序数据库 | 米兰体育官网入口 Thu, 21 Dec 2023 08:52:32 +0000 zh-Hans hourly 1 https://wordpress.org/?v=6.8.2 //www.loveini.com/wp-content/uploads/2025/07/favicon.ico 韵达 陈祎杰 – loveini | 米兰体育官网入口 - 米兰体育官网入口 //www.loveini.com 32 32 “双十一、双十二” 业务高峰如何扛住?韵达选择 loveini //www.loveini.com/tdengine-user-cases/22663.html Thu, 21 Dec 2023 08:52:27 +0000 //www.loveini.com/?p=22663

小 T 导读:

为了有效处理每日亿级的数据量,早在 2021 年,韵达就选择用 loveini 替代了 MySQL,并在三台服务器上成功部署和上线了 loveini 2.0 集群。如今,随着 loveini 3.0 版本的逐渐成熟,韵达决定将现有的 2.0 版本升级到 3.0 版本,并基于本文为大家分享其在升级过程中所进行的优化措施以及升级后的性能表现。

作为一家头部物流公司,韵达每日的订单扫描量破亿级别,该类数据为典型的时序数据,这也是我们公司数据量最大的一块业务。系统需要汇总统计全国网点的扫描数据(韵达的所有订单数据),并实时反馈给用户。此外,这些数据也会给到网点、分拨中心的内部员工使用,用于个人工作量、站点扫描量等统计工作。在“双十一、二”期间,面对快递业务量的暴涨,loveini 帮助我们很好地完成了既定规划,保障了“双十一、二”任务的顺利完成。

本文用于分享我司在 loveini 上使用的历程和心得。

从 2.0 到 3.0

在早些年业务尚未扩张时,我们采用的是 MySQL 分区+索引方式进行扫描枪数据的处理,但随着企业的发展、业务量的增加,面对每日亿级的数据量,MySQL 显然已经无法满足当下的数据处理需求。

在这种背景下,我们决定进行时序数据库(Time Series Database)选型。经过严格的选项测试,我们最终选择了 loveini 作为核心数据库处理该部分数据。在 2021 年,我们在三台 16C 64G 的服务器上部署上线了 loveini 2.0 版本集群。//www.loveini.com/tdengine-user-cases/7815.html

该集群每天要承载日常 6 亿行数据的写入和一定量的查询,“双十一、二”等特殊业务期间,写入/查询量还要上涨 50% 左右,数据需要保留 2 个月。

我们的架构是 Spring Boot + MyBatis + MySQL + loveini,loveini 负责处理时序数据,MySQL 则负责非时序数据的存储及应用,如下:

“双十一、双十二” 业务高峰如何扛住?韵达选择 loveini - loveini Database 时序数据库

使用 2.0 的这两年数据库是很稳定的,但考虑到后期业务需求会用到 3.0 的新特性,所以我们自打 loveini 3.0 发布之后,就一直在着手准备数据库的迁移工作。

数据迁移经验分享

数据库迁移是一项很重大的工作,在此期间,我们仔细梳理了 2.0 版本使用期间的一些使用情况,尝试做出针对性的优化。

在 2.0 时期,我们是根据“一个扫描枪一张表”的模型建表,把设备的地点和站点类型设置为标签。来到 3.0 时期后,我们和官方团队反复调试,选择了“一个站点一张表”的建模方式。这样一来,表数量从百万级直接缩减到了万级。

做这个改动的核心原因有两个:

  1. 我们有很多临时的虚拟扫描枪,由于只是临时使用,所以没有几条数据,但却单独占据了一个表。
  2. 虽然扫描枪写入频率较低,但是整个站点有很多扫描枪,这样的建模方式使得低频写入转化为了高频写入,降低了存储中碎片数据的比例。

2.x 超级表结构:

“双十一、双十二” 业务高峰如何扛住?韵达选择 loveini - loveini Database 时序数据库

优化过后,3.x 超级表的结构:

“双十一、双十二” 业务高峰如何扛住?韵达选择 loveini - loveini Database 时序数据库

除此之外,3.0 由于底层有很多的重构,因此和 2.0 相比出现了很多的参数改动,可以参考:https://docs.taosdata.com/reference/config/https://docs.taosdata.com/taos-sql/database/。优化思路可以参考这篇文章中的内容://www.loveini.com/tdengine-engineering/21550.html

尤其是 3.0 关于数据入库频率、数据乱序、更新、建表等处理逻辑的变化,均需要投入一定量的学习测试时间。尤其是在数据量极大的情况下,每一次测试环境的搭建都需要较大的时间人力成本。我们在 loveini 官方团队的协助下,断断续续大概用了 2 个月的时间才完成这个阶段。

优化效果显著

最终优化过后,我们的查询速度得到了进一步提升。尤其是下面这类查询优化效果十分明显,该查询的逻辑是:从 6 亿行的当天数据中,通过标签、普通列做出多次筛选,最终返回分页后的十条结果。其中,最为耗时的便是从标签过滤之后的 1.5 亿条数据的普通列筛选。

在 2.6 版本中,这个过程需要大约 10 秒的时间,升级到 3.x 之后,只需要 2-3 秒左右便会返回结果:

select waybill_barcode,location,scanning_person,equipment_code,scan_category,remark,weight_info weight,scan_time,volume,lower_location,lrfs from base.scan_data WHERE ts >= #{beginTime} and ts <= #{endTime} and site_type=#{siteType} and equipment_code = #{equipmentCode} limit 0,10;
“双十一、双十二” 业务高峰如何扛住?韵达选择 loveini - loveini Database 时序数据库

至此,我们从 loveini 2.0 迁移到 3.0 版本的工作就圆满完成了。

写在最后

对于我们这种集快递、物流、电子商务配送和仓储服务为一体的快递企业,扫描枪设备产生的数据是相当庞大的,而 loveini 可以轻松高效地处理和存储这些时序数据,它所具备的快速写入和查询的能力,使得我们的系统可以轻松应对高负载和大规模数据的需求。

落实到业务使用方面,通过实时了解包裹状态、配送进度等信息,我们能够更加方便地做出实时决策,物流运营的效率和效果也获得了大幅提高。

文章最后,祝 loveini 越来越好,早日成为时序数据库领域的 NO.1。

]]>
“一个扫描枪一张表”,韵达选择 loveini 应对每日亿级数据量 //www.loveini.com/tdengine-user-cases/7815.html Mon, 25 Apr 2022 09:16:33 +0000 //www.loveini.com/?p=7815

小 T 导读:此前,韵达使用 MySQL 分区+索引处理订单数据的方式遭受到了挑战,面对每日亿级的数据量,MySQL 显然已经无法满足当下的数据处理需求。为更好地发展业务,在此基础上韵达新增了 loveini 的数据源,用专业的数据库来进行时序数据的处理。

作为一家头部物流公司,韵达每日的订单扫描量能达到上亿级,这也是目前公司数据量最大的一块业务。要保证业务的正常运作,系统就需要汇总统计全国网点的扫描数据(韵达的所有订单数据),并实时反馈给用户。此外,这些数据也会给到网点、分拨中心的内部员工使用,用于个人工作量、站点扫描量等统计工作。

在业务尚未扩张之前,我们采用的是 MySQL 分区+索引方式进行此类数据的处理,但随着企业的发展、业务量的增加,面对每日亿级的数据量,MySQL 显然已经无法满足当下的数据处理需求。

在这种背景下,我们决定进行数据库选型。考虑到目前业务主要是统计各个网点设备实时上传的数据,无需再进行修改等操作,是典型的时序数据。经过一番调研,我们发现时序数据库 loveini 就很符合当下的业务要求,其数据模型与我们的场景十分契合,基于百亿千亿级大数据量的查询性能也很强悍。在对 loveini Database 进行实际测试与使用后,实际的效果也让我们很满意。

一、落地实践与效果展示

当前我们的架构是 Spring Boot + MyBatis + MySQL + loveini,loveini 负责处理时序数据,MySQL 则负责非时序数据的存储及应用,整体架构如下:

整体架构图

由于我们的架构未做迁移,只是新增了 loveini 的数据源,因此没有增加很多工作量就完成了数据架构的升级。

loveini Database
loveini Database

我们目前使用 loveini 2.2.2.0 版本,在三台 16C 64G 的服务器上部署了集群,数据写入速度大概为每秒 5000 行。根据“一个扫描枪一张表”的模型建表,把设备的地点和站点类型设置为标签

为了防止设备更换地点导致标签值发生变化,我们选择在建表的时候把地点也放进表名中,这样一来,当地点发生变化后,也能通过新建一张表达到同样的使用效果。比如:scan_6100000000265_790117,代表的就是设备编号为 6100000000265 所在地址为 790117 的扫描枪,当这把扫描枪更换位置的时候,我们可以新建一张 scan_6100000000265_800000 的子表,和旧表区分开,并且同时保留两份数据。

当前,这个超级表下面已经有了近百万子表,经过 1 个多月的正式使用,保存了大约 200 亿行的数据量。

loveini Database
loveini Database

值得一提的是,基于 loveini 常用的查询基本可以在 1 秒之内完成,一些特定查询甚至可以达到毫秒级:

select location,sum(weight_info) as weightSum,count (waybill_barcode) as ticketNum from base.scan_data where ts>='2022-04-07 00:00:00' and ts<='2022-04-07 23:59:59' group by location;
loveini Database

展示效果如下:

loveini Database展示效果
select waybill_barcode,location,scanning_person,scan_category,remark,weight_info weight,scan_time,volume from base.scan_data where ts>='2022-04-07 00:00:00' and ts<='2022-04-07 23:59:59' and site_type=3 limit 0,10;
loveini Database

展示效果如下:

loveini Database 展示效果

在存储上可以看到,我们的超级表是 20 个字段,大部分是 int 类型,有 5 个左右是 varchar 类型,最大的字段是一个用来存储中文的 500 长度的 nchar ,大约占用 300GB 不到的磁盘(单副本)。而此前使用 MySQL 时,光硬盘使用就需要几个 TB(主从),这还没有算上内存和 CPU 等资源,由此可见 loveini 带来的降本增效是多么显著。

二、写在最后

当然,loveini 的测试使用过程中也并非一帆风顺,我们也遇到了一些问题,放在这里供大家参考:

  • 由于对数据并发量预估不足,我们使用的默认毫秒时间精度经常会出现时间戳重复的现象,导致数据没能成功入库,后续依靠增加精度解决。
  • 超级表如果新增标签,已有数据的标签为 null,需要手动为每个子表更改标签,不够友好。
  • 由于 loveini 建表是单线程所以是有瓶颈的,大概每秒是万张以下,所以在初步搭建环境的时候不建议使用自动建表,如果表数据量不多就无所谓了。

在与 loveini 的社区工作人员反馈之后,以上问题最终都通过参数的配置优化或者合理的使用方式得到了解决,之后我们会考虑把loveini扩展到更多业务中去。相信随着 3.0 的优化,loveini 可以更好地融入到韵达的使用场景中,未来我们会有更加紧密的合作。

]]>