bigywater.tech
ClickHouse 内部原理 · 71

Kafka Engine:Kafka 消息如何进入 ClickHouse

真实起一个Kafka broker,验证Kafka Engine表直接SELECT时默认的安全护栏,以及开启后消费掉数据的真实行为。

查一次少一次
真实直接SELECT会把数据从Kafka队列里消费掉
默认有护栏
真实ClickHouse默认拦截直接SELECT并给出明确警告

做的事:真实起一个Kafka broker,建Kafka Engine表直接查

代码-- 真实的Kafka topic,生产3条消息 kafka-topics.sh --create --topic events ... echo '{"id":1,...}\n{"id":2,...}\n{"id":3,...}' | kafka-console-producer.sh --topic events CREATE TABLE demo.kafka_src (id UInt32, name String, amt Float64) ENGINE = Kafka SETTINGS kafka_broker_list='127.0.0.1:19200', kafka_topic_list='events', kafka_group_name='ch_group1', kafka_format='JSONEachRow'; SELECT * FROM demo.kafka_src; -- 直接查会怎样?

验证:真实被安全护栏拦住了

实测 · 本机执行输出
SELECT * FROM demo.kafka_src ORDER BY id;
→ DB::Exception: Direct select is not allowed. To enable use setting
  `stream_like_engine_allow_direct_select`, but be aware that usually
  the read data is removed from the queue. (QUERY_NOT_ALLOWED)

ClickHouse真实默认不让你直接SELECT一张Kafka Engine表,报错信息本身就写明了真实的原因——直接查询会把读到的数据从队列里真实移除。

验证:开启之后真实第一次能读到,第二次就真实空了

实测 · 本机执行输出(SETTINGS stream_like_engine_allow_direct_select=1)
第1次 SELECT * FROM demo.kafka_src ORDER BY id;
→ 1  alice  10.5
  2  bob    20
  3  carol  30.5

第2次(同样的查询,同一个consumer group):
→ (空,一行都没有)
这组真实对比精确验证了报错信息里说的"usually removed from the queue"到底是什么意思:Kafka Engine表真实不是一张普通意义上"数据存在磁盘上、查多少次都一样"的表,它更像是一个贴了SQL接口的消费者游标——每次SELECT真实驱动这个内部消费者去Kafka broker拉取新消息,拉到的消息读完就真实提交了offset(本文这个例子里,第一次查询之后system.kafka_consumers真实显示current_offset变成了3),第二次用同一个consumer group再查,Kafka broker真实知道这个group已经读到过offset 3之后的位置了,自然返回空。这也是为什么ClickHouse要给"直接SELECT"这件事设一道默认关闭的护栏——如果新手不知道这个机制,以为Kafka Engine表跟普通表一样可以反复查看,第一次调试查询就会真实把数据"看没了",后续任何依赖这份数据的下游处理都会真实拿到空结果。真实推荐的用法(本系列下一篇会验证)是配合Materialized View,让消费和落盘这两件事自动持续发生,而不是靠人工反复执行SELECT。

分步演示:从安全护栏到真实的消费即清空

每一步都是本文上面用真实Kafka broker跑出来的原始结果。

Kafka Engine表:查一次少一次的真实消费者游标
这一步新验证的状态

    本文用到的工具

    • 本机真实独立起的Kafka broker(KRaft单节点),真实的 ENGINE = Kafka
    • 真实的 stream_like_engine_allow_direct_select 与 system.kafka_consumers
    京ICP备2026067502号-1京公网安备11010502063487号