2. 环境搭建与集群部署:打好实时数仓的地基
说实话,很多同学做实时数仓项目,上来就写代码,结果跑起来各种报错。我见过最夸张的一次,一个团队花了三周排查 Kafka 丢数据的问题,最后发现是集群时钟不同步。嗯,环境搭建这事儿,看着基础,但坑是真不少。
这一章,我会带你从头搭一套完整的实时数仓底座。包括 Hadoop、Zookeeper、Kafka、Flink on YARN 和 ClickHouse。每个组件我都会给出生产级的配置建议,以及我踩过的坑。
核心原则:所有组件尽量用同一套时钟源(NTP),主机名解析用 /etc/hosts 别用 DNS,数据盘单独挂载不要用系统盘。
2.1 Hadoop 集群搭建
Hadoop 是底座中的底座。HDFS 存数据,YARN 管资源。我个人习惯用 Apache 发行版,不搞 CDH 那套,原因很简单——升级灵活,不受厂商绑架。
2.1.1 节点规划
我建议至少 3 台机器。别用 1 台伪分布式糊弄,生产环境 replica 为 3,你只有 1 台,数据丢了都没地方哭。
| 节点角色 | 主机名 | 配置建议 |
|---|---|---|
| NameNode + ResourceManager | nn01 | 16C / 64G / 500G SSD |
| DataNode + NodeManager × 2 | dn01, dn02 | 16C / 128G / 4T × 4 HDD |
| SecondaryNameNode | snn01 | 8C / 32G / 500G SSD |
我的经验:NameNode 内存给够,64G 起步。我曾经遇到过 NameNode 堆内存只有 16G,管理 5000 万个文件块直接 OOM,集群挂了半天才恢复。
2.1.2 核心配置
配置文件就三个:core-site.xml、hdfs-site.xml、yarn-site.xml。别被吓到,核心参数其实没几个。
<!-- core-site.xml -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://nn01:8020</value>
</property>
<!-- hdfs-site.xml -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
<!-- yarn-site.xml -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>114688</value> <!-- 112GB -->
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>32768</value> <!-- 单个 Container 最大 32GB -->
</property>
⚠️ 注意:yarn.nodemanager.resource.memory-mb 不要设成物理内存的 100%,留 10%-15% 给操作系统和系统进程。我见过有人设满 128G,结果 NodeManager 刚启动就被 OOM Killer 干掉了。
2.2 Zookeeper 集群部署
Zookeeper 是 Kafka 和 HBase 的命根子。它挂了,整个实时链路就断了。我习惯部署奇数台,3 台起步,5 台撑死。
2.2.1 安装与配置
Zookeeper 配置极其简单,核心就一个 zoo.cfg。
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper
clientPort=2181
server.1=zk01:2888:3888
server.2=zk02:2888:3888
server.3=zk03:2888:3888
然后在 dataDir 目录下创建 myid 文件,内容就是对应的 server ID。比如 zk01 的 myid 写 1。
避坑指南:我曾经把 dataDir 设在系统盘 /tmp 下,重启后 myid 文件丢了,Zookeeper 起不来。后来我统一把数据目录挂载到独立的数据盘,再也没出过这问题。
2.3 Kafka 集群部署
Kafka 是实时数仓的数据总线。说白了,所有数据都从它这过。我个人习惯用 2.8+ 版本,支持 Raft 模式,可以不依赖 Zookeeper。但生产环境我还是建议用 Zookeeper 模式,稳定。
2.3.1 关键参数
| 参数 | 推荐值 | 说明 |
|---|---|---|
| num.partitions | 3-6 | Topic 默认分区数,根据吞吐量调整 |
| default.replication.factor | 3 | 副本数,保证高可用 |
| log.retention.hours | 72 | 日志保留 3 天,太长占磁盘 |
| log.segment.bytes | 1073741824 | 1GB 一个段文件,方便清理 |
# server.properties 核心配置
broker.id=1
listeners=PLAINTEXT://kafka01:9092
log.dirs=/data/kafka/logs
zookeeper.connect=zk01:2181,zk02:2181,zk03:2181/kafka
⚠️ 注意:log.dirs 不要用 RAID 0,用多块盘独立挂载。Kafka 自己会做数据均衡。我曾经用 RAID 0 坏一块盘整个 Broker 废了,恢复数据花了整整两天。
2.4 Flink on YARN 模式部署
Flink 部署方式有好几种,Standalone、Kubernetes、YARN。我个人最推荐 YARN 模式。为什么?因为 YARN 帮你管资源,你不用操心 TaskManager 的分配和回收。
2.4.1 两种运行模式
- Session 模式:先启动一个 Flink 集群在 YARN 上,然后往里面提交作业。适合短作业、测试环境。
- Per-Job 模式:每个作业单独启动一个 Flink 集群,作业结束集群自动释放。适合生产环境,资源隔离好。
我生产环境一律用 Per-Job 模式。Session 模式一旦某个作业内存泄漏,整个集群都受影响。这事儿我吃过亏。
2.4.2 提交命令示例
./bin/flink run \
-m yarn-cluster \
-yjm 2048 \
-ytm 8192 \
-ys 4 \
-p 8 \
-c com.example.RealTimeETL \
/path/to/job.jar
参数说明:-yjm 是 JobManager 内存,-ytm 是 TaskManager 内存,-ys 是每个 TaskManager 的 Slot 数,-p 是并行度。我一般让 Slot 数等于 CPU 核数,并行度是 Slot 总数的 2-3 倍。
2.5 ClickHouse 集群部署
ClickHouse 是实时数仓的最后一环,负责 OLAP 查询。它不走 Zookeeper 那套,而是用自己的一套分布式方案。
2.5.1 集群架构
ClickHouse 集群由多个分片(Shard)组成,每个分片有多个副本(Replica)。Zookeeper 在这里只负责元数据同步,不存数据。
| 组件 | 数量 | 说明 |
|---|---|---|
| Shard | 2 | 数据分片,每个 Shard 存一部分数据 |
| Replica | 2 | 每个 Shard 有 2 个副本,保证高可用 |
| Zookeeper | 3 | 用于副本间元数据同步 |
2.5.2 配置示例
<!-- config.xml 核心配置 -->
<remote_servers>
<my_cluster>
<shard>
<replica>
<host>ch01</host>
<port>9000</port>
</replica>
<replica>
<host>ch02</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>ch03</host>
<port>9000</port>
</replica>
<replica>
<host>ch04</host>
<port>9000</port>
</replica>
</shard>
</my_cluster>
</remote_servers>
⚠️ 注意:ClickHouse 的 Zookeeper 和 Kafka 的 Zookeeper 可以共用,但建议分开。我曾经在一个 ZK 集群上同时挂了 Kafka 和 ClickHouse,结果 ClickHouse 的副本同步把 ZK 压力拉满,Kafka 的 Controller 选举超时,整个实时链路断了 40 分钟。
2.6 集群验证清单
所有组件部署完后,别急着写代码。按这个清单验证一遍,能省你后面 80% 的排查时间。
- HDFS:上传一个文件,用 hdfs dfs -ls 确认副本数为 3。
- YARN:跑一个 sleep 任务,看 ResourceManager UI 上节点状态是否正常。
- Zookeeper:用 zkCli.sh 连上去,执行 stat / 看 Leader 是否选举成功。
- Kafka:创建一个 Topic,用 console-producer 和 console-consumer 测试收发消息。
- Flink:提交一个简单的 WordCount 作业,看 YARN 上是否正常启动和运行。
- ClickHouse:在任意节点创建分布式表,插入数据,查询确认数据分布到所有 Shard。
最后说一句:环境搭建这事儿,慢就是快。每个组件启动后,花 5 分钟验证一下健康状态,比后面花 5 小时排查问题划算得多。我见过太多人图快,结果集群跑了一个月才发现 DataNode 的磁盘挂载错了,数据全写到了系统盘。