跳到主要内容

Apache Doris 在京东客服 OLAP 中的应用实践

Apache Doris最佳实践

引言

Apache Doris 是一款开源的 MPP 分析型数据库产品,不仅能够在亚秒级响应时间即可获得查询结果,有效的支持实时数据分析,而且支持 10PB 以上的超大的数据集。相较于其他业界比较火的 OLAP 数据库系统,Doris 的分布式架构非常简洁,支持弹性伸缩,易于运维,节省大量人力和时间成本。目前国内社区火热,也有美团、小米等大厂在使用。

本文主要讨论京东客服在人工咨询、客户事件单、售后服务单等专题的实时大屏,在实时和离线数据多维分析方面,如何利用 Doris 进行业务探索与实践。近些年来,随着数据量爆炸式的增长,以及海量数据联机分析需求的出现,MySQL、Oracle 等传统的关系型数据库在大数据量下遇到瓶颈,而 Hive、Kylin 等数据库缺乏时效性。于是 Apache Doris、Apache Druid、ClickHouse 等实时分析型数据库开始出现,不仅可以应对海量数据的秒级查询,更满足实时、准实时的分析需求。离线、实时计算引擎百花齐放。但是针对不同的场景,面临不同的问题,没有哪一种引擎是万能的。我们希望通过本文,对京东客服业务在离线与实时分析的应用与实践,能够给到大家一些启发,也希望大家多多交流,给我们提出宝贵的建议。

京东客服业务形态

京东客服作为集团服务的入口,为用户和商家提供了高效、可靠的保障。京东客服肩负着及时解决用户问题的重任,给用户提供详细易懂的说明与解释;为更好的了解用户的反馈以及产品的状况,需要实时的监控咨询量、接起率、投诉量等一系列指标,通过环比和同比,及时发现存在的问题,以更好的适应用户的购物方式,提高服务质量与效率,进而提高京东品牌的影响力。

Easy OLAP 设计

01 EasyOLAP Doris 数据导入链路

EasyOLAP Doris 数据源主要是实时 Kafka 和离线 HDFS 文件。实时数据的导入依赖于 Routine Load 的方式;离线数据主要使用 Broker Load 和 Stream Load 的方式导入。

EasyOLAP Doris 数据导入链路

EasyOLAP Doris 数据导入链路

02 EasyOLAP Doris 全链路监控

目前 EasyOLAP Doris 项目的监控,使用的是 Prometheus + Grafana 框架。其中 node_exporter 负责采集机器层面的指标,Doris 也会自动以 Prometheus 格式吐出 FE、BE 的服务层面的指标。另外,部署了 OLAP Exporter 服务用于采集 Routine Load 相关的指标,旨在第一时间发现实时数据流导入的情况,确保实时数据的时效性。

EasyOLAP Doris monitoring link

EasyOLAP Doris 监控链路

640

EasyOLAP Doris 监控面板展示

03 EasyOLAP Doris 主备双流设计

EasyOLAP Doris 为了保障 0 级业务在大促期间服务的稳定性,采取了主备集群双写的方式。当其中一个集群出现抖动或者数据存在延迟的情况,用户可以自主地快速切换到另一个集群,尽可能的减少集群抖动给业务带来的影响。

03 EasyOLAP Doris Primary-Secondary Dual Stream Design

EasyOLAP Doris 主备双流设计

04 EasyOLAP Doris 动态分区管理

京东 OLAP 团队分析需求之后,对 Doris 做了一定的定制化开发,其中就涉及到动态分区管理功能。尽管社区版本已经拥有动态分区的功能,但是该功能无法保留指定时间的分区。针对京东集团的特点,我们对指定时间的历史数据进行了留存,比如 618 和 11.11 期间的数据,不会因为动态分区而被删除。

动态分区管理功能能够控制集群中存储的数据量,而且方便了业务方的使用,无需手动或使用额外代码来管理分区信息。

Doris 缓存机制

01 需求场景

致力于不断提升用户体验,京东客服的数据分析追求极致的时效性。离线数据分析场景是写少读多,数据写入一次,多次频繁读取;实时数据分析场景,一部分数据是不更新的历史分区,一部分数据是处于更新的分区。在大部分的分析应用中,存在下述几种场景:

  • 高并发场景:Doris 较好的支持高并发,但是过高的 QPS 会引起集群抖动,且单个节点无法承载太高的 QPS ;
  • 复杂查询:京东客服实时运营平台监控根据业务场景需展示多维复杂指标,丰富指标展示对应多种不同的查询,且数据源来自于多张表,虽然单个查询的响应时间在毫秒级别,但是整体的响应时间可能会到秒级别;
  • 重复查询:如果没有防重刷机制,由于延迟或手误,重复刷新页面会导致提交大量重复的查询;

针对上述场景,在应用层有解决方案——将查询结果放入到 Redis 中,缓存会周期性的刷新或者由用户手动刷新,但是也会存在一些问题:

  • 数据不一致:无法立即对数据的更新作出响应,用户接收到的结果可能是旧数据;
  • 命中率低:如果数据实时性强,缓存频繁失效,则缓存的命中率低且系统的负载无法得缓解;
  • 额外成本:引入外部组件,增加系统复杂度,增加额外成本。

02 缓存机制简介

在 EasyOLAP Doris 中,一共有三种不同类型 Cache。根据适用场景的不同,分别为 Result Cache、SQL Cache 和 Partition Cache 。三种缓存都可以通过 MySQL 客户端指令控制开关。

这三种缓存机制是可以共存的,即可以同时开启。查询时,查询分析器首先会判断是否开启了 Result Cache ,在 Result Cache 开启的情况下先从 Result Cache 中查找该查询是否存在缓存,如果存在缓存,直接取缓存的值返回给客户端;如果缓存失效或者不存在,则直接进行查询并将结果写入到缓存。缓存放在各个 FE 节点的内存中,以便快速读取。

SQL Cache 按照 SQL 的签名、查询的表的分区的 ID 和分区最新版本号来存储和获取缓存。这三者一起作为缓存的条件,其中一者发生变化,如 SQL 语句变化、数据更新之后分区版本号变化,都会无法命中缓存。在多表 Join 的情况下,其中一张表的分区更新,也会导致无法命中缓存。SQL Cache 更适合 T+1 更新的场景。

Partition Cache 是更细粒度的缓存机制。Partition Cache 主要是将一个查询根据分区并行拆分,拆分为只读分区和可更新分区,只读分区缓存,更新分区不缓存,相应的结果集也会生成 n 个,然后再将各个拆分后的子查询的结果合并。因此,如果查询 N 天的数据,数据更新最近的 D 天,每天只是日期范围不一样但相似的查询,就可以利用 Partition Cache ,只需要查询 D 个分区即可,其他部分都来自缓存,可以有效降低集群负载,缩短查询响应时间。

一个查询进入到 Doris,系统先会处理查询语句,并将该查询语句作为 Key,在执行查询语句之前,查询分析器能够自动选择最适合的缓存机制,以确保在最优的情况下,利用缓存机制来缩短查询相应时间。然后检查 Cache 中是否存在该查询结果,如果存在就获取缓存中的数据返回给客户端;如果没有缓存,则正常查询,并将该查询结果以 Value 的形式和该查询语句 Key 存储到缓存中。Result Cache 可以在高并发场景下发挥其作用,也可以保护集群资源不受重复的大查询的侵占。SQL Cache 更加适合 T+1 的场景,在分区更新不频繁以及 SQL 语句重复的情况下,效果很好。Partition Cache 是粒度最小的缓存。在查询语句查询一个时间段的数据时,查询语句会被拆分成多个子查询。在数据只写一个分区或者部分分区的情况下,能够缩短查询时间,节省集群资源。

为了更好的观察缓存的效果,相关指标已经加入到 Doris 的服务指标中,通过 Prometheus 和 Grafana 监控系统获取直观的监控数据。指标有不同种类的 Cache 的命中数量、不同种类的 Cache 命中率、 Cache 的内存大小等指标。

03 缓存机制效果

京东客服 Doris 主集群,11.11 期间在没有开启缓存时,部分业务就导致 CPU 的使用率达到 100% ;在开启 Result Cache 的情况下,CPU 使用率在 30%-40% 之间。缓存机制确保业务在高并发场景下,能够快速的得到查询结果,并很好的保护了集群资源。

Doris 在 2020 年 11.11 大促期间的优化

01 导入任务优化

实时数据的导入一直是一个挑战。其中,保证数据实时性和导入稳定性是最重要的。为了能够更加直观的观察实时数据导入的情况,京东 OLAP 团队自主开发了 OLAP Exporter ,用于采集实时数据导入相关的指标,如导入速度、导入积压和暂停的任务等。通过导入速度和导入积压,可以判断一个实时导入任务的状态,如发现任务有积压的趋势,可以使用自主开发的采样工具,对实时任务进行采样分析。实时任务主要有三个阈值来控制任务的提交,分别是每批次最大处理时间间隔、每批次最大处理条数和每批次最大处理数据量,一个任务只要达到其中一个阈值,该任务就会被提交。通过增加日志,发现 FE 中的任务队列比较繁忙,所以,参数的调整主要都是将每批次最大处理条数和每批次最大处理数据量调大,然后根据业务的需求,调整每批次最大处理时间间隔,以保证数据的延迟在每批次最大处理时间间隔的两倍之内。通过采样工具,分析任务,不仅保证了数据的实时性,也保证了导入的稳定性。另外,我们也设置了告警,可以及时发现实时导入任务的积压以及导入任务的暂停等异常情况。

02 监控指标优化

监控指标主要分为两个部分,一个是机器层面指标部分,一个是业务层面指标部分。在整个监控面板里,详细的指标带来了全面的数据的同时,也增加了获取重要指标的难度。所以,为了更好的观察所有集群的重要指标,单独设立一个板块—— 11.11 重要指标汇总板块。板块中有 BE CPU 使用率、实时任务消费积压行数、TP99、QPS 等指标。指标数量不多,但是可以观测到所有集群的情况,这样可以免去在监控中频繁切换的麻烦。

03 周边工具支持

除了上述说到的采样工具和 OLAP Exporter ,京东 OLAP 团队还开发了一系列的 Doris 维护工具。

  1. 导入采样工具:导入采样工具不仅可以采集实时导入的数据,而且还支持调整实时导入任务的参数,或者在实时导入任务暂停状态下,生成创建语句(包括最新的位点等信息)用于任务的迁移等操作。

  2. 大查询工具:大查询不仅会造成集群 BE CPU 使用率的抖动,还会导致其他查询响应时间变长。在有大查询工具之前,发现集群 CPU 出现抖动,需要去检查所有 FE 上的审计日志,然后再做统计,不仅浪费时间,而且不够直观。大查询工具就是为了解决上述的问题。当监控侧发现集群有抖动,就可以使用大查询工具,输入集群名和时间点,就可以得到该时间点下,不同业务的查询总数,时间超过 5 秒、 10 秒、 20 秒的查询个数,扫描量巨大的查询个数等,方便我们从不同的维度分析大查询。大查询的详细情况也将被保存在中间文件中,可以直接获取不同业务的大查询。整个过程只需要几十秒到一分钟就可以定位到正在发生的大查询并获取相应的查询语句,大大节约了时间和运维成本。

  3. 降级与恢复工具:为了确保 11.11 大促期间, 0 级业务的稳定性,在集群压力超过安全位的时候,需要对其他非 0 级业务做降级处理,待度过高峰期后,再一键恢复到降级前的设置。降级主要是降低业务的最大连接数、暂停非 0 级的实时导入任务等。这大大增加了操作的便捷性,提高了效率。

  4. 集群巡检工具:在 11.11 期间,集群的健康巡检是极其重要的。常规巡检包括双流业务的主备集群一致性检查,为了确保业务在一个集群出现问题的时候可以快速切换到另一个集群,就需要保证两个集群上的库表一致、数据量差异不大等;检查库表的副本数是否为 3 且检查集群是否存在不健康的 Tablet ;检查机器磁盘使用率、内存等机器层面的指标等。

总结与展望

京东客服是在 2020 年年初开始引入 Doris 的,目前拥有一个独立集群,一个共享集群,是京东 OLAP 的资深用户。

在业务使用中也遇到了例如任务调度相关的、导入任务配置相关的和查询相关等问题,这也在推动京东 OLAP 团队更深入的了解 Doris 。我们计划推广使用物化视图来进一步提升查询的效率;使用 Bitmap 来支持 UV 等指标的精确去重操作;使用审计日志,更方便的统计大查询、慢查询;解决实时导入任务的调度问题,使导入任务更加高效稳定。除此之外,我们也计划优化建表、创建优质 Rollup 或物化视图以提升应用的流畅性,加速更多业务向 OLAP 平台靠拢,以提升应用的影响力。