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

throwable發表於2020-11-21

前提

隨著現在業務開展,幾個業務系統的資料量開始急劇膨脹。之前使用了關係型資料庫MySQL進行了一次資料倉儲的建模,發現了資料量上來後,大量的JOIN操作在提高了雲MySQL的配置後依然有點吃不消,加之開發了一個基於關係型資料庫設計的標籤服務,日全量標籤資料(無法避免的笛卡爾積)單表超過5000W。目前採取了基於使用者ID分段配合多程式處理的方式暫時延緩了效能的惡化,但是考慮到不遠將來,還是需要做一個小型的資料平臺。Hadoop的那套體系過於龐大,元件過多,硬體和軟體的學習成本比較高,不是一朝一夕可以讓小團隊的所有成員掌握。考慮到這麼多因素的前提下,需要調研ClickHouse這項黑科技,看看使用他能不能突圍困局。

軟體版本

這裡就不對ClickHouse進行簡介,其官方網站https://clickhouse.tech有詳細的文件。一般使用Windows系統進行開發,如果是Windows10則可以直接安裝Docker,利用Hyper-V的特性直接執行ClickHouse的映象即可。下面列出開發環境搭建需要的軟體:

軟體 版本 備註
Windows 10 確保使用了Windows10並且開啟了Hyper-V才能使用Docker
Docker Desktop 任意 DockerWindows桌面版
ClickHouse Server 20.3.x 直接拉取latest的映象即可
ClickHouse Client 20.3.x 直接拉取latest的映象即可
Cmder 最新版 可選,用來代替自帶的不好用控制檯

Windows10下可以通過:控制皮膚 -> 程式 -> 啟用或關閉Windows功能 -> Hyper-V(勾選Hyper-V管理平臺和Hyper-V平臺,然後重啟生效)開啟Hyper-V特性:

然後在Docker官方站點的https://www.docker.com/get-started子頁面可以找到Docker Desktop的下載入口:

安裝完之後Docker Desktop會隨著系統自啟,軟體介面如下:

安裝和使用ClickHouse

注意需要先初步瞭解ClickHouse的核心目錄,再進行容器安裝啟動。

映象拉取和核心目錄

先下載ClickHouse ServerClickHouse Client的映象:

docker pull yandex/clickhouse-server
docker pull yandex/clickhouse-client

下載完畢後提示如下:

可以通過docker images驗證一下:

λ  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服務本身依賴三個埠,這三個埠的預設值是9000TCP協議)、8123HTTP協議)和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.xmlusers.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.xmlusers.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 '-'
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:defaultroot:root兩個賬號密碼的SHA256摘要。修改宿主機上的users.xml檔案:

然後修改宿主機上的config.xml檔案:

最後通過docker stop temp-clickhouse-server停止和銷燬臨時容器。

執行ClickHouse服務

接著使用下面的命令建立和執行一個ClickHouse Server容器例項(確保config.xmlusers.xml已經存在):

命名和容器命名: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按鈕即可。

最後使用原生的命令列客戶端ClickHouse Client進行連線,使用命令docker run -it --rm --link single-clickhouse-server:clickhouse-server yandex/clickhouse-client -uroot --password root --host clickhouse-server

λ  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服務

ClickHouseJDBC驅動目前有三個:

  • 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依賴:

<dependency>
    <groupId>ru.yandex.clickhouse</groupId>
    <artifactId>clickhouse-jdbc</artifactId>
    <version>0.2.4</version>
</dependency>

編寫一個測試類:

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<String> 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")));
        }
    }
}

執行結果如下:

表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 開始搞小資料)

個人部落格

相關文章