Presto的学习笔记

2017/10/11 posted in  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
tar -xzvf presto-0.161.tar.gz

# 编译
./mvnw clean install -DskipTests

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

<repositories>
    <repository>
        <id>nexus-aliyun</id>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </repository>
</repositories>

编译报错

[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)

解决办法

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目录下

[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 来指定用户名

-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通过名字中的“.“来表示层级和集成关系,信息如下:

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

node.properties

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

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 主节点配置

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,但作为性能考虑,一般大型机群最好将两者分开。

  2. 若coordinator设置成true,则此节点成为一个coordinator。

  3. 若node-scheduler.include-coordinator设置成true,则成为一个worker,两者可以同时设置成true,此节点拥有两种身份。在一个节点上的Presto server即作为coordinator又作为worke将会降低查询性能。因为如果一个服务器作为worker使用,那么大部分的资源都会被worker占用,那么就不会有足够的资源进行关键任务调度、管理和监控查询执行.

  4. http-server.http.port:指定HTTP server的端口。Presto 使用 HTTP进行内部和外部的所有通讯.

  5. query.max-memory=10GB:一个单独的任务使用的最大内存 (一个查询计划的某个执行部分会在一个特定的节点上执行)。 这个配置参数限制的GROUP BY语句中的Group的数目、JOIN关联中的右关联表的大小、ORDER BY语句中的行数和一个窗口函数中处理的行数。 该参数应该根据并发查询的数量和查询的复杂度进行调整。如果该参数设置的太低,很多查询将不能执行;但是如果设置的太高将会导致JVM把内存耗光.

  6. discovery-server.enabled:Presto 通过Discovery 服务来找到集群中所有的节点。为了能够找到集群中所有的节点,每一个Presto实例都会在启动的时候将自己注册到discovery服务。Presto为了简化部署,并且也不想再增加一个新的服务进程,Presto coordinator 可以运行一个内嵌在coordinator 里面的Discovery 服务。这个内嵌的Discovery 服务和Presto共享HTTP server并且使用同样的端口.

  7. discovery.uri:Discovery server的URI。由于启用了Presto coordinator内嵌的Discovery 服务,因此这个uri就是Presto coordinator的uri。注意:这个URI一定不能以“/“结尾

worker节点配置

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

# 在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

单节点启动

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

# 后台运行
bin/launcher start
# 前台运行
bin/launcher run

# 重启presto
bin/launcher restart

# 停止presto
bin/launcher stop

批量启动停止脚本

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

监控presto

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

http://U007:8585

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

cli连接

连接器注意说明

  • cli下载地址(找到自己的版本下载):https://repo1.maven.org/maven2/com/facebook/presto/presto-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-(配置文件的地址)
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

connector.name=jmx

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

[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

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

schema 后面跟的mysql的数据库,

[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
[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]

查询有多少个节点

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接口

依赖下载安装

<!-- 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格式如下:

jdbc:presto://host:port
jdbc:presto://host:port/catalog
jdbc:presto://host:port/catalog/schema

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

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

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

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

Java代码

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

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库下的所有表

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名称指定,然后加上库名表明即可.

./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

[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找到报错原因,从而解决问题.

常见错误

连接不上连接器

类似这样的错误

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. 看源码!

参考文档