
简介这是一份面向大数据初学者的系统性入门学习资源覆盖Hadoop、Hive、Spark、Storm、Flink、HBase、Kafka、ZooKeeper、Flume等主流组件聚焦环境搭建、核心命令、集群管理、数据查询、分区与视图等实操要点帮助零基础学习者快速构建完整技术栈认知并完成本地实验验证。资源包共629个文件以380张原理/操作示意图png/jpg、101篇结构化Markdown笔记含学习路线、思维导图、安装指南、配置详解、69个Java工具类与测试代码如HBaseUtils、HdfsTest为主辅以XML配置、Scala示例及JSON/Parquet等数据样例整体20.75MB轻量易下载。已有154人学习下载内容组织清晰从技术选型对比切入到单机/伪分布式部署再到典型SQL查询与数据流转链路实践配套代码可直接运行笔记覆盖常见报错与调优提示是兼顾理论梳理与动手验证的高实用性入门套件。1. 这不是“学完八件套就能进大厂”的速成课而是用 Hadoop、Hive、Spark、Flink 等组件搭出真实数据流水线的实操起点很多人点开“大数据入门指南”时期待的是一个带图形界面、三步装好、跑通 WordCount 就算通关的玩具环境。但现实是你在生产环境看到的每一条用户行为日志、每一笔实时订单、每小时聚合的销售报表背后都由 Hadoop 存储原始数据、ZooKeeper 协调服务状态、Kafka 承接高吞吐写入、Flink 或 Spark Streaming 做实时计算、Hive 或 Spark SQL 提供即席查询能力、HBase 支撑低延迟随机读写——它们不是并列选项而是按数据时效性、一致性、吞吐量需求分层咬合的齿轮。本指南不讲“哪个框架最火”只聚焦一件事如何让这八个组件在一台 16GB 内存的开发机上形成最小可行闭环——能从本地文件或模拟日志出发经 Kafka 入队被 Flink 实时清洗并写入 HBase同时用 Hive 建表映射同一份 HDFS 数据再用 Spark SQL 跑离线统计全程可验证、可调试、可查日志。适合刚脱离单机 Python 数据分析、正准备接触企业级数据平台的工程师也适合需要快速搭建教学实验环境的高校教师。2. 用 Docker Compose 拉起最小可用集群Hadoop ZooKeeper Kafka HBase 四件套联动要避免“先配 JDK、再改 hosts、再同步时间、再反复格式化 NameNode”的传统陷阱必须把环境依赖收束到容器层。Hadoop 3.3.6、ZooKeeper 3.8.3、Kafka 3.6.1、HBase 2.4.18 这组版本在社区验证充分且彼此兼容性明确——比如 Kafka 的advertised.listeners必须指向容器内网关地址而非 localhostHBase 的hbase.zookeeper.quorum必须填 ZooKeeper 容器名而非 IP。我们不用手动写 200 行 YAML而是基于 Confluent 官方 Kafka 镜像、Apache 官方 HBase 镜像配合自定义 Hadoop 配置构建轻量组合。2.1 编写 docker-compose.yml声明服务依赖与网络拓扑version: 3.8 services: zoo1: image: zookeeper:3.8.3 hostname: zoo1 container_name: zoo1 ports: - 2181:2181 environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1zoo1:2888:3888;2181 server.2zoo2:2888:3888;2181 server.3zoo3:2888:3888;2181 zoo2: image: zookeeper:3.8.3 hostname: zoo2 container_name: zoo2 environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1zoo1:2888:3888;2181 server.2zoo2:2888:3888;2181 server.3zoo3:2888:3888;2181 zoo3: image: zookeeper:3.8.3 hostname: zoo3 container_name: zoo3 environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1zoo1:2888:3888;2181 server.2zoo2:2888:3888;2181 server.3zoo3:2888:3888;2181 namenode: image: bde2020/hadoop-namenode:3.3.6 container_name: namenode volumes: - ./hadoop/namenode:/hadoop/dfs/name environment: - CLUSTER_NAMEtest ports: - 9870:9870 - 8020:8020 depends_on: - zoo1 - zoo2 - zoo3 datanode: image: bde2020/hadoop-datanode:3.3.6 container_name: datanode volumes: - ./hadoop/datanode:/hadoop/dfs/data environment: - CORE_SITE_XML_FS_DEFAULTFShdfs://namenode:8020 - HDFS_SITE_XML_DFS_NAMENODE_SECONDARY_HTTP_ADDRESSnamenode:9868 depends_on: - namenode - zoo1 - zoo2 - zoo3 kafka: image: confluentinc/cp-kafka:3.6.1 container_name: kafka ports: - 9092:9092 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,EXTERNAL:PLAINTEXT KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,EXTERNAL://localhost:9092 KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092 KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 depends_on: - zoo1 - zoo2 - zoo3 hbase-master: image: harisekhon/hbase:2.4.18 container_name: hbase-master ports: - 16010:16010 - 16000:16000 environment: HBASE_MASTER_OPTS: -Djava.security.krb5.conf/etc/krb5.conf HBASE_REGIONSERVER_OPTS: -Djava.security.krb5.conf/etc/krb5.conf HBASE_MANAGES_ZK: false HBASE_ZOOKEEPER_QUORUM: zoo1,zoo2,zoo3 HBASE_ZOOKEEPER_CLIENT_PORT: 2181 depends_on: - zoo1 - zoo2 - zoo3 - namenode - datanode hbase-regionserver: image: harisekhon/hbase:2.4.18 container_name: hbase-regionserver environment: HBASE_MASTER_OPTS: -Djava.security.krb5.conf/etc/krb5.conf HBASE_REGIONSERVER_OPTS: -Djava.security.krb5.conf/etc/krb5.conf HBASE_MANAGES_ZK: false HBASE_ZOOKEEPER_QUORUM: zoo1,zoo2,zoo3 HBASE_ZOOKEEPER_CLIENT_PORT: 2181 depends_on: - hbase-master - namenode - datanode提示HBASE_MANAGES_ZK: false是关键——HBase 不再启动自己的 ZooKeeper而是复用已有的三节点集群避免端口冲突和会话不一致。KAFKA_ADVERTISED_LISTENERS中EXTERNAL://localhost:9092保证宿主机上的生产者/消费者能连上容器内 Kafka而PLAINTEXT://kafka:9092供其他容器如 Flink内部通信。2.2 启动并验证四件套连通性执行docker-compose up -d后等待约 90 秒逐项验证# 查看所有容器状态 docker-compose ps # 进入 namenode 容器检查 HDFS 是否可写 docker exec -it namenode hdfs dfs -mkdir /test docker exec -it namenode hdfs dfs -ls / # 进入 kafka 容器创建测试 topic 并发送一条消息 docker exec -it kafka kafka-topics.sh --create --topic test-log --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1 docker exec -it kafka kafka-console-producer.sh --topic test-log --bootstrap-server localhost:9092 EOF {user_id:U1001,event:click,ts:1717023456} EOF # 在另一终端消费该消息需另开 shell docker exec -it kafka kafka-console-consumer.sh --topic test-log --bootstrap-server localhost:9092 --from-beginning --max-messages 1若kafka-console-consumer成功输出 JSON 字符串说明 Kafka → ZooKeeper → HDFS 三层链路已通。此时hbase-master的 Web UIhttp://localhost:16010应显示1 live regionserver且Status标签页中ZooKeeper Quorum显示zoo1:2181,zoo2:2181,zoo3:2181—— 这证明 HBase 已正确连接外部 ZooKeeper。2.3 关键配置参数表为什么这些值不能乱改组件配置项推荐值作用说明错误设置后果KafkaKAFKA_ADVERTISED_LISTENERSPLAINTEXT://kafka:9092,EXTERNAL://localhost:9092定义 Broker 对内容器间和对外宿主机的监听地址若只写localhostFlink 任务无法连接若漏掉EXTERNAL本地脚本 producer 失败HBaseHBASE_ZOOKEEPER_QUORUMzoo1,zoo2,zoo3指向 ZooKeeper 集群域名列表若填localhost或127.0.0.1HBase 容器无法解析RegionServer 启动失败Hadoopfs.defaultFShdfs://namenode:8020HDFS 默认文件系统 URI若写hdfs://localhost:8020Kafka Connect 或 Flink 无法访问 HDFSZooKeeperZOO_SERVERSserver.1zoo1:2888:3888;2181 ...集群节点发现协议若 ID 重复或端口错位ZooKeeper 启动后立即退出日志报QuorumPeerMain错误3. 让 Hive 和 Spark 接入同一份 HDFS 数据统一元数据与计算引擎Hive 不是“SQL on HDFS”的简单翻译器而是通过 Metastore 服务将表结构、分区信息、存储路径持久化到关系型数据库如 Derby 或 MySQL再由 Execution EngineTez/Spark执行物理计划。Spark 则通过spark.sql.hive.thriftServer.enabledtrue直接复用 Hive Metastore实现跨引擎元数据共享——这才是“Hive Spark”协同的真实含义而非各自建表。3.1 初始化 Hive Metastore用 Derby 嵌入式数据库快速启动Hive 3.1.3 官方镜像默认使用 Derby无需额外部署 MySQL。我们只需挂载配置目录并确保hive-site.xml正确指向 HDFS 和 ZooKeeper# 创建 hive 配置目录 mkdir -p ./hive/conf # 生成 hive-site.xml关键字段已标注 cat ./hive/conf/hive-site.xml EOF ?xml version1.0? ?xml-stylesheet typetext/xsl hrefconfiguration.xsl? configuration property namejavax.jdo.option.ConnectionURL/name valuejdbc:derby:./metastore_db;createtrue/value descriptionmetastore 本地 Derby 数据库存储路径/description /property property namehive.metastore.warehouse.dir/name valuehdfs://namenode:8020/user/hive/warehouse/value descriptionHive 默认仓库根目录必须是 HDFS 路径/description /property property namehive.zookeeper.quorum/name valuezoo1,zoo2,zoo3/value descriptionZooKeeper 地址用于 HiveServer2 高可用/description /property property namefs.defaultFS/name valuehdfs://namenode:8020/value description强制 Hive 使用 Hadoop 配置避免本地文件系统误用/description /property /configuration EOF注意hive.metastore.warehouse.dir必须以hdfs://开头且路径需在 HDFS 上存在。启动前需执行docker exec -it namenode hdfs dfs -mkdir -p /user/hive/warehouse docker exec -it namenode hdfs dfs -chmod 777 /user/hive/warehouse3.2 启动 HiveServer2 并建表映射 Kafka 日志启动 HiveServer2HS2服务它提供 JDBC/ODBC 接口供 Spark 和 BI 工具连接# 启动 HS2后台运行 docker run -d \ --name hive-server2 \ --network docker-compose_default \ -v $(pwd)/hive/conf:/opt/hive/conf \ -p 10000:10000 \ -e HIVE_SERVER2_THRIFT_PORT10000 \ -e HIVE_SERVER2_THRIFT_BIND_HOST0.0.0.0 \ -e HIVE_METASTORE_URIthrift://namenode:9083 \ apache/hive:3.1.3 \ /opt/hive/bin/hiveserver2 # 进入容器执行建表语句模拟 Kafka 日志存入 HDFS 后的 Hive 表 docker exec -it hive-server2 beeline -u jdbc:hive2://localhost:10000 -n hive -p hive -e CREATE EXTERNAL TABLE IF NOT EXISTS user_log ( user_id STRING, event STRING, ts BIGINT ) ROW FORMAT SERDE org.apache.hive.hcatalog.data.JsonSerDe LOCATION hdfs://namenode:8020/user/logs/; 此表为EXTERNAL意味着删除表仅删元数据不删 HDFS 上原始数据——符合数仓分层设计原则。JsonSerDe解析器能自动将{user_id:U1001,event:click,ts:1717023456}映射为三列。3.3 Spark SQL 复用 Hive Metastore一行命令启用跨引擎查询Spark 3.3.2 默认支持 Hive 元数据集成。只需在spark-defaults.conf中指定 Metastore URI并确保spark-sql命令行工具能访问 HDFS 和 ZooKeeper# 启动 Spark SQL CLI自动加载 Hive 表 docker run -it \ --network docker-compose_default \ -v $(pwd)/hive/conf:/opt/spark/conf \ --entrypoint /opt/spark/bin/spark-sql \ apache/spark:3.3.2-hadoop3.3 \ --master local[*] \ --conf spark.sql.hive.metastore.uristhrift://namenode:9083 \ --conf spark.hadoop.fs.defaultFShdfs://namenode:8020 \ --conf spark.sql.hive.hiveserver2.jdbc.urljdbc:hive2://namenode:10000进入交互式 SQL 环境后直接执行-- 查看 Hive 中已注册的表 SHOW TABLES; -- 查询 user_log 表数据实际来自 HDFS SELECT event, COUNT(*) AS cnt FROM user_log GROUP BY event; -- 创建新表Spark 自动写入 Hive Metastore CREATE TABLE top_users AS SELECT user_id, COUNT(*) AS click_cnt FROM user_log WHERE event click GROUP BY user_id ORDER BY click_cnt DESC LIMIT 10;逻辑说明spark.sql.hive.metastore.uristhrift://namenode:9083告诉 Spark 去连接 Hive Metastore 服务需提前启动 Hive Metastore Thrift Serverspark.sql.hive.hiveserver2.jdbc.url则用于后续 JDBC 查询。若未启动 Metastore Thrift ServerSpark 会 fallback 到本地 Derby但无法与 HiveServer2 共享表。4. Flink 实时消费 Kafka 并写入 HBase从流式 ETL 到低延迟查询Flink 1.18 的flink-connector-hbase和flink-connector-kafka已稳定支持 Exactly-Once 语义。关键不在“能不能写”而在“怎么保证 HBase RowKey 设计不导致热点”、“Kafka 分区数与 Flink Source 并行度如何对齐”、“HBase 写入失败时如何触发 checkpoint 回滚”。4.1 编写 Flink DataStream JobJSON 解析 RowKey 生成 HBase Put以下 Java 代码片段可打包为 fat-jar 提交完成核心逻辑// pom.xml 中引入依赖 // dependency // groupIdorg.apache.flink/groupId // artifactIdflink-connector-kafka/artifactId // version1.18.0/version // /dependency // dependency // groupIdorg.apache.flink/groupId // artifactIdflink-connector-hbase/artifactId // version1.18.0/version // /dependency public class KafkaToHBase { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env StreamExecutionEnvironment.getExecutionEnvironment(); env.enableCheckpointing(5000); // 5秒 checkpoint 间隔 // 从 Kafka 读取 JSON 日志 Properties props new Properties(); props.setProperty(bootstrap.servers, kafka:9092); props.setProperty(group.id, flink-hbase-group); props.setProperty(auto.offset.reset, latest); FlinkKafkaConsumerString consumer new FlinkKafkaConsumer( test-log, new SimpleStringSchema(), props ); consumer.setStartFromLatest(); DataStreamString kafkaStream env.addSource(consumer); // 解析 JSON生成 HBase RowKey按 user_id hash 分散写入 DataStreamPut hbasePuts kafkaStream .map(json - { JSONObject obj new JSONObject(json); String userId obj.getString(user_id); String event obj.getString(event); long ts obj.getLong(ts); // RowKey md5(user_id) _ ts避免 user_id 热点 String rowKey DigestUtils.md5Hex(userId) _ ts; Put put new Put(Bytes.toBytes(rowKey)); put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(user_id), Bytes.toBytes(userId)); put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(event), Bytes.toBytes(event)); put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(ts), Bytes.toBytes(ts)); return put; }); // 写入 HBase Configuration hbaseConf HBaseConfiguration.create(); hbaseConf.set(hbase.zookeeper.quorum, zoo1,zoo2,zoo3); hbaseConf.set(hbase.zookeeper.property.clientPort, 2181); hbaseConf.set(hbase.master, hbase-master:16000); hbasePuts.addSink(new HBaseSinkFunction(user_log_table, hbaseConf)); env.execute(Kafka-to-HBase); } }参数说明DigestUtils.md5Hex(userId)将用户 ID 哈希为 32 位字符串与时间戳拼接构成 RowKey既保证唯一性又打散写入压力hbase.zookeeper.quorum必须与docker-compose.yml中 ZooKeeper 服务名一致hbase.master指向 HBase Master 容器名及端口而非 localhost。4.2 在 HBase Shell 中验证实时写入结果提交 Flink 任务后向 Kafka 发送多条消息# 发送 3 条不同 user_id 的日志 echo {user_id:U1001,event:view,ts:1717023500} | docker exec -i kafka kafka-console-producer.sh --topic test-log --bootstrap-server localhost:9092 echo {user_id:U1002,event:buy,ts:1717023501} | docker exec -i kafka kafka-console-producer.sh --topic test-log --bootstrap-server localhost:9092 echo {user_id:U1003,event:share,ts:1717023502} | docker exec -i kafka kafka-console-producer.sh --topic test-log --bootstrap-server localhost:9092然后进入 HBase 容器查询docker exec -it hbase-master hbase shell # 在 HBase shell 中执行 list # 查看是否有 user_log_table scan user_log_table, {LIMIT3} # 扫描前 3 行 get user_log_table, c4ca4238a0b923820dcc509a6f75849b_1717023500 # 根据 RowKey 精确查询若scan返回三行含user_id、event、ts列的数据则证明 Flink 流式管道已打通 Kafka → Flink → HBase 全链路。4.3 Storm 与 Flink 的定位差异何时该选 Storm尽管标题包含 Storm但在当前技术栈中Storm 1.3 已基本被 Flink 取代。Storm 的优势场景仅剩两类超低延迟硬实时要求端到端延迟 100ms且能接受 At-Least-Once 语义如高频交易风控复杂 DAG 拓扑需动态分支、条件路由、状态跨 bolt 共享如多级规则引擎。而 Flink 在Exactly-Once 语义保障、事件时间窗口、状态后端容错、SQL 层统一上全面胜出。因此本指南中 Storm 不作为必选组件仅在docker-compose.yml中预留占位注释掉若需启用只需取消注释并添加storm-nimbus、storm-supervisor服务其 ZooKeeper 依赖已由现有集群提供。5. Hive 修改表名、Spark DataFrame 优化、Flink SQL Watermark三个高频实战技巧这三个操作看似零散实则直击日常运维痛点Hive 表重命名常因权限或锁表失败Spark DataFrame 内存溢出是新手最常遇到的“黑盒崩溃”Flink SQL 的 Watermark 设置错误会导致窗口计算结果缺失或延迟。它们不构成完整流程却是每天都会敲的命令。5.1 Hive 修改表名的 SQL 语句绕过 rename 命令的权限陷阱Hive CLI 的ALTER TABLE old_name RENAME TO new_name在启用 Sentry 或 Ranger 权限控制时可能失败。更可靠的方式是用CREATE TABLE ... LIKEINSERT OVERWRITE组合-- 步骤1创建新表结构含分区、存储格式等 CREATE TABLE user_log_v2 LIKE user_log; -- 步骤2将旧表全量数据写入新表自动继承分区 INSERT OVERWRITE TABLE user_log_v2 PARTITION (dt20240530) SELECT * FROM user_log WHERE dt20240530; -- 步骤3删除旧表元数据HDFS数据 DROP TABLE user_log; -- 步骤4重命名新表仅元数据操作无数据移动 ALTER TABLE user_log_v2 RENAME TO user_log;注意CREATE TABLE ... LIKE复制表结构但不复制数据INSERT OVERWRITE会清空目标分区再写入确保一致性最后RENAME是轻量元数据操作成功率近 100%。5.2 Spark DataFrame 内存溢出的 3 个必调参数当spark-submit报java.lang.OutOfMemoryError: Java heap space或ExecutorLostFailure不要盲目加内存先检查以下参数参数推荐值作用调整依据spark.sql.adaptive.enabledtrue启用自适应查询执行AQE自动合并小分区、优化 Join 策略Spark 3.0 默认关闭开启后可减少 shuffle 文件数spark.sql.adaptive.coalescePartitions.enabledtrueAQE 下自动合并小分区避免大量 task 启动开销当numTasks 2000 且平均 input size 128MB 时启用spark.sql.files.maxPartitionBytes268435456256MB控制每个 partition 最大字节数影响初始分区数HDFS 块大小为 128MB设为 256MB 可平衡并行度与 task 数量提交命令示例spark-submit \ --conf spark.sql.adaptive.enabledtrue \ --conf spark.sql.adaptive.coalescePartitions.enabledtrue \ --conf spark.sql.files.maxPartitionBytes268435456 \ --class com.example.AnalyzeJob \ app.jar5.3 Flink SQL 中 Watermark 的两种写法与验证方法Watermark 是事件时间窗口的“心跳信号”错误设置会导致数据丢失。Flink SQL 提供两种声明方式方式一在 DDL 中定义推荐语义清晰CREATE TABLE kafka_source ( user_id STRING, event STRING, ts BIGINT, WATERMARK FOR ts AS ts - INTERVAL 5 SECOND ) WITH ( connector kafka, topic test-log, properties.bootstrap.servers kafka:9092, format json ); -- 后续窗口查询自动使用该 Watermark SELECT TUMBLING_START(ts, INTERVAL 1 MINUTE) AS window_start, COUNT(*) AS cnt FROM kafka_source GROUP BY TUMBLING(ts, INTERVAL 1 MINUTE);方式二在 INSERT SELECT 中显式指定调试用INSERT INTO hbase_sink SELECT user_id, event, ts, WATERMARK FOR ts AS ts - INTERVAL 5 SECOND FROM kafka_source;验证 Watermark 是否生效查看 Flink Web UIhttp://localhost:8081→ “Task Managers” → 点击任意 TaskManager → “Metrics” → 搜索watermark观察currentWatermark是否随事件时间递增若currentWatermark长时间停滞如卡在1717023000000说明 Kafka 中无新事件或ts字段为空/非法需检查 JSON 解析逻辑。关键提醒WATERMARK FOR ts AS ts - INTERVAL 5 SECOND中的5 SECOND是最大乱序容忍时间必须大于等于数据源实际乱序程度。若设为1 SECOND而实际乱序达 10 秒则窗口会提前触发丢失 late data。本文还有配套的精品资源点击获取