在上一篇中,我们通过Docker构建了一个简单的单点Clickhouse,但是如果要做大数据的处理的话,Clickhouse集群是必不可少的,今天我们先用Docker简单地搭建一个Clickhouse集群。
容器逐个部署
使用Docker部署ClickHouse集群涉及几个步骤,包括创建Docker网络、配置ClickHouse容器以及设置集群的各个节点。
1. 创建Docker网络
首先,需要创建一个Docker网络,以确保ClickHouse容器可以相互通信。
docker network create --subnet=172.18.0.0/16 clickhouse_network
如果遇到了这个问题"Error response from daemon: Pool overlaps with other one on this address space",那说明docker已经建立了对应的子网,占据了地址,我们可以改一下,比如说--subnet=172.16.0.0/16,如果此处冲突了。下一步的docker run指定的ip也需要修改。
2. 启动ClickHouse服务器
接着,启动ClickHouse服务器实例。假设我们要部署一个具有三个节点的集群。
对于每个节点,运行一个ClickHouse容器,并加入之前创建的网络:
docker run -d --name clickhouse-server-1 \
--ip 172.18.0.2 \
--network clickhouse_network \
-p 8123:8123 \
-p 9000:9000 \
-v /path/to/configs:/var/lib/clickhouse \
yandex/clickhouse-server
docker run -d --name clickhouse-server-2 \
--ip 172.18.0.3 \
--network clickhouse_network \
yandex/clickhouse-server
docker run -d --name clickhouse-server-3 \
--ip 172.18.0.4 \
--network clickhouse_network \
yandex/clickhouse-server
这里-p 8123:8123
和-p 9000:9000
表示将容器的端口映射到宿主机,这样可以通过宿主机的端口访问ClickHouse服务。-v
参数用于将宿主机的配置文件目录挂载到容器中,以自定义配置。
上面的格式是在bash下的格式,如果在Powershell,需要把斜杠去掉。 上面的容器是yandex/clickhouse-server,也可以修改成clickhouse/clickhouse-server,这个容器上一篇文章中下载过了。
3. 配置ClickHouse集群
每个ClickHouse节点都需要在其配置文件config.xml
中设置集群配置。你需要编辑每个节点的config.xml
文件,添加集群配置信息。
docker exec -it clickhouse-server-1 bash
cd /etc/clickhouse-server
//下载vim
apt-get update
apt-get install vim
vim config.xml
//按照下面的内容修改,修改完后
//先按Esc,:wq回车就保存好了
以下是示例配置:
<clickhouse>
<!-- Other configurations... -->
<remote_servers>
<cluster_1>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>clickhouse-server-1</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>clickhouse-server-2</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>clickhouse-server-3</host>
<port>9000</port>
</replica>
</shard>
</cluster_1>
</remote_servers>
<!-- Other configurations... -->
</clickhouse>
确保<host>
标签中的值与Docker容器名称一致。
修改结束之后,可以用exit退出当前容器,也可以ctrl+p+q退出
4. 重启ClickHouse服务器
配置完成后,需要重启所有ClickHouse服务器以使配置生效。
docker restart clickhouse-server-1 clickhouse-server-2 clickhouse-server-3
5. 验证集群
使用ClickHouse客户端连接到任意一个节点,并运行以下命令来验证集群是否配置正确:
docker exec -it clickhouse-server-1 clickhouse-client --query "SELECT * FROM system.clusters"
这个查询应该返回你配置的集群信息。
6. 删除集群
docker stop clickhouse-server-1 clickhouse-server-2 clickhouse-server-3
docker rm clickhouse-server-1 clickhouse-server-2 clickhouse-server-3
docker network rm clickhouse_network
使用Docker-compose部署
1. 编写yaml文件
使用docker-compose
来搭建ClickHouse集群会更加简单和方便,因为docker-compose
允许你在一个YAML文件中定义所有的服务,并且管理它们的生命周期。
version: '3'
services:
clickhouse-server-1:
image: yandex/clickhouse-server
container_name: clickhouse-server-1
networks:
- clickhouse_network
ports:
- "8123:8123"
- "9000:9000"
volumes:
- /path/to/configs-1:/var/lib/clickhouse
clickhouse-server-2:
image: yandex/clickhouse-server
container_name: clickhouse-server-2
networks:
- clickhouse_network
volumes:
- /path/to/configs-2:/var/lib/clickhouse
clickhouse-server-3:
image: yandex/clickhouse-server
container_name: clickhouse-server-3
networks:
- clickhouse_network
volumes:
- /path/to/configs-3:/var/lib/clickhouse
networks:
clickhouse_network:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.18.0.0/16
上面的volumns可以不带,如果不想挂载主机路径的话,上面的network里面的subnet地址也可以因为冲突修改掉。
在这个配置文件中,我们定义了三个ClickHouse服务(clickhouse-server-1
、clickhouse-server-2
和clickhouse-server-3
),它们都使用yandex/clickhouse-server
镜像。每个服务都挂载了一个卷,用于存储配置文件和数据。此外,我们创建了一个名为clickhouse_network
的网络,用于服务之间的通信。
2. 修改配置文件
与直接使用Docker容器一样,你需要为每个ClickHouse节点配置集群设置。编辑每个节点的config.xml
文件,添加集群配置信息。由于我们使用了卷挂载,你可以在宿主机的相应路径下编辑这些配置文件。
如果没有使用-v进行挂载的话,还是得进入到每个容器里面进行修改。
3. 启动集群
配置完成后,使用以下命令启动集群:
docker-compose up -d
这将根据docker-compose.yml
文件定义启动所有服务。
4. 验证集群
使用ClickHouse客户端连接到任意一个节点,并运行以下命令来验证集群是否配置正确:
docker-compose exec clickhouse-server-1 clickhouse-client --query "SELECT * FROM system.clusters"
这个查询应该返回你配置的集群信息。
5. 删除集群
docker-compose down -v --rmi all
Go使用Clickhouse
Go
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/ClickHouse/clickhouse-go"
)
func main() {
// 连接到ClickHouse单点
connectToSingleNode()
// 连接到ClickHouse集群
connectToCluster()
}
func connectToSingleNode() {
conn, err := sql.Open("clickhouse", "tcp://localhost:9000?debug=true")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
var version string
if err := conn.QueryRow("SELECT version()").Scan(&version); err != nil {
log.Fatal(err)
}
fmt.Printf("Single Node Version: %s\n", version)
}
func connectToCluster() {
conn, err := sql.Open("clickhouse", "tcp://localhost:9000,tcp://localhost:9001,tcp://localhost:9002?debug=true")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
var version string
if err := conn.QueryRow("SELECT version()").Scan(&version); err != nil {
log.Fatal(err)
}
fmt.Printf("Cluster Version: %s\n", version)
}
上述分别定义了连接单点和连接集群的方法,主要是在连接地址的不同,其余的对于开发者而言都是透明的,包括切片的选取和副本。
connectToSingleNode
函数连接到单个ClickHouse实例,它使用tcp://localhost:9000
作为连接字符串。connectToCluster
函数连接到ClickHouse集群,它使用tcp://localhost:9000,tcp://localhost:9001,tcp://localhost:9002
作为连接字符串,这样就可以连接到多个分片。
在ClickHouse中,当你连接到集群时,通常不需要手动选择分片。ClickHouse的查询处理器会自动处理分布式查询,根据查询语句和集群配置将查询分发到适当的分片上。你只需要连接到集群中的任何一个节点,ClickHouse就会负责将查询分发到所有相关的分片上,并合并结果。
然而,如果你想要手动控制查询在哪些分片上执行,你可以在查询中使用ON CLUSTER
子句来指定集群的名称,以及使用SHARD
和REPLICA
子句来指定特定的分片和副本。例如:
SELECT * FROM my_table ON CLUSTER my_cluster WHERE shard = 1
这个查询只会在集群my_cluster
中编号为1的分片上执行。
在Go程序中,你仍然使用相同的连接字符串来连接到集群,无论你是在所有分片上执行查询还是在特定的分片上执行查询。ClickHouse的Go驱动会处理与集群的通信,并将查询发送到正确的位置。