前提
隨著現在業務開展,幾個業務系統的資料量開始急劇膨脹。之前使用了關係型資料庫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 |
任意 | 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
特性:
然後在Docker
官方站點的https://www.docker.com/get-started
子頁面可以找到Docker Desktop
的下載入口:
安裝完之後Docker Desktop
會隨著系統自啟,軟體介面如下:
安裝和使用ClickHouse
注意需要先初步瞭解ClickHouse
的核心目錄,再進行容器安裝啟動。
映象拉取和核心目錄
先下載ClickHouse Server
和ClickHouse 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
服務本身依賴三個埠,這三個埠的預設值是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 '-'
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
檔案:
然後修改宿主機上的config.xml
檔案:
最後通過docker stop temp-clickhouse-server
停止和銷燬臨時容器。
執行ClickHouse服務
接著使用下面的命令建立和執行一個ClickHouse Server
容器例項(確保config.xml
和users.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服務
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
依賴:
<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 開始搞小資料)