目前有需求要实现对比不同数据库下两张表的数据量或者数值是否一致,而且希望在不进行数据搬迁落地的条件下完成。有许多数据虚拟化工具可以支撑,Facebook推出的开源工具Presto就是其中之一。网上找了一大推资料,看完有点懵,还是得要实操一把才有体会。顺道记录下丐版Presto集群的搭建过程,不然隔段时间又忘个干净。
Presto基本概念
还是要先说明下Presto是啥,都有哪些组成元素,这里简单翻译下官网的介绍。
作为支持从多个数据源查询数据的分布式SQL查询引擎,presto包含两种类型的server: coordinator和worker。一个完整的presto必须包含一个coordinator节点和一个或多个worker节点,允许一个节点即用作coordinator又用作worker。
- Coordinator负责解析查询SQL、制定执行计划以及管理各个worker节点,它往前连接了提交查询SQL的presto客户端,往后连接了负责执行查询任务的worker。Coordinator中discovery server负责跟踪每个worker的有效性,每个worker启动后都会向discovery server注册,而Coordinator给worker下发查询任务时需要根据discovery server管理的每个节点信息找到worker的位置。
- Worker负责执行coordinator下发的查询任务,从数据连接器获取数据并进行数据处理,数据处理时各个worker可能会交换数据。
presto中数据源的定义涉及connector, catalog, schema三个概念。
-
connector可以理解为类似于连接数据库的驱动,目前提供了常见的各种数据源驱动,包括:Oracle, MySQL, PostgreSQL, MongoDB等。
-
catalog是presto管理数据源的一种形式,1个数据源就是1个catalog配置文件,包含使用的connector、数据源连接信息(url/user/password),以及schema(非必填项)等信息。
-
schema等价于数据库实例,对MySQL来说,schema等价于MySQL的1个database。presto中完整定位1张表的方式是catalog.schema.table。
presto客户端用于向coordinator提交查询并接收查询结果,目前多种客户端可使用,包括命令行接口(CLI)、JDBC驱动、Python客户端、第三方的Web应用等。
presto中各个server节点间以REST API的方式进行通信。
集群配置说明
-
机器1(IP:192.168.18.128)是安装有Ubuntu 16.04系统的虚拟机,作为Presto的Coordinator使用。同时安装有提交查询给Coordinator的Presto命令行客户端(Presto CLI),以及安装了MySQL Server(后面用demo指代机器1的MySQL Server,这个Server建有
blog_master_db和blog_worker_db两个数据库)。 -
机器2(IP:192.168.18.129)也是安装有Ubuntu 16.04系统的虚拟机,作为Presto的Worker使用。
-
机器3(IP:192.168.3.2)是安装有Win10系统的物理机,机器上也安装了MySQL(后面用winremote指代机器1的MySQL Server,这个Server建有
blog_win_db数据库)。
话不多说,直接开干!
测试数据准备
为简单验证是否实现了跨库查询,在三个库上都建同样的表,只是写入了不同的数据。
表结构如下:
CREATE TABLE book (
book_id INT,
book_name VARCHAR ( 300 ),
book_desc VARCHAR ( 1000 ),
author VARCHAR ( 50 ),
created_date DATETIME,
publish_date DATETIME );
机器1 MySQL Server中blog_master_db中book的数据如下:
INSERT INTO book
( book_id, book_name, book_desc, author, publish_date )
VALUES
( 1, "AAA", "book in demo.blog_master_db", "BKY", "2018-09-10 06:00:00" );
机器1 MySQL Server中blog_worker_db中book的数据如下:
INSERT INTO book
( book_id, book_name, book_desc, author, publish_date )
VALUES
( 2, "BBB", "book in demo.blog_worker_db", "BTW", "2019-03-01 13:00:00" );
机器3 MySQL Server中blog_win_db中book的数据如下:
INSERT INTO book
( book_id, book_name, book_desc, author, publish_date )
VALUES
( 3, "CCC", "book in winremote.blog_win_db", "GOT", "2020-10-22 08:00:00" );
依赖项安装
presto的安装依赖于JDK(JDK 8及以上版本),所以presto中Coordinator和Worker所在机器上必须安装JDK。
在ubuntu下安装jdk比较简单,这里以安装open-jdk 8为例说明,在命令行依次执行以下命令即可。
# 安装jre
sudo apt install openjdk-8-jre-headless
# 安装jdk
sudo apt install openjdk-8-jdk-headless
# 验证安装是否成功
java --version
javac --version
presto server安装配置
presto server包括coordinator和worker。两者的安装使用同一个安装包,只是在部分配置上有区别。
安装包下载
官网下载的最新版本presto-server-0.242.tar.gz,下载后解压即可,解压后的文件夹也就是presto的安装路径。
官方推荐在安装路径外的新建data文件夹用于存储日志,也便于日后presto升级日志文件不用改动。
presto的安装路径:/town/presto-server-0.242/
data文件路径:/var/presto/data/
presto配置
在两个机器的presto安装文件夹下都新建etc文件夹,该文件夹用于存储以下配置信息
- Node Properties: environmental configuration specific to each node
- JVM Config: command line options for the Java Virtual Machine
- Config Properties: configuration for the Presto server
- Catalog Properties: configuration for Connectors (data sources)
节点属性
配置文件名固定etc/node.properties,用于存储presto集群下每个节点的信息。两台机器的id必须不同。
# 机器1: Coordinator
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-ffffffffffff
node.data-dir=/var/presto/data
# 机器2: Worker
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffffk
node.data-dir=/var/presto/data
node.environment: presto集群下每个节点的环境名称必须一致。node.id: 节点id,集群下每个节点的id必须唯一,形式不固定。node.data-dir: 用于存在日志等信息的文件绝对路径,使用安装包下载一节新建的文件夹。
JVM配置
配置文件名固定etc/jvm.config,存储加载Java虚拟机的配置信息。两台机器的配置可以相同,典型配置如下:
-server
-Xmx16G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError
配置属性
配置文件名固定etc/config.properties,存储presto节点(服务器)的配置信息。每个presto节点(服务器)都可以用作Coordinator或者Worker,也可以即作Coordinator也作Worker。节点作不同的用途,配置信息也不同,机器1 Coordinator的配置如下:
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8080
query.max-memory=5GB
query.max-memory-per-node=1GB
query.max-total-memory-per-node=2GB
discovery-server.enabled=true
discovery.uri=http://192.168.18.128:8080
机器2 Worker的配置如下:
coordinator=false
http-server.http.port=8080
query.max-memory=50GB
query.max-memory-per-node=1GB
query.max-total-memory-per-node=2GB
discovery.uri=http://192.168.18.128:8080
部分配置信息的解释:
coordinator: 设置当前presto节点是否用作coordinator.node-scheduler.include-coordinator: Allow scheduling work on the coordinator. 我理解是否允许当前节点兼任worker.http-server.http.port: 设置presto的通信端口.discovery-server.enabled: 是否启用Presto coordinator内嵌的Discovery service,两者共享通信端口.discovery.uri: Discovery server的URI,形式为IP:端口号。
日志配置
可选的日志级别配置,文件名固定为etc/log.properties,两台机器的配置可以相同,典型配置信息如下:
com.facebook.presto=INFO
Catalog配置
Presto通过连接器connectors连接数据源以获取数据,而连接器是挂载在目录下。也就是说在presto中1个目录就代表1个数据源。Coordinator和Worker的catalog配置应该保持一致(文件数量和文件内容),否则容易出错。
要使用presto访问某个 MySQL Server,在etc/catalog文件夹下创建catalog属性文件,属性文件名称不固定,可以自由命名。
比如用demo指代机器1的MySQL Server,可以创建/etc/catalog/demo.properties文件,其配置信息如下:
# 连接器类型, 如oracle, mysql, hive等.
connector.name=mysql
# 连接信息. 不同数据源类型要配置的连接信息不同.
# 以IP的形式连接mysql server时要确认mysql server允许远程连接,否则会报连接失败的错误
connection-url=jdbc:mysql://192.168.18.128:3306
connection-user=root
connection-password=123456
为了能访问机器3的MySQL Server,再创建/etc/catalog/winremote.properties,其配置信息如下:
connector.name=mysql
connection-url=jdbc:mysql://192.168.3.2:3306
connection-user=root
connection-password=123456
presto定位1个表的完整信息格式:catalog配置文件名.database.schema。比如访问机器1blog_worker_db数据库下book表,需要以demo.blog_worker_db.book形式访问。
**注:**以IP的形式连接mysql server时要确认mysql server允许远程连接,否则会报连接失败的错误。参考资料
启动presto
有两种方式启动presto。
# 后台启动
sudo ./bin/launcher start
# 前台启动. 命令行窗口可以看到启动的过程日志
sudo ./bin/launcher run
看到如下信息说明启动成功:
启动成功后可以在node.data-dir=/var/presto/data对应的文件夹下找到启动日志文件。
presto CLI安装和启用
presto CLI用于向coordinator提交1个查询。
下载presto-cli-0.242-executable.jar, 重命名为 presto并通过 chmod +x将其设置为可执行文件。
启动命令:
# 参数server: coordinator的URI
# 参数catalog: 设置查询SQL默认用数据源配置文件. 可不加
# 参数schema: 设置查询SQL默认查哪个database. 可不加
sudo ./presto --server 192.168.18.128:8080 --catalog demo --schema blog_master_db
执行跨库查询:
select * from demo.blog_master_db.book
union all
select * from demo.blog_worker_db.book
union all
select * from winremote.blog_win_db.book;
执行结果:可以看到1个SQL语句中将两个Server中三个数据库的数据都查出来了。
问题记录
- catalog配置中worker两个mysql server的配置文件都有,coordinator缺少机器3的配置文件winremot.properites,导致报错:Catalog xxx does not exist
- catalog配置中coordinator两个mysql server的配置文件都有,worker缺少机器3的配置文件winremot.properites,导致报错:No nodes available to run query
参考资料: