Presto的学习笔记

presto学习笔记

是什么?可以做什么?

  1. Presto是一个开源的分布式SQL查询引擎,适用于交互式分析查询,数据量支持GB到PB字节。
  2. Presto支持在线数据查询,包括Hive, Cassandra, 关系数据库以及专有数据存储。 一条Presto查询可以将多个数据源的数据进行合并,可以跨越整个组织进行分析。
  3. 作为Hive和Pig(Hive和Pig都是通过MapReduce的管道流来完成HDFS数据的查询)的替代者,Presto不仅可以访问HDFS,也可以操作不同的数据源,包括:RDBMS和其他的数据源(例如:Cassandra)。
  4. 查询后的数据自动分页,这个很不错.

源码编译

下载presto源码包地址:https://github.com/prestodb/presto/releases

安装文档地址(注意这个中文文档的版本是0.100):

注意:

  • jdk得是1.8以上
  • 我是用的presto0.161
1
2
3
4
tar -xzvf presto-0.161.tar.gz
# 编译
./mvnw clean install -DskipTests

在pom.xml文件中加入阿里云的仓库,加速下载依赖

1
2
3
4
5
6
7
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</repository>
</repositories>

编译报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ERROR] Failed to execute goal pl.project13.maven:git-commit-id-plugin:2.1.13:revision (default) on project presto-spi: .git directory could not be found! Please specify a valid [dotGitDirectory] in your pom.xml -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal pl.project13.maven:git-commit-id-plugin:2.1.13:revision (default) on project presto-spi: .git directory could not be found! Please specify a valid [dotGitDirectory] in your pom.xml
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:185)
at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call(MultiThreadedBuilder.java:181)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.maven.plugin.MojoExecutionException: .git directory could not be found! Please specify a valid [dotGitDirectory] in your pom.xml
at pl.project13.maven.git.GitCommitIdMojo.throwWhenRequiredDirectoryNotFound(GitCommitIdMojo.java:432)
at pl.project13.maven.git.GitCommitIdMojo.execute(GitCommitIdMojo.java:337)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)

解决办法

1
2
3
4
5
6
7
8
9
10
11
12
pom文件中加入这个插件
<pluginManagement>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>

部署包安装

下载地址

下载presto-cli(记住要下载的presto-cli-xxxx-executable.jar):https://repo1.maven.org/maven2/com/facebook/presto/presto-cli

下载部署包的地址:https://repo1.maven.org/maven2/com/facebook/presto/presto-server/

服务器说明

机器共有三台U006,U007,U008

  • coordinator
    • U007
  • discovery
    • U007
  • worker
    • U006
    • U008

coordinator和worker的其他配置都是一样的,除了config.properties不一样.具体哪里不一样,看下面的配置说明.

配置说明

以下配置均是presto0.161版本的.如果你的版本不一样,启动后如果报错了,那么可能是配置文件里面的参数和版本对应不上,请找相应版本的配置.

在presto-server-0.161目录下新建etc目录,下面的配置文件均在此etc目录下

1
2
3
4
5
6
7
8
9
[druid@U007 presto-server-0.161]$ tree etc/
etc/
├── catalog
│   ├── hive.properties
│   └── jmx.properties
├── config.properties
├── jvm.config
├── log.properties
└── node.properties

jvm.config

包含一系列在启动JVM的时候需要使用的命令行选项。这份配置文件的格式是:一系列的选项,每行配置一个单独的选项。由于这些选项不在shell命令中使用。 因此即使将每个选项通过空格或者其他的分隔符分开,java程序也不会将这些选项分开,而是作为一个命令行选项处理,信息如下:

VM 系统属性 HADOOP_USER_NAME 来指定用户名

1
2
3
4
5
6
7
8
9
-server
-Xmx16G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:OnOutOfMemoryError=kill -9 %p
-DHADOOP_USER_NAME=hdfs

log.properties

这个配置文件中允许你根据不同的日志结构设置不同的日志级别。每个logger都有一个名字(通常是使用logger的类的全标示类名). Loggers通过名字中的“.“来表示层级和集成关系,信息如下:

1
com.facebook.presto=INFO
  • 配置日志等级,类似于log4j。四个等级:DEBUG,INFO,WARN,ERROR

node.properties

包含针对于每个节点的特定的配置信息。 一个节点就是在一台机器上安装的Presto实例,etc/node.properties配置文件至少包含如下配置信息

1
2
3
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-ffffffffffff # 每个节点的node.id一定要不一样
node.data-dir=/home/druid/data/presto # 计算临时存储目录,presto得有读写权限

说明:

  1. node.environment: 集群名称, 所有在同一个集群中的Presto节点必须拥有相同的集群名称.
  2. node.id: 每个Presto节点的唯一标示。每个节点的node.id都必须是唯一的。在Presto进行重启或者升级过程中每个节点的node.id必须保持不变。如果在一个节点上安装多个Presto实例(例如:在同一台机器上安装多个Presto节点),那么每个Presto节点必须拥有唯一的node.id.
  3. node.data-dir: 数据存储目录的位置(操作系统上的路径), Presto将会把日期和数据存储在这个目录下

config.properties

coordinator 主节点配置

1
2
3
4
5
6
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8585
query.max-memory=10GB
discovery-server.enabled=true
discovery.uri=http://U007:8585

说明:

  1. coordinator表示此节点是否作为一个coordinator。每个节点可以是一个worker,也可以同时是一个coordinator,但作为性能考虑,一般大型机群最好将两者分开。
  1. 若coordinator设置成true,则此节点成为一个coordinator。
  2. 若node-scheduler.include-coordinator设置成true,则成为一个worker,两者可以同时设置成true,此节点拥有两种身份。在一个节点上的Presto server即作为coordinator又作为worke将会降低查询性能。因为如果一个服务器作为worker使用,那么大部分的资源都会被worker占用,那么就不会有足够的资源进行关键任务调度、管理和监控查询执行.
  3. http-server.http.port:指定HTTP server的端口。Presto 使用 HTTP进行内部和外部的所有通讯.
  4. query.max-memory=10GB:一个单独的任务使用的最大内存 (一个查询计划的某个执行部分会在一个特定的节点上执行)。 这个配置参数限制的GROUP BY语句中的Group的数目、JOIN关联中的右关联表的大小、ORDER BY语句中的行数和一个窗口函数中处理的行数。 该参数应该根据并发查询的数量和查询的复杂度进行调整。如果该参数设置的太低,很多查询将不能执行;但是如果设置的太高将会导致JVM把内存耗光.
  5. discovery-server.enabled:Presto 通过Discovery 服务来找到集群中所有的节点。为了能够找到集群中所有的节点,每一个Presto实例都会在启动的时候将自己注册到discovery服务。Presto为了简化部署,并且也不想再增加一个新的服务进程,Presto coordinator 可以运行一个内嵌在coordinator 里面的Discovery 服务。这个内嵌的Discovery 服务和Presto共享HTTP server并且使用同样的端口.
  6. discovery.uri:Discovery server的URI。由于启用了Presto coordinator内嵌的Discovery 服务,因此这个uri就是Presto coordinator的uri。注意:这个URI一定不能以“/“结尾

worker节点配置

1
2
3
4
5
6
coordinator=false
node-scheduler.include-coordinator=true
http-server.http.port=8585
query.max-memory=5GB
query.max-memory-per-node=1GB
discovery.uri=http://U007:8585

catalog

hive.properties(hive连接器的配置)

连接hive

1
2
3
4
5
6
7
8
# 在etc/catalog目录下,新建hive.properties文件,配置上hive的一些信息
[druid@U006 catalog]$ pwd
/home/druid/presto-server-0.161/etc/catalog
[druid@U006 catalog]$ more hive.properties
connector.name=hive-cdh5
hive.metastore.uri=thrift://U006:9083
hive.config.resources=/etc/hadoop/conf.cloudera.yarn/core-site.xml,/etc/hadoop/conf.clouder
a.yarn/hdfs-site.xml

保证每个节点presto对core-site.xml,hdfs-site.xml两个文件有读权限

启动停止presto

单节点启动

在每个节点依次执行启动脚本

1
2
3
4
5
6
7
8
9
10
# 后台运行
bin/launcher start
# 前台运行
bin/launcher run
# 重启presto
bin/launcher restart
# 停止presto
bin/launcher stop

批量启动停止脚本

1
ssh -t ${i} -C '. /usr/local/bin/env.sh && /usr/local/presto-server-0.161/bin/launcher restart'

监控presto

启动完成后,在浏览器输入:

1
http://U007:8585

这个地址也就是coordinator的discovery.uri

cli连接

连接器注意说明

  • 连接器的配置文件必须是以.properties后缀结尾的,前面的名字就是连接器的catalog名字
  • 每次新加连接器配置文件后,都需要在presto的所有机器上加上相同的配置文件,然后重启
  • 要下载对应版本的cli连接器,不然可能不好使.名字类似presto-cli-0.161-executable.jar

hive连接器

配置说明(hive连接器的配置在说catalog的时候已经配置好了,你可以回头看看):

  • connector.name=hive-cdh5(根据你的hive版本来选择)
  • hive.metastore.uri=thrift://U006:9083(hive的metastore地址)
  • hive.config.resources=/etc/hadoop/conf.cloudera.yarn/core-(配置文件的地址)
1
2
3
4
5
chmod +x presto-cli-0.161-executable.jar
./presto-cli-0.161-executable.jar --server U007:8585 --catalog hive --schema default
或者 mv presto-cli-0.161-executable.jar presto都可以
./presto --server U007:8585 --catalog hive --schema default
执行该语句后在 presto shell 中执行: show tables 查看 hive 中的 default 库下的表。如果出现对应的表,表安装验证成功

jmx连接器

  • JMX提供了有关JVM中运行的Java虚拟机和软件的信息
  • jmx连接器用于在presto服务器中查询JMX信息

在etc/catalog目录下新建jmx.properties

1
connector.name=jmx

现在连接presto cli以启用JMX插件

1
2
3
4
5
6
7
8
9
10
11
12
[druid@U007 presto-server-0.161]$ ./presto --server U007:8585 --catalog jmx --schema jmx
presto:jmx> show schemas from jmx;
Schema
--------------------
current
history
information_schema
(3 rows)
Query 20171012_063601_00020_yuhat, FINISHED, 2 nodes
Splits: 2 total, 2 done (100.00%)
0:00 [3 rows, 47B] [39 rows/s, 614B/s]

MySQL连接器

vim etc/catalog/mysql.properties

1
2
3
4
connector.name=mysql
connection-url=jdbc:mysql://10.10.25.13:3306
connection-user=root
connection-password=wankatest***

schema 后面跟的mysql的数据库,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[druid@U007 presto-server-0.161]$ ./presto --server U007:8585 --catalog mysql --schema test
presto:test> show tables;
Query 20171012_071844_00002_iz4q8 failed: No worker nodes available
presto:test> show tables;
Table
--------------------------
dmp_summary_daily_report
tb_dmp_stat_appboot
tb_dmp_stat_asdk_detail
tb_dmp_stat_device
tb_leidian1
tb_leidian2
(6 rows)
Query 20171012_072024_00003_iz4q8, FINISHED, 2 nodes
Splits: 2 total, 2 done (100.00%)
0:01 [6 rows, 190B] [6 rows/s, 196B/s]

kafka连接器

暂时没这个需求,未测试.

系统连接器

  • 系统连接器提供了正在运行的Presto集群的一些信息和指标
  • 那么这个就可以通过标准sql很方便的查询这些信息
  • 系统连接器不需要配置,已经内置了.我们可以很方便的访问名为system的catalog
1
2
3
4
5
6
7
8
9
10
11
12
13
[druid@U007 presto-server-0.161]$ ./presto --server U007:8585 --catalog system
presto> show schemas from system;
Schema
--------------------
information_schema
jdbc
metadata
runtime
(4 rows)
Query 20171012_082437_00019_iz4q8, FINISHED, 2 nodes
Splits: 2 total, 2 done (100.00%)
0:00 [4 rows, 57B] [70 rows/s, 997B/s]

查询有多少个节点

1
2
3
4
5
6
7
8
9
10
11
presto> SELECT * FROM system.runtime.nodes;
node_id | http_uri | node_version | coord
-------------------------------------------+-------------------------+--------------+------
ffffffff-ffff-ffff-ffff-ffffffffffff-u006 | http://10.10.25.13:8585 | 0.161 | false
ffffffff-ffff-ffff-ffff-ffffffffffff-u007 | http://10.10.25.14:8585 | 0.161 | true
ffffffff-ffff-ffff-ffff-ffffffffffff-u008 | http://10.10.25.15:8585 | 0.161 | false
(3 rows)
Query 20171012_082952_00023_iz4q8, FINISHED, 2 nodes
Splits: 2 total, 2 done (100.00%)
4:08 [3 rows, 228B] [0 rows/s, 0B/s]

JDBC接口

依赖下载安装

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.facebook.presto/presto-jdbc -->
<dependency>
<groupId>com.facebook.presto</groupId>
<artifactId>presto-jdbc</artifactId>
<version>0.161</version>
</dependency>

Presto支持的URL格式如下:

1
2
3
jdbc:presto://host:port
jdbc:presto://host:port/catalog
jdbc:presto://host:port/catalog/schema

例如,可以使用下面的URL来连接运行在U007服务器8585端口上的Presto的mysql catalog中的test schema:

1
jdbc:presto://10.10.25.14:8585/mysql/test

这个url就是来连接hive catalog中的default schema

1
jdbc:presto://10.10.25.14:8585/hive/default

###Java代码

读取mysql下的test库下的所有表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PrestoJdbcDemo {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("com.facebook.presto.jdbc.PrestoDriver");
Connection connection = DriverManager
.getConnection("jdbc:presto://10.10.25.14:8585/mysql/test", "root", "wankatest***");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("show tables");
while (rs.next()) {
System.out.println(rs.getString(1));
}
rs.close();
connection.close();
}
}

读取hive下的default库下的所有表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PrestoJdbcDemo {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Class.forName("com.facebook.presto.jdbc.PrestoDriver");
Connection connection = DriverManager
.getConnection("jdbc:presto://10.10.25.14:8585/hive/default","root",null);
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("show tables");
while (rs.next()) {
System.out.println(rs.getString(1));
}
rs.close();
connection.close();
}
}

不同数据源之间的join

presto的一个特性就是其支持在不同的数据源之间进行join

当连接presto的客户端的时候,也可以不指定连接器

不同的数据源就用catalog名称指定,然后加上库名表明即可.

1
2
./presto --server U007:8585
show tables from mysql.dsp_test;

presto提供的函数和运算符

参考文档:http://prestodb-china.com/docs/current/functions.html

看日志

日志路径

node.properties中配置了node.data-dir=/home/druid/data/presto

1
2
3
4
5
6
7
8
9
10
11
12
13
[druid@U007 presto]$ tree
.
├── etc -> /home/druid/presto-server-0.161/etc
├── plugin -> /home/druid/presto-server-0.161/plugin
└── var
├── log
│   ├── http-request.log
│   ├── launcher.log
│   └── server.log
└── run
└── launcher.pid
5 directories, 4 files

出现错误后,我们主要关注var/log目录下的日志.

当服务有问题的时候,看server.log找到报错原因,从而解决问题.

常见错误

连接不上连接器

类似这样的错误

1
2
No factory for connector mysql
No factory for connector hive

如果服务报相关这样的错误,那么就需要关注各个连接器的配置文件是否写对了.各个连接器的配置文件是否在每个presto服务器上都部署了.

Presto的实现原理

Presto架构

  • Presto的架构
  • Presto执行原理

简单来说:

  1. cli客户端把查询需求发送给Coordinator节点.Coordinator节点负责解析sql语句,生成执行计划,分发执行任务给worer节点执行.所以worker节点负责实际执行查询任务.
  2. worker节点启动后向discovery server服务注册,因此coordinator就可以从discovery server获得可以正常工作的worker节点.

深入来说:

  1. 参考网上相关blog.
  2. 买书.
  3. 看源码!

参考文档

Donate comment here