1. 程式人生 > >Windows10系統下使用Docker搭建ClickHouse開發環境

Windows10系統下使用Docker搭建ClickHouse開發環境

## 前提 隨著現在業務開展,幾個業務系統的資料量開始急劇膨脹。之前使用了關係型資料庫`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