Presto 架构原理与优化介绍|青训营笔记

164 阅读8分钟

Presto 架构原理与优化介绍|青训营笔记

这是我参与「第四届青训营」笔记创作活动的的第5天。

一、课程概述

  1. 大数据与OLAP的演进之路,包括Presto的设计理念
  2. Presto的基础概念与原理
  3. Presto的特色和重要机制
  4. Presto常用优化

二、详细内容

1. OLAP概述

1.1 大数据

在信息化时代背景下由于信息交换(通信网络带宽的大幅增长),信息存储(计算机存储量的大幅增长)和信息处理(整理、转换、分析数据能力大幅增加)而产生的数据。

  • 大数据不等价于大规模数据量
  • Hadoop的出现:基于廉价机器的存算分离的大规模分布式处理系统

1.2 OLAP概述

  • Online Analytical Processing
  • 对业务数据进行多维分析,并提供复杂计算,趋势分析和复杂数据建模的能力
  • 商务智能BI应用程序背后的技术
  • 发展为基于数据库通过SQL对外提供分析能力
  • OLAP vs MapReduce
    • MapReduce代表抽象的物理执行模型,使用门槛较高
    • 与MapReduce Job相比,OLAP引擎常通过SQL形式为数据分析数据开发人员提供统一的逻辑描述语言,实际的物理执行由具体的引擎进行优化和转换
  • OLAP核心概念:维度+度量
  • 常见的OLAP引擎
    • 预计算引擎:Kylin,Druid
    • 批式处理引擎:Hive,Spark
    • 流式处理引擎:Flink
    • 交互式处理引擎:Presto,Clickhouse,Doris

1.3 Presto设计理念

  • 多租户任务的管理与调度
  • 多数据源联邦查询
  • 支持内存化计算
  • pipeline式数据处理

2.Presto基础概念

Presto架构图

Screen Shot 2022-07-28 at 8.59.14 PM.png

2.1 服务相关概念

  • coordinator:负责调度(管理节点)
    • 解析SQL语句
    • 生成执行计划
    • 分发执行任务给worker节点执行
  • worker:工作节点
    • 执行task处理数据
    • 与其他worker交互传输数据
    • 一个presto集群中存在一个coordinator节点和多个worker节点
    • 每个节点上存在一个worker服务进程
      • 数据处理
      • task执行
    • worker服务进程每隔一定时间向coordinator服务器发送心跳,接受调度
    • 当客户提交查询时,coordinator会从当前存活的worker列表中选出适合的worker节点执行task
    • worker在执行每个task时会进一步对当前task读入的每个split进行一系列操作和处理

2.2 数据源相关概念

  • connector:支持多数据源的方式,一个connector代表一个数据源 (适配多数据源的统一接口)
  • catalog:针对不同数据源connector和catalog一一对应,包含了schema和data source的映射关系 (源信息与实际数据的映射)

2.3 Query相关概念

  • query:基于SQL parser后获得的执行计划
  • stage:根据是否需要shuffle将query拆分成的不同subplan,每个subplan则是一个stage
  • fragment:基本等价stage,不同阶段的称呼
  • task:单个worker节点上最小的资源管理单元
    • 一个节点上一个stage只有一个task
    • 一个query可以有多个task
  • pipeline:stage按照localExchange切分为若干operator的集合,每个operator集合定义一个pipeline
  • driver:pipeline的可执行实体 (pipeline和driver类似程序和进程,是最小执行单元)通过火山迭代模型执行每一个operator
  • split:输入数据描述(数据实体是page)
    • 数量上和driver一一对应
    • 不仅代表实际数据源split也代表不同stage间传输的数据
  • operator:最小的物理算子

2.4 数据传输相关概念

  • exchange:表示不同stage间的数据传输,大多数意义下等价于shuffle
  • localExchange:stage内的rehash操作
    • 常用于提高并行处理数据的能力
    • task在presto中是最小的容器,而不是最小的执行单元
    • 默认是16
  • 如何衡量某个任务Stage的真实并行度:在不同pipeline下split(driver)的数目之和

2.5 核心组件架构介绍

  • 服务发现 discovery service:将coordinator和worker结合在一起的服务
    • (worker配置文件配置DS地址)
    • worker节点启动后向discovery server服务注册
    • coordinator从该server获得worker节点
  • Presto的通信方式
    • client与server:Http
    • coordinator与worker:http/Thrift
    • worker与worker间通信:http/Thrift
    • thrift具有更好的数据编码能力,Http1.1不支持头部信息压缩,Thrift有更好的数据压缩率
  • worker节点状态
    • ACTIVE:活跃
    • INACTIVE:不活跃
    • SHUTDOWN:节点准备结束工作,进入shutdown状态,coordinator不再给节点分配工作,节点完成工作后结束

3. Presto的重要机制

3.1 Presto用户多租户隔离

Presto通过resource group对不同的用户创建不同group从而实现不同租户、不同场景的资源管理

3.2 Presto Resource Group优缺点

  • 优点
    • 支持通配符形式:简单配置文件实现
    • 对不同租户不同提交场景下用户进行限制
  • 缺点
    • 存在滞后性
    • 只会对group中正在运行的SQL资源进行判断

3.3Presto物理计划生成

  • Antlr4解析生成AST
  • 转换为Logical Plan
  • 按照是否存在shuffle(exchange)切分为不同stage(fragment)

3.4Presto多租户任务调度

  • stage调度
    • AllAtOnceExecutionpolicy 同时调度
      • 延迟低 存在任务空跑
      • 典型应用为join查询
        • build端右表构建join的hashtable
        • probe端:左表数据进行探查,等待build完成
        • build端构建hashtable时probe在空跑
    • phased Execution policy
      • 不代表每个stage都分开调度
      • 可以分开处理,无需等待stage完成
      • 内存友好无需落盘
      • 有一定延迟、节省部分资源
  • task调度
    • 数量确定
      • source:根据数据meta决定分配多少节点
      • fixed:hash partition count确定如集群节点数量
      • sink:汇聚结果一台机器
      • scaled:无分区限制,可扩展,如write数据
      • coordinator_only:只需要coordinator参与
    • 选择什么节点
      • HARD_AFFINITY:计算、存储local模式,保障计算与存储在同一节点减少数据传输
      • SOFT_AFFINITY:基于某些特定算法,如一致性HASH函数;常用于缓存场景,保证相似的task调度到同一个worker
      • NO_PREFERENCE:随机选取,常用于普通的纯计算Task
  • split调度 QueryA大SQL先提交,QueryB小SQL后提交,是否插队?
    • FIFO:顺序执行,绝对公平
    • 优先级调度:快速响应
      • 按照固定时间片轮巡Split处理数据,处理1s再重新选择一个split执行
      • split之间存在优先级
      • multiLevelSplitQueue:五个优先级level理论上时间占比为16:8:4:2:1
      • 优势
        • 优先保证小query快速执行
        • 保障大query存在固定比例时间片,不会被完全饿死 (优先级很低也能有时间)

3.5 内存计算

3.5.1 pipeline化的数据处理

  • pipeline按照localExchange拆分
    • 更好的实现算子间并行
    • 语义上保证算子执行并行

3.5.2 back pressure mechanism

  • 控制split生成流程
  • 控制operator执行
  • targetConcurrency auto-scale-out
    • 定时检查如果outputbuffers使用率低于0.5(下游消费速度更快,需要提高生产数据),并发度+1
  • sink.max-buffer-size写入buffer大小控制
  • exchange.max-buffer-size读取buffer大小控制
  • 达到最大值时operator进入阻塞状态

3.6 多数据源联邦查询

  • 将各个数据源进行统一抽象,最后由presto server进行统一的物理执行
  • 局限性
    • 源数据管理与映射(每个connector管理一套源数据服务)
    • 谓词下推(不同SQL处理不同)
    • 数据源分片

4. Presto性能优化

4.1 常用的性能分析工具

  • Grafana:埋点、系统指标如CPU、内存网络等可视化界面,时序化的数据展示
  • 线上问题排查工具 Arthas:不重启服务可以监控
    • watch/trace
    • 需要自己猜出问题大体在哪一段
  • Flame Figure火焰图
    • 分析热点代码占用大量CPU从而导致服务性能下降情况
  • java指令
    • jstack查看java线程栈信息,排查死锁、异常线程
    • JMX(Java Management Extensions)为应用程序植入管理功能框架,做监控指标的统计收集
    • JMAP & GC日志等内存分析工具
  • Presto UI

三、实践分析例

  1. github.com/prestodb/pr…
  • data: tpcds 1T
  • SQL:count(*) 3-4s
  • 火焰图:可以看出某个方法占用大量CPU cycle
  • 改进:逐元素copy大量hashmap的rehash操作 -> 对底层数据直接clone
  • 优化:3-4s -> 1s
  1. SQL执行缓慢,某几个节点CPU负载特别高
  • 问题:正则表达式完全由用户输入,而与正则表达式匹配的数据不可控,结果就是单条记录匹配需要天级别;正则表达式不可中断,阻塞了split的优先级调度
  • 解决思路
    • 能否实现可中断的正则表达式
    • 其他类似问题处理方法
  1. 字节内部优化实践 - Multi Coordinator
  • 问题:coordinator单节点实现性能差
  • 优化:不可用时间减少,coordinator多活
  1. History Server
  • presto UI存储在内存中无法长时间保存
  • 持久化的数据存储
  1. support remote UDF
  • 统一UDF抽象 适配多引擎
  • 多租户内核与网络隔离
  1. raptorX多级缓存
  • 在中间多级进行缓存,实现性能提升
    • metastore cache by version
    • list file cache
    • fragment cache
    • alluxio cache

四、课程总结

  1. 难点
    • Presto的概念、原理
    • Presto的优化
  2. 个人总结:本堂课学习了Presto相关的概念和原理,以及后期的优化。我个人对于Presto没有基础,需要在课后结合实践例、源代码进行进一步的深入学习。

五、引用内容

【大数据专场 学习资料三】第四届字节跳动青训营