赞
踩
有赞是国内领先的电商 SaaS 服务商,目前拥有社交电商、新零售、美业、教育及有赞国际化五大业务体系,通过旗下的社交电商、门店管理、解决方案以及其他新零售 SaaS 软件产品,全面帮助商家解决在移动互联网时代遇到的推广获客、成交转化、客户留存、复购增长、分享裂变等问题,帮助每一位重视产品和服务的商家实现顾客资产私有化、互联网客群拓展、经营效率提升,最终助力商家成功。
在面对商家与开发者的定制化服务需求的同时,为了能够更好地支持商家有效解决引流获客、分销体系等难题,有赞为商家搭建了 OLAP 分析系统,提供以下 SaaS 服务场景:
早期架构如图所示,数据主要来源于业务数据库 Binlog 与用户日志等原始数据,通过实时与离线两条链路分别对数据进行处理。其中原始数据首先导入至 Apache Kafka 与 NSQ 消息中间件,一部分会通过 Apache Flink 进行流处理计算并与存储在 HBase 中的维度明细表进行关联,另一部分数据会存储于 Apache Hive 与 HDFS 中作为离线数据,通过 Apache Spark 计算写入至 OLAP 引擎中。
有赞数据架构主要使用了以下三种 OLAP 引擎,各个组件根据业务场景的特点与需求为上游应用提供不同场景的查询与分析:
然而由于该架构组件过多、架构冗余等问题导致维养、开发、业务应用等方面带来了一系列的挑战,具体如下:
针对部份 SaaS 场景的高并发高 QPS 查询场景,Clickhouse 的查询能力表现不够理想。由于 Clickhouse 组件本身设计的问题,无法支持多表或大表 Join 的查询场景,这就导致一旦出现关联查询场景,业务方需要重新寻找解决方案,使整体查询效率低下。
Apache Kylin 在数据处理过程中采用了预计算的方式,通过在多维 Cube 构建过程中完成聚合计算,并生成 T+1 数据报表。对部分在夜间经营的商家而言,他们需要等待一天时间才能查看前一天的报表数据,这无法满足用户对于时效性的需求。
基于上述架构痛点,我们对市面上的架构进行了调研与选型,希望选择一款能够简化当前复杂架构、统一 OLAP 技术栈的引擎。我们除了分析 OLAP 性能本身对于业务的帮助,还需要评估架构改造所带来的收益成本比,思考架构进行迁移和重构之后所带来的 ROI 是否符合预期。
对于收益而言,我们需要评估新架构引入后的性能是否如预期提升,将 Apache Doris 分别与 Clickhouse、Druid、Kylin 进行对比评估。
对于成本而言,我们首先会考虑在替换过程中,周边工具开发的成本,其中涉及监控、告警、上下游依赖平台等一系列工具的构建与研发;其次业务的迁移会涉及大量业务改造与协调,如何催动业务方进行改造、提供更丰富的改造工具、尽可能降低投入成本也是我们主要考虑的问题。
经过一系列评估后,我们发现基于 Apache Doris 进行架构迭代,其不论是在业务赋能还是成本方面,都能够有效解决当前架构的痛点,极大程度地实现降本增效的目标,整体迭代的预期收益明显高于改造代价,因此我们决定基于 Apache Doris 构建统一实时数仓,具体评估分析如下:
如上图所示,新架构将基于 Apache Doris 搭建统一实时数仓,替换原架构中的三个 OLAP 组件,解决由组件过多引起的接入成本高、资源使用增加、数据链路过长等问题,最终能够减轻业务方的负担、减少整体框架的硬件成本、实现引擎与技术栈统一等目标。
在有赞绝大多数应用场景中,原架构都存在数据重复、数据延迟需要修复的情况,引入 Apache Doris 之后,我们将利用其 Unique Key、Duplicate Key、Aggregate Key 模型功能实现高效的数据更新,保证写入效率,并且 Doris 架构具备弹性伸缩的能力,引入后能够极大程度地降低故障发生的概率以及出现故障时数据恢复的效率。
此外我们还将引入 Apache Doris 以下功能:
在确定架构迁移之后,我们首先选择用 Apache Doris 来替换 Clickhouse 组件,主要由于在业务增长时 Clickhouse 查询性能瓶颈较大、集群扩缩容操作过于复杂等痛点使运维团队的工作量大幅增加,加之大表 Join 能力差、高 QPS 查询性能差等一系列问题无法满足业务方诉求,且 Clickhouse 功能与 Apache Doris 相似,业务方更便于迁移, 因此我们优先替换 Clickhouse 组件。
接下来,我们将分享 Doris 替换 Clickhouse 的迁移方案,架构迭代的整体节奏分为 SQL 语句改写实现自动导入(包含建表语句与查询语句的改写)、查询性能测试、稳定性测试、导入性能测试与优化,在结束一系列测试后最终进行整体业务数据的迁移。
目前,我们针对 Unique Key 模型与 Duplicate Key 模型制作了 SQL 建表语句改写工具,如上图所示,支持通过配置参数自动将 Clickhouse 建表语句转为 Doris 建表语句,该工具的主要功能具体如下:
与建表语句改写工具类似,SQL 查询语句改写能够自动将 Clickhouse 查询语句转成 Doris 查询语句,主要为了双跑进行数据准确性和稳定性验证。在改写过程中,我们梳理了以下注意事项:
COUNTIF()
需要转换为 SUM(CASE WHEN _ THEN 1 ELSE 0)
以达到相同的效果, ORDER BY
与 GROUP BY
需要利用 Doris 开窗函数进行转化,此外 Clickhouse 利用 Array Join
进行列传行,对应 Doris 则需要利用 Explode
、 Lateral View
来展开;sqlparse
进行递归,检查出所有的子查询进行设置。查询性能测试主要通过 Apache Doris 与原架构 Clickhouse 组件在三个核心业务场景(CDP、DMP、CRM)下的对比表现。我们选用了线上等比的集群规模,通过查询 SQL 性能对比、大表 Join 性能两方面进行对比压测,同时检测 Doris 在查询期间的 CPU 以及 内存损耗。接下来我们将详细介绍压测过程与具体性能数据对比。测试集群规模3 FE + 16 BE,BE单节点配置为( 32C 128 G 7T SSD)。
核心场景下查询 SQL 性能对比
在进行查询 SQL 性能测试中,我们主要基于当前实际应用场景最多的三大系统进行查询,分别是 CDP、DMP、CRM 场景的对比。最终有效查询 SQL 16 条,线上场景下查询 SQL 的具体特点如下:
如表格所示,我们将 Doris 与 Clickhouse 16 条 SQL 查询时间对比,其中有 10 条 SQL Doris 查询性能优于 Clickhouse。 此外我们将 Doris 与 Clickhouse 查询时间总和进一步对比,在对 Doris 表结构设计优化后,Doris 整体查询速度相比 Clickhouse 快 2-3 倍。
大表 Join 查询性能测试
在关联查询测试中,以 CDP 场景下的相关数据表为基础,我们选用了不同数据量级的主表与维表数据,主表测试数据量分别为 40 亿的用户行为表、250 亿的用户额外属性表、960 亿的用户额外属性表;维表以 kdt_id + user_id 为基础,测试量级分别为 100 万、1000 万、5000 万、1 亿、5 亿、10 亿及 25 亿维表数据量。为了测试更加全面,关联查询测试分为完全关联与过滤关联两种测试,完全关联是将主表与维度表直接进行 Join,过滤关联是在相同主表量级关联中,增加了 WHERE
条件对指定的两个店铺 ID 进行过滤。
具体的查询测试表现如下:
WHERE
条件过滤后的数据为 4100 万,相较于 Clickhouse,Doris 在维表数据量小的情况下能够达到 2-3 倍的性能提升,在维表数据量大的情况达到 10 倍以上的性能提升,其中当维度数据表超过 1 亿后,Doris 依旧可以稳定查询,而 Clickhouse 由于 OOM 情况导致查询失败。除响应性能外,我们还对于 Doris 的 CPU 与内存损耗进行检测,发现 Doris 在数百亿计大表关联查询的情况下集群负载依旧稳定。综上,Apache Doris 在绝大部份场景查询响应速度快于 Clickhosue ,特别是在大表 Join 场景下,Apache Doris 性能表现完全优于 Clickhouse。
在查询压测完成后,我们开始将 Doris 与 Clickhouse 线上双跑以进一步验证 Doris 的稳定性。具体步骤如下:
数据导入性能测试是我们重要关注的环节之一,Apache Doris 本身对于实时数据和离线数据的导入提供了比较丰富的导入方式,实时数据的导入方式主要是通过 Apache Flink 将 NSQ 和 Apache Kafka 的数据实时通过 Stream Load 方式写入 Apache Doris 中。在离线数据中,Doris 提供了多种导入方式:
由于离线数据量较大,针对这类数据我们将几种数据导入方式进行了性能测试对比,通过明细数据的各个数据量级对比测试导入时间。 测试集群规模 3 FE + 16 BE,BE 单节点配置为( 32C 128 G 7T SSD)测试结果:
Spark Doris Connector 格式导入的并行度为 80,单批为 100 万,集群的负载情况如下:
根据上方测试结果,我们进一步分析各种导入方式的优势与后续调优方案,希望以下的调优实践能够帮助到有类似需求的开发者们:
Doris Insert Into
Insert Into 方式能够提供快速导数性能,在用法上也相对简单,目前该方式的导入性能已经足够支持我们的业务需求。
Spark Doris Connector 支持阻塞写入
Spark Doris Connector 导入方式更具有通用性,能够解决大量数据导入的问题,导入性能相对稳定,在导入过程我们需要合理控制导入速率与导入并行度。考虑到我们的业务场景每天会涉及千亿级别的数据量并花费 5-6 个小时进行导入,对于这类大表数据的导入如果因为 BE 写入被拒绝导致失败,会造成下游数据产出延迟等问题。此外,在 2.0 版本中,类似 -235,-238 错误已经在 Apache Doris 内核层面解决,无需用户再手动处理此类问题。
我们主要从控制写入速度入手,整体改造原理是通过指数退避写入的方式延迟阻塞,利用配置参数使大数据量出现导入异常时可以等待重试,不让任务失败。通过最大阻塞次数、单次最大阻塞时间、需要阻塞异常捕获关键词这三个参数来捕获阻塞异常情况,实现阻塞退避功能。最终在该设置下,我们的大表导入数据成功率达 95%以上。
1 相关 PR: https://github.com/apache/doris-spark-connector/pull/117
Spark Doris Connector 支持 Bitmap 数据导入
在阅读 Apache Doris 官方文档时,我们发现 Spark Load 的方式可以对 Bitmap 数据进行导入,同时能够将 Bitmap 数据计算放在 Spark 集群中进行计算。在业务实践中,我们使用 Spark Doris Connector 更为常用,于是开始探索通过 Spark Doris Connector 的方式实现 Bitmap 数据导入。
如上图所示,Bitmap 建表语句主要分为三个字段,其中最后一个字段是将 CASE_ID 进行 Bitmap 计算。在与社区成员沟通之后,提供一种设置 Doris Read Field 选项,写除 Bitmap 列外的其他列,同时在 Doris Write Field 中做映射处理。最终实现如上图所示方式通过 Spark Doris Connect 直接将 Apache Hive 明细数据导入 Apache Doris 的 Bitmap 数据中。
Spark Doris Connector CSV 格式导入优化
在我们的导入流程中,无论是 Spark Doris Connector 还是 Flink Doris Connector,最终都是利用 Stream Load 的方式进行导入,其导入文件 CSV 与 JSON 有两种导入格式且对于不同格式的选择,导入性能的损耗与速率也是不同的。
在优化前,我们进行了测试,以数十亿数据规模、26 个字段的业务表进行导入性能测试,发现 CSV 格式比 JSON 的导入速度快近 40% 且其内存消耗是更低的,这也是为什么 Apache Doris 官方推荐使用 CSV 格式。
其中值得注意的是使用 CSV 格式进行导入时,设置合理的字段分隔符和换行符对于 CSV Reader 识别效率是至关重要的,如果 BE 的 CSV Reader 对于字段中最后一个字符和分隔符的首字符相同时,则无法识别分隔符。
通过官方文档的提示,我们发现 Stream Load 中能够支持参数配置去除字段最外层的双引号,基于此我们决定在 Spark Doris Connector 写入阶段添加用户设置配置,在字段外层拼接双引号,保证不用选定特殊字符依然能够有效分隔,同时在 Stream Load 写入阶段添加去除最外层双引号的配置。通过两端配置,能够保证即使业务数据很复杂的情况下,也无需为字段符号的识别而烦恼,有效保证字段能够正常分割。
2 相关 PR: https://github.com/apache/doris-spark-connector/pull/119
Spark Load
Spark Load 导入方式的特点是基于 Spark 资源进行 Shuffle、排序等工作将文件输出在 HDFS 中,之后 BE 节点能够直接读取 HDFS 上的文件并按照 Doris 格式写入。基于这种方式,在测试过程中我们发现当数据量越大时导入速度越快、越能够节省 Doris 的集群资源,不会带来较大性能损耗。
由于 Spark Load 在临时修复数据场景中使用频繁,我们也基于测试进一步优化。通过官网文档与社区帮助下我们发现,Spark Load 阶段的导入速率主要由单次导入并发度和单次 BE 导入数据处理量两方面参数影响,且两个参数都与源文件大小、BE 节点密切相关。当控制其他变量的情况下,源文件越小,导入速度越慢,因此我们认为在 ETL 阶段充分利用 Spark 经营资源并且合理设置 Bucket 数量能够有效加速导入速率。
在整体测试环节中,基于 Apache Doris 2.0 正式版本的性能测试已经完成,我们对于 Doris 的查询性能表现是十分满意的。此外,对于导入性能,我们在测试时首先采用的是 Doris 2.0-Alpha 版本,发现在导入过程中存在偶发性 CPU 瓶颈的问题,例如当通过 Spark Doris Connector 的方式,Spark 使用资源和 Doris 导入数据 CPU 存在一定的瓶颈。同时,我们也将问题反馈给社区,在经过社区优化与 2.0-Beta 版本发布后,稳定性得到了改善。
目前,我们正在与 Clickhouse 线上双跑对 Doris 的稳定性进一步验证,同时我们正在对 Spark Doris Connector 导入方式的的进行性能优化、开发导入周边工具以完成组件替换等落地工作。后续在逐步完成 Clickhouse 的业务迁移后,基于 Clickhouse 的迁移经验,对未迁移的存量业务逐步完成 Druid、Kylin 两个组件的迁移,最终基于 Apache Doris 构建极速分析、实时统一的数据仓库。
在此非常感谢 SelectDB 技术团队的积极响应与专业解答,加速有赞业务的迁移进程,也希望通过这篇文章为准备进行架构迁移的企业提供相关实践经验和 OLAP 选型参考。最后,我们也会持续参与社区活动,将相关成果贡献回馈社区,希望 Apache Doris 飞速发展,越来越好!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。