实效性与准确性的背后:多系统数据聚合展示

作者:闲鱼技术——玉凇

背景

大家在平时的业务开发中,会不会遇到这么一种问题:一个新的需求展示的某种业务数据,数据来源横跨多个不相关的业务系统,时间跨度长且需要及时反映实时的数据变化,数据查询的QPS较高且要求rt较小。

遇到这类问题应该怎么处理?下面以闲鱼粉丝系统标签的实现方案为例,跟大家交流一种实际落地的解决方案。

粉丝系统标签面临的挑战

粉丝系统标签是闲鱼提供给Pro用户进行粉丝管理的基础功能,在“我的粉丝”页面有几个粉丝系统标签分组,包括新粉、老粉和已购粉。其中,已购粉的含义是有过交易成功记录的粉丝,且在已购粉列表中透出历史总购买次数,并按照最新购买时间排序。

对于系统标签,有如下要求:

•须包含全部的历史数据,如已购粉需要统计出历史交易总数。•多场景透出,如IM聊天场景也需要进行标签的透显,QPS较高。

实现目标:

•数据实时更新,反应最新的粉丝购买动态。•查询性能良好,QPS比较大,rt要求高。•数据准确无遗漏。

系统标签的面临的问题和挑战,和文章一开始提到的基本一致,用一句话来说,就是在面对多系统业务数据聚合展示的需求时,如何在保障数据准确性的同时,还兼顾实时性以及查询性能。

下面就这种类型问题的解决进行展开讨论。

解决方案

整体思路与方案选择

为了解决上面的问题,有如下几个比较通用的方案,其各自的优缺点已罗列如下:

image.png

以上的三种方案有各自的优缺点,我们可以考虑把上面的解决思路进行结合,以满足文章一开始提到的要求。

首先采用方案二的方式每天凌晨将不同系统的业务数据进行导出,进行离线关联计算,然后对计算结果进行schema的转化后作为业务数据的离线数据源。这种方式可以满足涵盖多个业务系统全量历史数据的要求,并且能保障数据的准确性。为了在此基础上反应实时数据的变化,可以采用方案三的思路对离线数据进行实时补偿

实时数据补偿可以基于消费业务变更消息来进行。如在系统标签场景中,可以对关注/取关消息、交易消息进行消费,来生成实时补偿数据。业务数据查询时,再对离线和实时补偿数据进行聚合,如下图所示。

image.png

最后,需要保障查询的高吞吐低延时。这里可以分两方面来考虑。首先在技术选型上,需要考虑选择一种高性能的存储系统,这里可以使用kv存储(如LevelDB),保障低延时。其次,可根据查询的数据视图来生成数据存储的schema,尽可能降低数据查询频率与数据后处理的复杂度。

离线数据和实时数据应该怎样聚合才能保障数据准确?离线和实时数据制备链路具体又是如何实现的?下来以已购粉系统标签的为例,介绍一下具体的方案实现。

已购粉标签开发实践

数据结构与聚合逻辑

系统标签数据存储使用的是kv存储。kv存储中的数据,从类型上主要分为一对一交易数据和一对多已购粉列表数据。从离线和实时上,两种不同的类型有各自的离线和实时数据。

之所以有一对一交易数据,是为了用来进行交易次数的正反向查询,并且在新增关注之后,也可实时查询到两个人的历史购买数据。

在查询交易次数时,第一步会先读取一对一离线交易数据,获取历史交易数量。第二步再读取一对一实时补偿交易数据,查询交易时间大于离线数据更新时间的交易订单数,将二者求和即为当前交易次数总和。

查询已购粉列表时,会将一对多实时交易数据和一对多离线数据进行merge,根据最新购买时间重新排序,然后再查询已购数据服务获取交易次数,展示给用户。

系统标签数据制备链路

离线数据的制备,是根据订单数据和关注关系的业务系统存储数据,离线生成离线数据表,再聚合导入到离线的kv存储中。

而实时数据的制备,主要是通过消费交易成功的消息,对一对一交易实时数据进行更新。如果是关注关系变更消息,则进行已购粉列表实时补偿数据更新。

还有一种场景需要处理,如果有新增的粉丝,需要对该粉丝历史购买的数据进行查询,补充到已购粉列表数据中。在具体更新链路中会消费新增关注的消息,然后通过查询离线和实时一对一交易数据获取最新的交易时间,更新到已购粉列表的实时补偿数据中。

方案成果

以上方案实现了既能展示历史全量已购粉丝数据,又能满足及时反应数据实时变化的要求,在保障数据准确度的同时,承载了接近1w的QPS,查询rt可以控制在几毫秒内。

总结与展望

本文以闲鱼系统标签系统为例,介绍了一种通用的解决多业务系统数据实时聚合展示问题的思路。这种思路可以高效快速地满足一些业务需求,但是也会存在一些局限,如热点数据会导致实时补偿数据激增等问题,有待进一步优化。另外在数据存储上的选型,也可以考虑使用分析数据库,如AnalyticDB。

在类似问题的解决上,有其他思路也欢迎留言讨论,谢谢。

猜你喜欢

转载自juejin.im/post/7085923227922333704