基于 Elasticsearch 的数据报表方案

avatar
开发 @网易智企

文 | 闵令超 网易智企高级应用开发工程师

前言

数据报表分析对于企业管理者的分析决策有着至关重要的作用,因此数据报表的灵活可用以及数据的准确性显得至关重要。本文会介绍基于 Elasticsearch 的数据指标系统,希望对大家有一定的借鉴和帮助。

背景

数据报表通常在业务开发中是必不可少的一部分,对于 To B 的应用更是如此。企业在使用产品的过程中必然需要对于整个的业务情况有一个准确的判断和分析,这就需要我们能够提供给企业尽可能多维度的详细的数据报表。

初始数据报表方案

在项目的初期,为了业务的快速发展,往往采取的是比较简单的架构进行处理,如下图所示。根据产品对于指标的定义,通常开发通过代码的形式直接定义指标的运算,依赖自研或者开源的定时任务调度系统,跑出相应的指标计算结果,保存到中间表中,查询的时候根据不同的筛选条件,从不同的中间表中获取指标的计算结果。

存在的问题

  1. 口径不一致。在上述架构中,当不同的业务有数据交叉场景时,往往是从其他业务方复制相关指标计算的代码拿来使用,这会造成数据指标口径发生变化时,各个业务的相同的指标出现了指标口径不一致的问题。
  2. 开发效率低。每次添加指标/修改指标都需要修改代码、添加数据库字段等多步骤 ,导致整个的指标开发周期特别的长。
  3. 不同维度的指标的计算逻辑处理逻辑、任务不同,每次修改逻辑需要修改多个地方。

基于 Elasticsearch 的数据报表方案

随着业务的发展,指标的定义越来越多,报表也变得越来越丰富,基于定时任务架构的弊端暴露的越来越明显,开发的负担变的越来越重,在这时候,就需要对上述架构升级,减少业务开发的工作量。此阶段,由于数据量仍然不是很大,同时为了业务方便开发和维护,可以参考数仓系统,搭建一个简易的数据指标系统。

考虑到上述存在的问题,首先需要明确大的方向和目标。

  1. 规范化数据指标的开发流程,保证数据口径的统一。
  2. 提供数据指标平台,便于业务开发能够基于 SQL 开发大部分的指标,减少指标的开发工作量,提高指标的开发效率。
  3. 明确整个数据报表的生产流程,参考数仓建设方案,规范化整个数据指标的产出流程。
  4. 提供有效的 SDK,方便业务方的调用。
  5. 需要支持多数据源,在业务中往往不止一个数据源,可能会有 MySQL、Hive、ElasticSearch 等多个数据源,所以需要支持从多数据源汇集数据的能力。
  6. 需要对于指标的异常进行及时告警,方便开发排查业务异常。

术语简介

  • 原子指标:原子指标是指最细粒度的指标,即不能再向下拆分的指标,例如 指标 A=指标 B+指标 C,那么这里指标 B 和指标 C 即为原子指标。
  • 复合指标:复合指标是多个原子指标通过计算处理获取的结果,例如 指标 A=指标 B+指标 C,这里指标 A 就是表示复合指标。
  • 维度:数据查询的角度。一般是指日期、客服组等信息。如下图中标红部分即为维度信息。

  • 时间周期:时间周期是用来描述一个指标的计算范围。在统计指标的过程中必须指定用于计算的时间周期字段,通常,原子指标的计算的最小时间周期为小时,天数据基于小时数据做聚合得出。
  • 报表:报表是一系列复合指标/原子指标的集合,通常业务方获取的指标数据都是一张报表。
  • 业务域:一个项目往往会有多条业务线,每条业务线我们可以理解为一个业务域,以七鱼为例,如在线会话、呼叫等,任何的原子指标、复合指标、报表都属于某一个业务域。

架构

基于上述目标,这里以 Elasticsearch 的聚合查询能力为依托,搭建如下的数据指标平台架构。

整体分为5大部分:

  1. 原始数据层: 主要是关系型数据库中的表数据
  2. 明细层: 主要是通过 binlog 同步到 Elasticsearch 中保存。
  3. 业务层:主要包括两大部分,指标计算和项目管理。指标计算主要是基于明细层数据以及业务开发和产品定义的指标口径,产出相应维度的指标。项目管理主要是维度、指标、业务域相关配置等。
  4. 网关:提供统一的 SDK 便于业务方的直接调用。
  5. 业务方/控制台,业务方调用sdk获取报表数据以及维度、指标等控制台的配置。

从整个架构体系来看,上述架构主要是统一了各个业务的原始层和明细层数据,并基于此开发了数据指标配置系统,能够快速的响应业务需求,将数据指标的开发周期大大缩短,也避免了开发人员直接在代码里面编写指标计算代码,带来口径不统一或者重复建设的问题。

原始数据层/明细层

从上图中可以看到,最底层部分是原始数据层和明细层,这个是整个架构的基础所在。从原始层到明细层同步采用 binlog+ 自定义消息的同步方式,具体架构如下:

同步数据主要有三种模式:

  1. binlog 模式。通过 binlog 模式,同步数据库中相应表中的数据,根据指定的关联表的唯一键,可以将多张表的数据同步到一张大宽表中,方便指标的运算。binlog 同步可以依靠开源的 Canal、Maxwell 等组件,也可以是自研组件等。
  2. 全量同步模式。当 binlog 同步出现数据丢失,或者需要历史数据同步时,采用全量同步的模式进行数据的补全和修正。全量同步主要依赖业务的定时任务调度系统。
  3. 自定义 topic。当数据统计需要添加自定义字段而又不想在数据库中添加相应字段时,可以通过自定义 topic 将想要添加的字段添加到对应的大宽表中。

明细层数据的存储在 es 中,通过明细层可以完成业务到数据的转换,保存维度信息以及最细粒度的数据。聚合层可基于明细层进行复杂的指标计算。

明细层数据保存在 Elasticsearch 中,我们需要考虑索引的分片规则,防止由于分片规则导致索引的数据分布不均匀,会对于搜索和聚合产生较大的影响。对于索引的划分,通常采用月份进行划分索引,这样保证明细数据在各个索引中会比较均匀的分布,同时,当索引较多时,也方便对于历史索引做冷数据处理,聚合的速度也能够保存比较稳定的状态,不会因为某个索引的数据过多,降低聚合的速度。

聚合层

聚合层负责对业务指标进行沉淀、向上提供统一的计算口径,同时可以基于现有的指标进行组合查询,避免重复计算指标。目前指标的查询计算均通过 Elasticsearch 计算。通过依赖 ElasticsearchSql 组件,可以使得业务方通过编写 SQL 的方式定义原子指标,如下

SELECT COUNT(*FROM table_1 
WHERE condition_1<>2 AND condition_2=2 GROUP BY A,B

如上面语句所示,WHERE 即原子指标计算的查询条件,GROUP BY 即指标计算的维度。具体计算流程如下:

当然在聚合指标数据的过程中,过多的指标聚合查询,可能会导致 Elasticsesrch 的 CPU 负载过高,为了避免这个问题我们需要调整任务策略,每个指标一次批量处理多家企业,这样可以大大降低请求的次数,提高了任务的执行速度,保证了 Elasticsearch 集群的稳定。

在实际的业务指标开发中,经常会碰到产品对于指标的定义的改变,当指标定义改变时,需要测试用户对于改指标变化的反馈程度,以及能够提供相应的策略,方便回滚到老的指标定义的数据。

针对上面的问题,我们提出了环境和版本的概念。指标的上线会有业务定义的多套环境,例如灰度和全量。通过环境,可以给一部分企业尝试切换新的指标定义,测试反馈效果。同时,每一个原子指标会有多个版本,每一次定义的改变都会产生一个版本,复合指标可以选择相应版本的指标进行结果的计算,如果客户对于新的指标定义不满意,依然可以回滚到之前的版本。具体的操作流程如下图所示:

业务方调用

业务方添加指标并调用的整个流程如下图:

如上图所示,业务方需要添加指标时,需要在原子指标池中添加相应的指标计算规则,默认初始化版本为 V1,如果需要同步历史数据则在添加指标时创建历史数据同步任务,创建完任务之后,系统会自动计算并同步所选时间段的指标数据,历史数据同步完成之后方可在指标建模中勾选新指标。指标建模完成之后,通常是需要业务方在自己的定制化报表中添加建模之后的指标,通过 SDK 获取相应的报表时,会自动返回添加的指标值。

总结与展望

当然,上述的架构仍有一定的局限性,当业务发展到比较大的规模,业务线逐渐增多,业务数据量级也逐渐增大,企业对于数据的需求要求会变的更加的多样,往往我们的报表不能充分的满足客户的需求,这个时候,就需要给客户提供自定义报表的能力,使其不局限于系统内提供的报表查询维度,对于一个指标,企业可以从任意的可选维度进行查询分析。这个时候这套方案已经不能满足客户的需求。所以需要对报表系统再次进行架构升级,这时候可以搭建业务内部的数仓系统,整合内部企业分析以及对外数据报表输出能力。

更多技术干货,欢迎关注【网易智企技术+】微信公众号