• 沒有找到結果。

编译并运行程序

9 ClickHouse 开发指南(安全模式)

9.1 概述

9.1.1 ClickHouse 简介

ClickHouse 简介

ClickHouse是面向联机分析处理的列式数据库,支持SQL查询,且查询性能好,特别 是基于大宽表的聚合分析查询性能非常优异,比其他分析型数据库速度快一个数量 级。

ClickHouse的设计优点:

● 数据压缩比高

● 多核并行计算

● 向量化计算引擎

● 支持嵌套数据结构

● 支持稀疏索引

● 支持数据Insert和Update ClickHouse的应用场景:

● 实时数仓场景

使用流式计算引擎(如Flink)把实时数据写入ClickHouse,借助ClickHouse的优 异查询性能,在亚秒级内响应多维度、多模式的实时查询分析请求。

● 离线查询场景

把规模庞大的业务数据导入到ClickHouse,构造数亿至数百亿记录规模、数百以 上的维度的大宽表,随时进行个性化统计和持续探索式查询分析,辅助商业决 策,具有非常好的查询体验。

应用开发指南 9 ClickHouse 开发指南(安全模式)

ClickHouse 开发接口简介

ClickHouse由C++语言开发,定位为DBMS,支持HTTP和Native TCP两种网络接口协 议,支持JDBC、ODBC等多种驱动方式,推荐使用社区版本的clickhouse-jdbc来进行 应用程序开发。

9.1.2 常用概念

基本概念

cluster

cluster(集群)在ClickHouse里是一种逻辑的概念,它可以由用户根据需要自由 的定义,和我们通常理解的集群有一定的差异。多个ClickHouse节点之间是一种 松耦合的关系,各自独立存在。

shards

shard(分片)是对cluster的横向切分,1个cluster可以由多个shard组成。

replicas

replica(副本),1个shard可以有多个replica组成。

partition

partition(分区),针对的是本地replica而言的,可以理解为是一种纵向切分。

MergeTree

ClickHouse拥有非常庞大的表引擎体系,MergeTree作为家族系统最基础的表引 擎,提供了数据分区、一级索引和二级索引等功能。在创建表的时候需要指定表 引擎,不同的表引擎会决定一张数据表的最终“性格”,比如数据表拥有何种特 性、数据以何种形式被存储以及如何被加载。

9.1.3 开发流程

开发流程中各阶段的说明如图1 ClickHouse应用程序开发流程和表1 ClickHouse应用开 发的流程说明 所示。

应用开发指南 9 ClickHouse 开发指南(安全模式)

9-1 ClickHouse 应用程序开发流程

9-1 ClickHouse 应用开发的流程说明

阶段 说明 参考文档

了解基本概 念

在开始开发应用前,需要了解

ClickHouse的基本概念。 基本概念 准备开发和

运行环境 ClickHouse的应用程序支持多种 语言开发,主要为Java语言,推 荐使用IntelliJ IDEA工具,请根 据指导完成开发环境配置。

准备开发和运行环境

根据场景开 发工程

提供样例工程,帮助用户快速了 解ClickHouse各部件的编程接 口。

配置并导入样例工程

运行程序及 查询结果

用户可以直接通过运行结果查看

应用程序运行情况。 在Windows下调测程序

在Linux下调测程序

9.2 环境准备

应用开发指南 9 ClickHouse 开发指南(安全模式)

9.2.1 准备开发和运行环境

准备开发环境

在进行应用开发时,要准备的开发和运行环境如表9-2所示。

9-2 开发环境

准备项 说明

操作系统 ● 开发环境:Windows系统,支持Windows7以上版 本。

● X86客户端:Oracle JDK:支持1.8版本;IBM JDK:支持1.8.5.11版本。

● TaiShan客户端:OpenJDK:支持1.8.0_272版本。

说明基于安全考虑,服务端只支持TLS V1.2及以上的加密协议。

IBM JDK默认只支持TLS V1.0,若使用IBM JDK,请配置启动 参数“com.ibm.jsse2.overrideDefaultTLS”为“true”,设

安装和配置IntelliJ IDEA 开发环境的基本配置,建议使用2019.1或其他兼容版 本。

说明

● 若使用IBM JDK,请确保IntelliJ IDEA中的JDK配置为IBM JDK。

● 若使用Oracle JDK,请确保IntelliJ IDEA中的JDK配置为 Oracle JDK。

● 若使用Open JDK,请确保IntelliJ IDEA中的JDK配置为 Open JDK。

● 不同的IntelliJ IDEA不要使用相同的workspace和相同路径 下的示例工程。

准备项 说明

7-zip 用于解压“*.zip”和“*.rar”文件,支持7-Zip 16.04版 本。

a. 登录FusionInsight Manager页面,选择“集群 > 概览 > 更多 > 下载客户

端”,“选择客户端类型”设置为“仅配置文件”,根据待安装客户端节点

9.2.2 配置并导入样例工程

背景信息

获取ClickHouse开发样例工程,将工程导入到IntelliJ IDEA开始样例学习。

前提条件

确保本地PC的时间与集群的时间差要小于5分钟,若无法确定,请联系系统管理员。集 群的时间可通过FusionInsight Manager页面右下角查看。

操作场景

ClickHouse针对多个场景提供样例工程,帮助客户快速学习ClickHouse工程。

操作步骤

步骤1 参考通过开源镜像站获取样例工程,获取样例代码解压目录中“src”目录下的样例工 程文件夹“clickhouse-examples”以及Maven相关配置。

步骤2 在应用开发环境中,导入样例工程到IntelliJ IDEA开发环境。

1. 在IDEA界面选择“File > New > Project from Existing Sources”。

2. 在显示的“Select File or Directory to Import”对话框中,选择“clickhouse-examples”文件夹中的“pom.xml”文件,单击“OK”。

3. 确认后续配置,单击“Next”,如无特殊需求,相关配置使用默认值即可。

4. 选择推荐的JDK版本,单击“Finish”完成样例工程导入。

步骤3 工程导入完成后,修改样例工程的“conf”目录下的“clickhouse-example.properties”文件,根据实际环境信息修改相关参数。

loadBalancerIPList=

sslUsed=false

loadBalancerHttpPort=21425 loadBalancerHttpsPort=21426

CLICKHOUSE_SECURITY_ENABLED=true user=

password=

clusterName=default_cluster databaseName=testdb tableName=testtb batchRows=10000 batchNum=10

应用开发指南 9 ClickHouse 开发指南(安全模式)

9-3 配置说明表

配置名称 默认值 含义

loadBalancerIPLis

t - 必填参数,配置为LoadBalance的IP列表。

登录Manager,选择“集群 > 服务 > ClickHouse

> 实例”,查看所有ClickHouseBalancer实例对应 的业务IP地址。

多个IP地址使用逗号分割,例如配置为

“10.10.10.100,10.10.10.101”。

sslUsed false 是否启用ssl加密,安全模式集群建议配置为

“true”。

loadBalancerHttp

Port 21425 LoadBalance的HTTP端口。

登录FusionInsight Manager,选择“集群 > 服务

> ClickHouse > 实例”,单击对应的

ClickHouseBalancer实例,选择“实例配置 > 全 部配置”,搜索“lb_http_port”并获取其参数 值,默认为21425。

loadBalancerHttp

sPort 21426 LoadBalance的HTTPS端口,若sslUsed配置为 true,则此参数不允许为空。

登录FusionInsight Manager,选择“集群 > 服务

> ClickHouse > 实例”,单击对应的

ClickHouseBalancer实例,选择“实例配置 > 全 部配置”,搜索“lb_https_port”并获取其参数 值,默认为21426。

CLICKHOUSE_SEC

URITY_ENABLED true ClickHouse安全模式开关,安全模式集群时该参数 固定为true。

databaseName testdb 样例代码工程中需要创建的数据库名称,可以根据 实际情况修改。

tableName testtb 样例代码工程中需要创建的表名称,可以根据实际 情况修改。

batchRows 10000 一个批次写入数据的条数。

batchNum 10 写入数据的总批次。

应用开发指南 9 ClickHouse 开发指南(安全模式)

说明

ClickHouse虽有集群能力,但没有统一的访问入口,客户端需要直接感知集群内所有的节点,易 用性不好。ClickHouse提供了基于Loadbalance部署架构,可以将用户访问流量自动分发到多台 后端节点,扩展系统对外的服务能力,实现更高水平的应用容错。客户端应用请求集群时,使用 基于Nginx的ClickHouseBalancer控制节点来进行流量分发,无论集群写入的负载、读的负载以 及应用接入的高可用性都具备了有力的保障。

----结束

9.3 开发程序

9.3.1 典型场景说明

通过典型场景,我们可以快速学习和掌握ClickHouse的开发过程,并且对关键的接口 函数有所了解。

9.3.2 开发思路

开发思路

ClickHouse作为一款独立的DBMS系统,使用SQL语言就可以进行常见的操作。以下开 发程序示例中,全部通过clickhouse-jdbc API接口来进行描述。

● 设置属性

● 建立连接

● 创建库

● 创建表

● 插入数据

● 查询数据

● 删除表

9.4 样例代码说明

9.4.1 设置属性

设置连接属性,如下样例代码设置socket超时时间为60s。

ClickHouseProperties clickHouseProperties = new ClickHouseProperties();

clickHouseProperties.setSocketTimeout(60000);

clickHouseProperties.setSsl(true);

clickHouseProperties.setSslMode("none");

9.4.2 建立连接

创建连接时传入表9-3中配置的user和password作为认证凭据,ClickHouse会带着用户 名和密码在服务端进行安全认证。

ClickHouseDataSource clickHouseDataSource =new ClickHouseDataSource(JDBC_PREFIX + serverList.get(tries - 1), clickHouseProperties);

connection = clickHouseDataSource.getConnection(user, password);

应用开发指南 9 ClickHouse 开发指南(安全模式)

9.4.3 创建库

通过on cluster语句在集群中创建表9-3中以databaseName参数值为数据库名的数据 库。private void createDatabase(String databaseName, String clusterName) throws Exception {

String createDbSql = "create database if not exists " + databaseName + " on cluster " + clusterName;

util.exeSql(createDbSql);

}

9.4.4 创建表

通过on cluster语句在集群中创建表9-3中tableName参数值为表名的ReplicatedMerge 表和Distributed表。

private void createTable(String databaseName, String tableName, String clusterName) throws Exception { String createSql = "create table " + databaseName + "." + tableName + " on cluster " + clusterName +

" (name String, age UInt8, date Date)engine=ReplicatedMergeTree('/clickhouse/tables/{shard}/" + databaseName + "." + tableName + "'," + "'{replica}') partition by toYYYYMM(date) order by age";

String createDisSql = "create table " + databaseName + "." + tableName + "_all" + " on cluster " + clusterName + " as " + databaseName + "." + tableName + " ENGINE = Distributed(default_cluster," + databaseName + "," + tableName + ", rand());"; ArrayList<String> sqlList = new ArrayList<String>();

sqlList.add(createSql);

sqlList.add(createDisSql);

util.exeSql(sqlList);

}

9.4.5 插入数据

创建表创建的表具有三个字段,分别是String、UInt8和Date类型。

String insertSql = "insert into " + databaseName + "." + tableName + " values (?,?,?)";

PreparedStatement preparedStatement = connection.prepareStatement(insertSql);

long allBatchBegin = System.currentTimeMillis();

for (int j = 0; j < batchNum; j++) { for (int i = 0; i < batchRows; i++) {

preparedStatement.setString(1, "huawei_" + (i + j * 10));

preparedStatement.setInt(2, ((int) (Math.random() * 100)));

preparedStatement.setDate(3, generateRandomDate("2018-01-01", "2021-12-31"));

preparedStatement.addBatch();

}

long begin = System.currentTimeMillis();

preparedStatement.executeBatch();

long end = System.currentTimeMillis();

log.info("Inert batch time is {} ms", end - begin);

}long allBatchEnd = System.currentTimeMillis();

log.info("Inert all batch time is {} ms", allBatchEnd - allBatchBegin);

9.4.6 查询数据

查询语句1:querySql1查询创建表创建的tableName表中任意10条数据;查询语句 2:querySql2通过内置函数对创建表创建的tableName表中的日期字段取年月后进行 聚合。

private void queryData(String databaseName, String tableName) throws Exception {

String querySql1 = "select * from " + databaseName + "." + tableName + "_all" + " order by age limit 10";

String querySql2 = "select toYYYYMM(date),count(1) from " + databaseName + "." + tableName + "_all"

+ " group by toYYYYMM(date) order by count(1) DESC limit 10";

ArrayList<String> sqlList = new ArrayList<String>();

sqlList.add(querySql1);

sqlList.add(querySql2);

ArrayList<ArrayList<ArrayList<String>>> result = util.exeSql(sqlList);

for (ArrayList<ArrayList<String>> singleResult : result) { for (ArrayList<String> strings : singleResult) {

应用开发指南 9 ClickHouse 开发指南(安全模式)

StringBuilder stringBuilder = new StringBuilder();

for (String string : strings) {

stringBuilder.append(string).append("\t");

}

log.info(stringBuilder.toString());

} } }

9.4.7 删除表

删除在创建表中创建的副本表和分布式表。

private void dropTable(String databaseName, String tableName, String clusterName) throws Exception { String dropLocalTableSql = "drop table if exists " + databaseName + "." + tableName + " on cluster " + clusterName;

String dropDisTableSql = "drop table if exists " + databaseName + "." + tableName + "_all" + " on cluster

" + clusterName;

ArrayList<String> sqlList = new ArrayList<String>();

sqlList.add(dropLocalTableSql);

sqlList.add(dropDisTableSql);

util.exeSql(sqlList);

}

9.5 调测程序

9.5.1 在 Windows 下调测程序

编译并运行程序

在程序代码完成开发后,您可以在Windows环境中运行应用。本地和集群业务平面网 络互通时,您可以直接在本地进行调测。在开发环境IntelliJ IDEA工程“clickhouse-examples”中单击“Run 'Demo'”运行应用程序工程。

查看调测结果

ClickHouse应用程序运行完成后,可通过以下方式查看程序运行情况:

● 通过运行结果查看程序运行情况。

● 通过ClickHouse日志获取应用运行情况,即“logs”目录下的日志文件:

clickhouse-example.log。

应用开发指南 9 ClickHouse 开发指南(安全模式)

运行clickhouse-examples的完整样例后,控制台显示部分运行结果如下:

Connected to the target VM, address: '127.0.0.1:53321', transport: 'socket'

2021-04-21 21:02:16,900 | INFO | main | loadBalancerIPList is 100.120.147.36, loadBalancerHttpPort is 21425, user is luxx, clusterName is default_cluster, isSec is true, password is Admin12!. |

com.huawei.clickhouse.examples.Demo.main(Demo.java:40)

2021-04-21 21:02:16,904 | INFO | main | ckLbServerList current member is 0, ClickhouseBalancer is 100.120.147.36:21425 | com.huawei.clickhouse.examples.Demo.getCkLbServerList(Demo.java:96) 2021-04-21 21:02:16,914 | INFO | main | Driver registered |

ru.yandex.clickhouse.ClickHouseDriver.<clinit>(ClickHouseDriver.java:49)

2021-04-21 21:02:16,918 | INFO | main | Current load balancer is 100.120.147.36:21425 | com.huawei.clickhouse.examples.Util.exeSql(Util.java:58)

2021-04-21 21:02:17,517 | INFO | main | Execute query:drop table if exists testdb.testtb on cluster default_cluster | com.huawei.clickhouse.examples.Util.exeSql(Util.java:63)

2021-04-21 21:02:17,656 | INFO | main | Execute time is 139 ms | com.huawei.clickhouse.examples.Util.exeSql(Util.java:67)

2021-04-21 21:02:17,657 | INFO | main | Current load balancer is 100.120.147.36:21425 | com.huawei.clickhouse.examples.Util.exeSql(Util.java:58)

2021-04-21 21:02:17,701 | INFO | main | Execute query:drop table if exists testdb.testtb_all on cluster default_cluster | com.huawei.clickhouse.examples.Util.exeSql(Util.java:63)

2021-04-21 21:02:17,851 | INFO | main | Execute time is 148 ms | com.huawei.clickhouse.examples.Util.exeSql(Util.java:67)

2021-04-21 21:02:17,851 | INFO | main | Current load balancer is 100.120.147.36:21425 | com.huawei.clickhouse.examples.Util.exeSql(Util.java:58)

2021-04-21 21:02:17,895 | INFO | main | Execute query:create database if not exists testdb on cluster default_cluster | com.huawei.clickhouse.examples.Util.exeSql(Util.java:63)

2021-04-21 21:02:18,043 | INFO | main | Execute time is 148 ms | com.huawei.clickhouse.examples.Util.exeSql(Util.java:67)

2021-04-21 21:02:18,044 | INFO | main | Current load balancer is 100.120.147.36:21425 | com.huawei.clickhouse.examples.Util.exeSql(Util.java:58)

2021-04-21 21:02:18,088 | INFO | main | Execute query:create table testdb.testtb on cluster default_cluster (name String, age UInt8, date Date)engine=ReplicatedMergeTree('/clickhouse/tables/{shard}/

testdb.testtb','{replica}') partition by toYYYYMM(date) order by age | com.huawei.clickhouse.examples.Util.exeSql(Util.java:63)

2021-04-21 21:02:18,233 | INFO | main | Execute time is 144 ms | com.huawei.clickhouse.examples.Util.exeSql(Util.java:67)

2021-04-21 21:02:18,233 | INFO | main | Current load balancer is 100.120.147.36:21425 | com.huawei.clickhouse.examples.Util.exeSql(Util.java:58)

2021-04-21 21:02:18,278 | INFO | main | Execute query:create table testdb.testtb_all on cluster

2021-04-21 21:02:18,278 | INFO | main | Execute query:create table testdb.testtb_all on cluster