人群圈选业务痛点
- 用户标签多、标签丰富,标签列可达成百甚至上千列。
- 数据量庞大,用户数多,从而所需运算量也极大。
- 圈选条件组合多样化,没有固定索引可以优化,存储空间占用极大。
- 性能要求高,圈选结果要求及时响应,过长的延时会造成营销人群的不准确。
- 数据更新时效要求高,用户画像要求近实时的更新,过期的人群信息也将直接影响圈选的精准性。
ClickHouse 特性
- 优势
- 查询速度快
- 存储压缩率高,节省空间
- 架构简单,集群中所有节点功能相同,规避单点故障
- 社区活跃,应用广泛,产品成熟度高
- 不足
- 不支持事务、异步删除与更新
- 不适合高并发场景
- 不支持标准 sql,join 由内部实现
- 集群在线扩容支持不佳,运维成本高
下载安装包
sudo yum install yum-utils
sudo rpm --import https://repo.clickhouse.tech/CLICKHOUSE-KEY.GPG
sudo yum-config-manager --add-repo https://repo.clickhouse.tech/rpm/clickhouse.repo
sudo yum install clickhouse-server clickhouse-client
文件目录
# 默认数据存储路径
/var/lib/clickhouse
# 默认日志路径
/var/log/clickhouse-server
# 服务端配置文件路径
/etc/clickhouse-server
# 核心配置文件详解:https://www.e-learn.cn/topic/4050968
/etc/clickhouse-server/config.xml
# 客户端配置文件路径
/etc/clickhouse-client
命令
# 服务端命令
service clickhouse-server start | status | restart | stop
# 调试,日志打印在控制台
sudo -u clickhouse /usr/bin/clickhouse-server --config-file /etc/clickhouse-server/config.xml
# 启动客户端
clickhouse-client --port 9003
集群部署
-
在群集的所有机器上安装 ClickHouse 服务端
-
在配置文件中设置群集配置
<!--config.xml配置--> <tcp_port>9003</tcp_port> <listen_host>::</listen_host> <!--incl属性表示可从外部文件中获取节点名--> <remote_servers incl="clickhouse_remote_servers" /> <zookeeper incl="zookeeper-servers" optional="true" /> <macros incl="macros" optional="true" /> <!--使用外部扩展配置文件--> <include_from>/etc/clickhouse-server/metrika.xml</include_from> <!--metrika.xml配置--> <yandex> <!-- 集群配置 --> <clickhouse_remote_servers> <ck_cluster> <shard> <replica> <host>worker07</host> <port>9003</port> </replica> <replica> <host>worker08</host> <port>9003</port> </replica> <replica> <host>worker09</host> <port>9003</port> </replica> </shard> </ck_cluster> </clickhouse_remote_servers> <!--zookeeper相关配置--> <zookeeper-servers> <node index="3"> <host>master01</host> <port>2181</port> </node> <node index="2"> <host>worker01</host> <port>2181</port> </node> <node index="1"> <host>worker02</host> <port>2181</port> </node> <node index="5"> <host>worker03</host> <port>2181</port> </node> <node index="4"> <host>worker04</host> <port>2181</port> </node> </zookeeper-servers> <!--环境变量 --> <macros> <shard>0</shard> <replica>worker07</replica> </macros> </yandex>
-
分发配置,其自动生效,查看集群
select * from system.clusters;
一致性
internal_replication:表示是否只将数据写入其中一个副本,默认为 false
四种复制模式:
- 非复制表,internal_replication=false。写入单机表时,不同服务器查询结果不同;插入到分布式表中的数据被插入到两个本地表中,如果在插入期间没有问题,则两个本地表上的数据保持同步。我们称之为“穷人的复制”,因为复制在网络出现问题的情况下容易发生分歧,没有一个简单的方法来确定哪一个是正确的复制。
- 非复制表,internal_replication=true。数据只被插入到一个本地表中,但没有任何机制可以将它转移到另一个表中。因此,在不同主机上的本地表看到了不同的数据,查询分布式表时会出现非预期的数据。显然,这是配置 ClickHouse 集群的一种不正确的方法。
- 复制表,internal_replication=true。插入到分布式表中的数据仅插入到其中一个本地表中,但通过复制机制传输到另一个主机上的表中。因此两个本地表上的数据保持同步。这是官方推荐配置。
- 复制表,internal_replication=false。数据被插入到两个本地表中,但同时复制表的机制保证重复数据会被删除。数据会从插入的第一个节点复制到其它的节点。其它节点拿到数据后如果发现数据重复,数据会被丢弃。这种情况下,虽然复制保持同步,没有错误发生。但由于不断的重复复制流,会导致写入性能明显的下降。所以这种配置实际应该是避免的。
优化
- 读的时候是用 distribution 表去读取数据,轮询写入本地表
- 写入时尽量“大批量,少批次”写入
- 尽量使用大宽表代替 join,列宽支持 1w+
集群测试
-- 先创建本地表,再创建分布式表,往分布式表插入数据,数据随机分布在本地表
-- 在每个实例上创建本地表
CREATE TABLE default.cluster3s1r_local(`id` Int32,`website` String,`wechat` String,`FlightDate` Date,Year UInt16) ENGINE = MergeTree(FlightDate, (Year, FlightDate), 8192);
-- 创建一个分布式表(指定集群名、数据库名、数据表名、分片KEY)
CREATE TABLE default.cluster3s1r_all AS cluster3s1r_local ENGINE = Distributed(ck_cluster, default, cluster3s1r_local, rand());
-- 插入测试数据
INSERT INTO default.cluster3s1r_all
(id,website,wechat,FlightDate,Year)values(1,'https://niocoder.com/','java干货','2020-11-28',2020);
INSERT INTO default.cluster3s1r_all (id,website,wechat,FlightDate,Year)values(2,'http://www.merryyou.cn/','javaganhuo','2020-11-28',2020);
INSERT INTO default.cluster3s1r_all (id,website,wechat,FlightDate,Year)values(3,'http://www.xxxxx.cn/','xxxxx','2020-11-28',2020);
-- 查询分布式表
select * from cluster3s1r_all;
-- 查询本地表
select * from cluster3s1r_local;
-- 创建复制表,连接zk,不用创建分布式表,不配置集群clickhouse_remote_servers。数据写入本地表,其他节点自动同步数据
-- 创建复制表
CREATE TABLE default.cluster1s3r_local on cluster ck_cluster (`id` Int32,`website` String,`wechat` String,`FlightDate` Date,Year UInt16) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/cluster1s3r_local', '{replica}', FlightDate, (Year, FlightDate), 8192);
INSERT INTO default.cluster1s3r_all
(id,website,wechat,FlightDate,Year)values(1,'https://niocoder.com/','java干货','2020-11-28',2020);
select * from cluster1s3r_all;
问题
-
DB::Exception: Effective user of the process (root) does not match the owner of the data (clickhouse). Run under ‘sudo -u clickhouse’.
sudo -u clickhouse clickhouse-server —config-file=/etc/clickhouse-server/config.xml
-
Access to file denied: /var/log/clickhouse-server/clickhouse-server.log
chown -R clickhouse /var/log/clickhouse-server/
-
Address already in use
更改 tcp 配置,切换 9000 端口为 9003
-
There are two exactly the same ClickHouse instances
单台节点只能部署一个分片副本,即 3 分片 2 副本需要 6 台服务器