写这篇总结,是因为最近刚把腾讯云上的这套实时数仓完整跑通,从最开始选型、搭环境,到后面一步步调优、踩坑、填坑,整个过程值得好好记一笔。网上关于实时数仓的理论文章很多,但真正把腾讯云上的实操细节、组件选型逻辑、以及那些“不跑一遍根本发现不了”的坑讲清楚的不多,所以这篇就来补这个缺。如果你是正在做大数据开发、准备搞实时数仓项目、或者刚买了腾讯云服务器不知道从哪下手的,这篇应该能帮你少走不少弯路。
整篇会围绕几个核心展开:为什么在腾讯云上做实时数仓、整体架构怎么设计、核心组件怎么选型与部署、离线实时两条链路怎么落地,以及我在实际运维中遇到的典型问题和排查思路。不绕弯子,直接上干货。
1. 整体架构与设计思路:为什么选择腾讯云自建这套实时数仓
先交代一下背景。我这次的业务场景是典型的互联网实时分析需求:用户行为日志实时接入、订单数据实时汇总、核心指标实时大屏展示,同时还需要支撑多维度的即席查询。数据量不算夸张,日均亿级条目的日志量,峰值QPS大概在几万这个量级,但对实时性和稳定性要求不低。
当时摆在面前的有两条路:一是用云厂商提供的全托管实时数仓产品,开箱即用;二是自己基于云服务器搭建开源大数据生态。我最终选择了后者,在腾讯云服务器上自建了这套实时数仓。原因有三点:
第一是成本可控。全托管产品按量计费,长期跑下来费用不低,尤其是当你的集群需要24小时不间断运行时,自建的包年包月模式明显更划算。
第二是灵活度高。自建意味着我可以完全掌控每个组件的版本和配置,比如Flink CDC的并发度、Kafka的分区数、Doris的Bucket数量,这些参数在全托管平台上往往受限,而在自建环境下可以自由调整。
第三是为了学习和沉淀。这套系统不光是支撑业务,也是我个人技术栈的一次完整实践。从零搭建一套实时数仓,对理解整个大数据的链路非常有帮助。
整体架构上,我采用了经典的Lambda架构加Kappa架构的混合形态:实时链路走 Flink + Kafka + Doris,离线链路走 Spark + Hive + ClickHouse,两条链路的数据最终在服务层汇合,通过统一的查询接口对外提供服务。数据源则统一接入,包括业务数据库的Binlog、应用服务器的访问日志、以及第三方API回调的数据。
在选型上,有一个点想重点说明:为什么最终选择了Doris作为实时链路的存储层。其实在选型初期,我在Doris和ClickHouse之间犹豫了很久。两者都是优秀的OLAP引擎,性能都很强。ClickHouse在单表查询和聚合分析上极具优势,尤其是它的MergeTree系列表引擎,压缩比和查询速度都非常出色。但它在多表Join、数据更新、以及高并发点查方面相对薄弱。而Doris在整体架构上更接近传统MPP数据库,支持标准SQL,具备良好的多表Join能力,而且它的Unique Key模型天然支持实时数据更新,配合Flink Doris Connector,可以实现秒级的数据同步和更新。考虑到我的业务中有不少需要实时更新的场景,比如订单状态的流转、用户画像的标签更新,Doris更适合作为实时数仓的存储层。ClickHouse则被我用作离线分析场景的主力引擎,和Spark配合跑T+1的批量任务。
还有一点是集群规模的设计。我一开始就确定了要做成“能撑住业务、又不过度浪费资源”的配置:3台计算与存储混合节点跑Doris和ClickHouse,2台节点跑Kafka和Flink,1台节点跑调度和元数据服务,另外用1台轻量级服务器作为跳板机和监控。整体是6台腾讯云CVM,配置大致在8核16G到16核32G之间。这个规模处理当前的业务量绰绰有余,后期如果数据量增长,Doris和ClickHouse都支持横向扩展,扩容也比较方便。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心组件选型与部署要点:Kafka、Flink、Doris的搭配细节
这一节是实操的重头戏。组件选型是一回事,真正部署起来又是另一回事。我在实际搭建过程中踩了不少坑,下面把核心组件的选型逻辑和部署要点一一拆解。
2.1 Kafka的部署与参数调优
Kafka在整个实时链路里起到的是消息缓冲和削峰填谷的作用。业务日志通过Filebeat或Flume采集后写入Kafka,Flink从Kafka消费数据。在选择Kafka版本时,我没有一味的追求最新版,而是选择了当时稳定性口碑最好的2.8.1版本,配合ZooKeeper 3.6.3使用。之所以没选Kafka 3.x,是因为3.x版本虽然已经逐步去ZooKeeper化,但KRaft模式在当时还不够成熟,生产环境下踩坑的概率比较大。稳定优先,这是我做技术选型时的一个重要原则。
部署Kafka时有几个关键参数值得重点说:
日志保留策略,也就是log.retention.hours和log.retention.bytes。如果保留时间太短,Flink任务宕机恢复时可能已经消费不到之前的消息,导致数据丢失;如果保留时间太长,磁盘占用又是个问题。我最终设置为保留48小时,同时设置单个分区的最大保留大小为10GB,双管齐下控制磁盘占用。
分区数的确定也值得细说。分区数直接影响Kafka的吞吐量和并行度,但并不是越多越好。分区太多会导致文件句柄过多、ZooKeeper压力增大,也会增加Flink的checkpoint开销。我的经验公式是:分区数 = max(目标吞吐量 / 单个分区吞吐量, Flink消费并行度)。我的场景是日均亿级消息量,峰值每秒大概3-5万条,单分区吞吐量按5000条/秒估算,再考虑到Flink的并行度设置,最终给核心topic设置了24个分区。这样既保证了吞吐量,又不会因为分区过多导致管理复杂。
还有一个容易忽略的坑是消息体大小。默认的message.max.bytes是1MB,看起来够用,但如果你的业务日志里包含了完整的请求报文甚至Base64编码的图片信息,单条消息很容易超过这个限制。我当时就遇到了这个问题,Flink任务反复报RecordTooLargeException,排查了半天才发现是Kafka默认限制的问题。后来将message.max.bytes调整到了10MB,同时将Broker端的replica.fetch.max.bytes也一并调大,问题才彻底解决。
2.2 Flink部署与Checkpoint配置心得
Flink是实时链路的核心计算引擎。我使用的是Flink 1.15.2版本,部署模式选择了YARN Per-Job模式,每个实时任务单独申请一个YARN Application,任务之间互不影响,隔离性比较好。如果你对资源利用率有更高要求,也可以考虑Application模式,多个任务共享一个集群,但隔离性会差一些,运维起来也稍复杂
