2. 环境搭建与集群部署:打好实时数仓的地基

说实话,很多同学做实时数仓项目,上来就写代码,结果跑起来各种报错。我见过最夸张的一次,一个团队花了三周排查 Kafka 丢数据的问题,最后发现是集群时钟不同步。嗯,环境搭建这事儿,看着基础,但坑是真不少。

这一章,我会带你从头搭一套完整的实时数仓底座。包括 Hadoop、Zookeeper、Kafka、Flink on YARN 和 ClickHouse。每个组件我都会给出生产级的配置建议,以及我踩过的坑。

核心原则:所有组件尽量用同一套时钟源(NTP),主机名解析用 /etc/hosts 别用 DNS,数据盘单独挂载不要用系统盘。

实时数仓集群部署架构图 实时数仓集群部署架构 Hadoop HDFS / YARN 资源管理与分布式存储 Zookeeper 分布式协调服务 Kafka 消息队列 / 数据总线 Flink on YARN 实时计算引擎(Session / Per-Job 模式) ClickHouse OLAP 实时分析引擎 💡 部署顺序: Hadoop → Zookeeper → Kafka → Flink on YARN → ClickHouse 每个组件启动后先验证健康状态,再部署下一个,不要一口气全装完再排查。

2.1 Hadoop 集群搭建

Hadoop 是底座中的底座。HDFS 存数据,YARN 管资源。我个人习惯用 Apache 发行版,不搞 CDH 那套,原因很简单——升级灵活,不受厂商绑架。

2.1.1 节点规划

我建议至少 3 台机器。别用 1 台伪分布式糊弄,生产环境 replica 为 3,你只有 1 台,数据丢了都没地方哭。

节点角色主机名配置建议
NameNode + ResourceManagernn0116C / 64G / 500G SSD
DataNode + NodeManager × 2dn01, dn0216C / 128G / 4T × 4 HDD
SecondaryNameNodesnn018C / 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.partitions3-6Topic 默认分区数,根据吞吐量调整
default.replication.factor3副本数,保证高可用
log.retention.hours72日志保留 3 天,太长占磁盘
log.segment.bytes10737418241GB 一个段文件,方便清理
# 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 在这里只负责元数据同步,不存数据。

组件数量说明
Shard2数据分片,每个 Shard 存一部分数据
Replica2每个 Shard 有 2 个副本,保证高可用
Zookeeper3用于副本间元数据同步

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% 的排查时间。

  1. HDFS:上传一个文件,用 hdfs dfs -ls 确认副本数为 3。
  2. YARN:跑一个 sleep 任务,看 ResourceManager UI 上节点状态是否正常。
  3. Zookeeper:用 zkCli.sh 连上去,执行 stat / 看 Leader 是否选举成功。
  4. Kafka:创建一个 Topic,用 console-producer 和 console-consumer 测试收发消息。
  5. Flink:提交一个简单的 WordCount 作业,看 YARN 上是否正常启动和运行。
  6. ClickHouse:在任意节点创建分布式表,插入数据,查询确认数据分布到所有 Shard。

最后说一句:环境搭建这事儿,慢就是快。每个组件启动后,花 5 分钟验证一下健康状态,比后面花 5 小时排查问题划算得多。我见过太多人图快,结果集群跑了一个月才发现 DataNode 的磁盘挂载错了,数据全写到了系统盘。