presto架构图
Presto采用经典的master-slave模型:
1.coordinator(matser)负责meta管理,woker管理,query的解析和调度,
2.Worker则负责计算和读写
3.discovery server,通常内嵌于coordinator节点中,也可以单独部署,用于节点心跳,在下文
中,默认discovery和coordinator共享一台机器。
在worker的配置中,可以选择配置:
1.discovrey的ip:port
2.一个http地址,内容是service inventory,包含discovery地址。
- 一个本地文件地址
{
"environment": "production",
"services": [
{
"id": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"type": "discovery",
"location": "/ffffffff-ffff-ffff-ffff-ffffffffffff",
"pool": "general",
"state": "RUNNING",
"properties": {
"http": "http://192.168.1.1:8080"
}
}
]
}
2和3的原理是基于service inventory, worker 会动态监听这个文件,如果有变化,load出最新的配置,指向最新的discovery节点。
在设计上,discovery和coordinator都是单节点。如果有多个coordinator同时存活,worker 会随机的向其中一个汇报进程和task状态,导致脑裂。调度query时有可能会发生死锁。
discovery和coordinator可用性设计。由于service inventory的使用,监控程序可以在发现discovery挂掉后,修改service inventory中的内容,指向备机的discovery。无缝的完成切换。coordiantor的配置必须要在进程启动时指定,同一个集群中无法存活多个coordinator。因此最好的办法是和discovery配置到一台机器。 secondary机器部署备用的discovery和coordinator。在平时,secondary机器是一个只包含一台机器的集群,在primary宕机时,worker的心跳瞬间切换到secondary。
数据模型
presto采取三层表结构:
- catalog 对应某一类数据源,例如hive的数据,或mysql的数据
- schema 对应mysql中的数据库
- table 对应mysql中的表
presto的存储单元包括:
- Page: 多行数据的集合,包含多个列的数据,内部仅提供逻辑行,实际以列式存储。
- Block:一列数据,根据不同类型的数据,通常采取不同的编码方式,了解这些编码方式,有助于自己的存储系统对接presto。
不同类型的block:
- array类型block,应用于固定宽度的类型,例如int,long,double。block由两部分组成
- boolean valueIsNull[]表示每一行是否有值。
- T values[] 每一行的具体值。
2. 可变宽度的block,应用于string类数据,由三部分信息组成
-
- Slice : 所有行的数据拼接起来的字符串。
- int offsets[] :每一行数据的起始便宜位置。每一行的长度等于下一行的起始便宜减去当前行的起始便宜。
- boolean valueIsNull[] 表示某一行是否有值。如果有某一行无值,那么这一行的便宜量等于上一行的偏移量。
3. 固定宽度的string类型的block,所有行的数据拼接成一长串Slice,每一行的长度固定。
4. 字典block:对于某些列,distinct值较少,适合使用字典保存。主要有两部分组成:
-
- 字典,可以是任意一种类型的block(甚至可以嵌套一个字典block),block中的每一行按照顺序排序编号。
- int ids[] 表示每一行数据对应的value在字典中的编号。在查找时,首先找到某一行的id,然后到字典中获取真实的值。
插件
了解了presto的数据模型,就可以给presto编写插件,来对接自己的存储系统。presto提供了一套connector接口,从自定义存储中读取元数据,以及列存储数据。先看connector的基本概念:
- ConnectorMetadata: 管理表的元数据,表的元数据,partition等信息。在处理请求时,需要获取元信息,以便确认读取的数据的位置。Presto会传入filter条件,以便减少读取的数据的范围。元信息可以从磁盘上读取,也可以缓存在内存中。
- ConnectorSplit: 一个IO Task处理的数据的集合,是调度的单元。一个split可以对应一个partition,或多个partition。
- SplitManager : 根据表的meta,构造split。
- SlsPageSource : 根据split的信息以及要读取的列信息,从磁盘上读取0个或多个page,供计算引擎计算。
插件能够帮助开发者添加这些功能:
- 对接自己的存储系统。
- 添加自定义数据类型。
- 添加自定义处理函数。
- 自定义权限控制。
- 自定义资源控制。
- 添加query事件处理逻辑。
Presto提供了一个简单的connector : local file connector ,可用于参考如何实现自己的connector。不过local file connector中使用的遍历数据的单元是cursor,即一行数据,而不是一个page。 hive 的connector中实现了三种类型,parquet connector, orc connector, rc file connector。