技术编程|基于Apache Doris的小米增长分析平台实践( 四 )


4. 获取db锁添加了超时机制 , 如果指定时间内获取不到db锁 , 则取消任务 , 因为这时候be端的rpc请求也已经超时了 , 继续执行取消的任务没有意义 。
5. 对coordinator be每一步操作的耗时添加metric记录 , 如请求开始事务的耗时 , 获取执行计划的耗时等 , 在最终的执行结果中返回 , 方便我们及时了解每个stream load操作的耗时分布 。
经过以上改造 , 我们数据导入稳定性有了比较好的提升 , 至今再没发生过因为fe处理数据导入事务压力过大而导致master节点挂掉的问题 。但是数据导入依然存在一些问题待改进:
1. be端使用了libevent来处理http请求 , 使用了Reactor模式的libevent一般是编写高性能网络服务器的首选 , 但是这里却不适用于我们的场景 , Doris在回调函数中多次地调用包含阻塞逻辑的业务代码 , 如rpc请求 , 等待数据分发完成等 , 由于多个请求共用同一个线程 , 这将部分请求的回调操作不能得到及时的处理 。目前这块我们并没有好的解决方法 , 唯一的应对措施只是调大了libevent的并发线程数 , 以减弱不同请求之间的相互影响 , 彻底的解决方案仍有待社区的进一步讨论 。
2. fe端在更新表的分区版本时采用了db级别的隔离 , 这个锁的粒度过大 , 导致了相同db不同表的数据导入都要竞争db锁 , 这大大降低了fe处理事务的效率 。
3. 发布事务的操作现在依然比较容易出现publish timeout的问题(这意味着无法在指定时间内得到大多数事务相关be节点完成发布事务操作的响应) , 这对数据导入的效率提升是一个比较大的阻碍 。
4.3 Doris在线查询实践
在增长分析业务场景中 , 事件表是我们的核心表 , 需要实时导入明细日志 。这些事件表没有聚合和去重需求 , 而且业务需求是能够查询明细信息 , 所以都选用了冗余模型(DUPLICATE KEY) 。事件表根据天级别分区 , 分桶字段使用了日志id字段(实际上是一个随机产生的md5) , 其hash值能够保证分桶之间数据均匀分布 , 避免数据倾斜导致的写入和查询问题 。
下图是我们线上规模最大的集群最近30天的查询性能统计(查询信息的统计来自于Doris的查询审计日志) , 最近一周每天成功的SQL查询数在1.2w~2w之间 。
技术编程|基于Apache Doris的小米增长分析平台实践
文章图片

文章图片

从图中可以看出 , 使用了Doris后 , 平均查询时间保持在10秒左右 , 最大不超过15秒;查询时间P95一般能保证在30秒内 。这个查询体验 , 相对于原来的SparkSQL , 提升效果比较明显 。
Doris提供了查询并发度参数parallel_fragment_exec_instance_num , 查询服务端根据正在运行的任务个数动态调整它来优化查询 , 低负载下增加并发度提高查询性能 , 高负载下减少并发度保证集群稳定性 。在分析业务查询profile时 , 我们发现Doris默认执行过程中exchange前后并发度是一样的 , 实际上对于聚合型的查询 , exchange后的数据量是大大减少的 , 这时如果继续用一样的并发度不仅浪费了资源 , 而且exchange后较少数据量用较大的并发执行 , 理论上反而降低了查询性能 。因此 , 我们添加了参数doris_exchange_instances控制exchange后任务并发度(如下图所示) , 在实际业务测试中取得了较好的效果 。
技术编程|基于Apache Doris的小米增长分析平台实践
文章图片

文章图片

这个对数据量巨大的业务或者exchange后不能明显降低数据量级的查询并不明显 , 但是这个对于中小业务(尤其是那些用了较多bucket的小业务)的聚合或join查询 , 优化比较明显 。我们对不同数量级业务的测试 , 也验证了我们的推断 。我们选取了一个数据量4亿/日的小业务 , 分别测试了不同场景下查询性能:


推荐阅读