Windows10系統下使用Docker搭建ClickHouse開發環境
阿新 • • 發佈:2020-11-21
## 前提
隨著現在業務開展,幾個業務系統的資料量開始急劇膨脹。之前使用了關係型資料庫`MySQL`進行了一次資料倉庫的建模,發現了資料量上來後,大量的`JOIN`操作在提高了雲`MySQL`的配置後依然有點吃不消,加之開發了一個基於關係型資料庫設計的標籤服務,日全量標籤資料(無法避免的笛卡爾積)單表超過`5000W`。目前採取了基於使用者`ID`分段配合多程序處理的方式暫時延緩了效能的惡化,但是考慮到不遠將來,還是需要做一個小型的資料平臺。`Hadoop`的那套體系過於龐大,元件過多,硬體和軟體的學習成本比較高,不是一朝一夕可以讓小團隊的所有成員掌握。考慮到這麼多因素的前提下,需要調研`ClickHouse`這項黑科技,看看使用他能不能突圍困局。
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-1.png)
## 軟體版本
這裡就不對`ClickHouse`進行簡介,其官方網站`https://clickhouse.tech`有詳細的文件。一般使用`Windows`系統進行開發,如果是`Windows10`則可以直接安裝`Docker`,利用`Hyper-V`的特性直接執行`ClickHouse`的映象即可。下面列出開發環境搭建需要的軟體:
|軟體|版本|備註|
|:-:|:-:|:-:|
|`Windows`|`10`|確保使用了`Windows10`並且開啟了`Hyper-V`才能使用`Docker`|
|`Docker Desktop`|任意|`Docker`的`Windows`桌面版|
|`ClickHouse Server`|`20.3.x`|直接拉取`latest`的映象即可|
|`ClickHouse Client`|`20.3.x`|直接拉取`latest`的映象即可|
|`Cmder`|最新版|可選,用來代替自帶的不好用控制檯|
`Windows10`下可以通過:控制面板 `->` 程式 `->` 啟用或關閉`Windows`功能 `->` `Hyper-V`(勾選`Hyper-V`管理平臺和`Hyper-V`平臺,然後重啟生效)開啟`Hyper-V`特性:
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-2.png)
然後在`Docker`官方站點的`https://www.docker.com/get-started`子頁面可以找到`Docker Desktop`的下載入口:
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-3.png)
安裝完之後`Docker Desktop`會隨著系統自啟,軟體介面如下:
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-4.png)
## 安裝和使用ClickHouse
注意需要先初步瞭解`ClickHouse`的核心目錄,再進行容器安裝啟動。
### 映象拉取和核心目錄
先下載`ClickHouse Server`和`ClickHouse Client`的映象:
```shell
docker pull yandex/clickhouse-server
docker pull yandex/clickhouse-client
```
下載完畢後提示如下:
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-5.png)
可以通過`docker images`驗證一下:
```shell
λ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
yandex/clickhouse-server latest c85f84ea6550 10 days ago 515MB
yandex/clickhouse-client latest f94470cc9cd9 10 days ago 488MB
```
兩個映象其實都是包裹在一個微型的`Ubuntu`系統中,所以啟動後的容器可以使用當作是一個`Linux`系統這樣操作。`ClickHouse Server`在容器中的核心目錄部分如下:
- `/etc/clickhouse-server`:這個是`ClickHouse Server`預設的配置檔案目錄,包括全域性配置`config.xml`和使用者配置`users.xml`等等。
- `/var/lib/clickhouse`:這個是`ClickHouse Server`預設的資料儲存目錄。
- `/var/log/clickhouse-server`:這個是`ClickHouse Server`預設的日誌輸出目錄。
為了方便管理配置、檢視資料和搜尋日誌,可以把上面這三個目錄直接對映到宿主機的具體目錄,筆者在本開發機做了如下的對映:
|Docker容器目錄|宿主機目錄|
|:-:|:-:|
|`/etc/clickhouse-server`|`E:/Docker/images/clickhouse-server/single/conf`|
|`/var/lib/clickhouse`|`E:/Docker/images/clickhouse-server/single/data`|
|`/var/log/clickhouse-server`|`E:/Docker/images/clickhouse-server/single/log`|
`ClickHouse Server`啟動前需要注意幾點:
- `ClickHouse Server`服務本身依賴三個埠,這三個埠的預設值是`9000`(`TCP`協議)、`8123`(`HTTP`協議)和`9009`(叢集資料複製),對映到宿主機的時候儘可能一一對應,所以需要確保宿主機的這三個埠沒有被佔用,可以使用`Docker`的引數`-p`指定容器和宿主機的埠對映。
- `ClickHouse Server`正常使用需要修改容器系統的檔案控制代碼數量配置`ulimit nofile`,可以使用`Docker`引數`--ulimit nofile=262144:262144`指定檔案控制代碼數。
- 可以運用一個技巧,使用`Docker`的`--rm`引數建立臨時容器,先獲取到`/etc/clickhouse-server`目錄下配置檔案,通過`docker cp 容器目錄 宿主機目錄`命令可以拷貝容器的配置檔案到宿主機目錄下,容器停止之後會被直接刪除,這樣就能保留宿主機的配置檔案模板。
### 臨時容器拷貝配置
先執行命令`docker run --rm -d --name=temp-clickhouse-server yandex/clickhouse-server`執行一個臨時容器,成功後通過下面的命令拷貝容器的`config.xml`和`users.xml`檔案到宿主機:
- `docker cp temp-clickhouse-server:/etc/clickhouse-server/config.xml E:/Docker/images/clickhouse-server/single/conf/config.xml`
- `docker cp temp-clickhouse-server:/etc/clickhouse-server/users.xml E:/Docker/images/clickhouse-server/single/conf/users.xml`
這兩個命令執行完畢後,可以看到宿主機的磁碟目錄已經生成了`config.xml`和`users.xml`,接著需要做幾項配置:
- 建立`default`賬號的密碼。
- 建立一個新的`root`賬號。
- 開放客戶端監聽的`Host`,避免後面使用`JDBC`客戶端或者`ClickHouse Client`的時候無法連線`ClickHouse Server`。
通過`docker exec -it temp-clickhouse-server /bin/bash`命令進入臨時容器,然後在臨時容器中執行:
- `PASSWORD=$(base64 < /dev/urandom | head -c8); echo "default"; echo -n "default" | sha256sum | tr -d '-'`
- `PASSWORD=$(base64 < /dev/urandom | head -c8); echo "root"; echo -n "root" | sha256sum | tr -d '-'`
```shell
root@607c5abcc132:/# PASSWORD=$(base64 < /dev/urandom | head -c8); echo "default"; echo -n "default" | sha256sum | tr -d '-'
default
37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f
root@607c5abcc132:/# PASSWORD=$(base64 < /dev/urandom | head -c8); echo "root"; echo -n "root" | sha256sum | tr -d '-'
root
4813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2
```
這樣就得到了`default:default`和`root:root`兩個賬號密碼的`SHA256`摘要。修改宿主機上的`users.xml`檔案:
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-6.png)
然後修改宿主機上的`config.xml`檔案:
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-7.png)
最後通過`docker stop temp-clickhouse-server`停止和銷燬臨時容器。
### 執行ClickHouse服務
接著使用下面的命令建立和執行一個`ClickHouse Server`容器例項(確保`config.xml`和`users.xml`已經存在):
```shell
命名和容器命名:docker run -d --name=single-clickhouse-server
埠對映:-p 8123:8123 -p 9000:9000 -p 9009:9009
檔案控制代碼數配置:--ulimit nofile=262144:262144
資料目錄對映:-v E:/Docker/images/clickhouse-server/single/data:/var/lib/clickhouse:rw
配置目錄對映:-v E:/Docker/images/clickhouse-server/single/conf:/etc/clickhouse-server:rw
日誌目錄對映:-v E:/Docker/images/clickhouse-server/single/log:/var/log/clickhouse-server:rw
映象:yandex/clickhouse-server
```
上面的命令合成一行執行`docker run -d --name=single-clickhouse-server -p 8123:8123 -p 9000:9000 -p 9009:9009 --ulimit nofile=262144:262144 -v E:/Docker/images/clickhouse-server/single/data:/var/lib/clickhouse:rw -v E:/Docker/images/clickhouse-server/single/conf:/etc/clickhouse-server:rw -v E:/Docker/images/clickhouse-server/single/log:/var/log/clickhouse-server:rw yandex/clickhouse-server`
> 上面的命令執行完後,Docker Desktop會有幾個彈出框確認是否共享宿主機的目錄,直接按share it按鈕即可。
![](https://throwable-blog-1256189093.cos.ap-guangzhou.myqcloud.com/202011/c-h-i-g-8.png)
最後使用原生的命令列客戶端`ClickHouse Client`進行連線,使用命令`docker run -it --rm --link single-clickhouse-server:clickhouse-server yandex/clickhouse-client -uroot --password root --host clickhouse-server`:
```shell
λ docker run -it --rm --link single-clickhouse-server:clickhouse-server yandex/clickhouse-client -uroot --password root --host clickhouse-server
ClickHouse client version 20.10.3.30 (official build).
Connecting to clickhouse-server:9000 as user root.
Connected to ClickHouse server version 20.10.3 revision 54441.
f5abc88ff7e4 :) select 1;
SELECT 1
┌─1─┐
│ 1 │
└───┘
1 rows in set. Elapsed: 0.004 sec.
```
下次如果電腦重啟`ClickHouse Server`的容器沒有啟動,只需要使用命令`docker (re)start single-clickhouse-server`拉起容器例項即可。
## 使用JDBC連線ClickHouse服務
`ClickHouse`的`JDBC`驅動目前有三個:
- `clickhouse-jdbc`(官方):地址是`https://github.com/ClickHouse/clickhouse-jdbc`,目前版本是基於`Apache Http Client`實現。
- `ClickHouse-Native-JDBC`(第三方):地址是`https://github.com/housepower/ClickHouse-Native-JDBC`,基於`Socket`實現。
- `clickhouse4j`(第三方):地址是`https://github.com/blynkkk/clickhouse4j`,比官方驅動輕量級。
說實話有點尷尬,官方的驅動包竟然沒有對接`TCP`私有協議棧,而是使用了`HTTP`協議進行互動,這裡不知道效能會下降多少,但是基於"官方更好"的思維這裡還是選用官方的驅動包進行`Demo`演示。引入`clickhouse-jdbc`依賴:
```xml
ru.yandex.clickhouse
clickhouse-jdbc
0.2.4
```
編寫一個測試類:
```java
public class ClickHouseTest {
@Test
public void testCh() throws Exception {
ClickHouseProperties props = new ClickHouseProperties();
props.setUser("root");
props.setPassword("root");
// 不建立資料庫的時候會有有個全域性default資料庫
ClickHouseDataSource dataSource = new ClickHouseDataSource("jdbc:clickhouse://localhost:8123/default", props);
ClickHouseConnection connection = dataSource.getConnection();
ClickHouseStatement statement = connection.createStatement();
// 建立一張表,表引擎為Memory,這類表在服務重啟後會自動刪除
boolean execute = statement.execute("CREATE TABLE IF NOT EXISTS t_test(id UInt64,name String) ENGINE = Memory");
if (execute) {
System.out.println("建立表default.t_test成功");
} else {
System.out.println("表default.t_test已經存在");
}
ResultSet rs = statement.executeQuery("SHOW TABLES");
List tables = Lists.newArrayList();
while (rs.next()) {
tables.add(rs.getString(1));
}
System.out.println("default資料庫中的表:" + tables);
PreparedStatement ps = connection.prepareStatement("INSERT INTO t_test(*) VALUES (?,?),(?,?)");
ps.setLong(1, 1L);
ps.setString(2, "throwable");
ps.setLong(3, 2L);
ps.setString(4, "doge");
ps.execute();
statement = connection.createStatement();
rs = statement.executeQuery("SELECT * FROM t_test");
while (rs.next()) {
System.out.println(String.format("查詢結果,id:%s,name:%s", rs.getLong("id"), rs.getString("name")));
}
}
}
```
執行結果如下:
```shell
表default.t_test已經存在 # <--- 這裡估計是驅動包的實現有BUG,首次建立成功返回結果為false
default資料庫中的表:[t_test]
查詢結果,id:1,name:throwable
查詢結果,id:2,name:doge
```
## 小結
`ClickHouse`開發環境初步搭建完畢,後面會開始學習`ClickHouse`的基本語法、各類引擎的特性和使用場景以及叢集搭建(分片和多副本)等等。
參考資料:
- `https://clickhouse.tech`
## 提醒
這個是筆者在某次直接斷電後發現`Docker`中的`ClickHouse`服務雖然重啟成功,但是錯誤日誌瘋狂輸出`File not found`,導致所有客戶端無法連線服務。初步判斷為元資料和實際儲存的資料因為"斷電"後造成不一致導致的。所以建議在開發環境中關機前要先進入容器呼叫`service clickhouse-server stop`,然後在宿主機呼叫`docker stop 容器名|容器ID`停止容器再進行關機,否則需要遞迴刪除資料目錄下的`store`目錄中的所有檔案才能正常重啟`ClickHouse Server`和使用(這個是十分粗暴的辦法,**有比較大機率會直接導致資料丟失,一定要謹慎操作**)。
(本文完 c-2-d e-a-20201108 開始搞小資料)
## 個人部落格
- [Throwable's Blog](https://throwx.cn/2020/11/21/click-house-windows-install