面试题 / 大数据

大数据面试题

Kafka 的 message 包括哪些信息?

一个 Kafka 消息通常可以概括为:

  • 固定长度头部
  • 变长消息体

头部中常见的元信息包括:

  • magic
  • CRC
  • 属性位

消息体里则是具体的 key/value 数据。

怎么查看 Kafka 的 offset?

不同版本和客户端方式不同。

常见思路:

  • 使用 Kafka 自带命令行工具
  • 使用消费者客户端 API
  • 在代码中结合 seekToEnd()position() 等接口查看

Hadoop 的 shuffle 过程是什么?

Shuffle 分为 Map 端和 Reduce 端两个阶段。

Map 端:

  1. 结果先写入内存缓冲区
  2. 达到阈值后 spill 到磁盘
  3. 排序、分区、可选 combiner
  4. 多个 spill 文件最终归并

Reduce 端:

  1. 从各个 Map 拉取对应分区数据
  2. 归并排序
  3. 交给 Reduce 逻辑处理

Spark 集群有哪些常见运行模式?

常见模式包括:

  • 本地模式
  • Standalone
  • Yarn
  • Mesos
  • Cloud 环境

实际生产里最常见的是:

  • Standalone
  • Yarn

HDFS 读写数据的过程是什么?

读流程:

  1. 客户端先向 NameNode 获取元数据
  2. 找到目标 block 所在的 DataNode
  3. 与 DataNode 建立连接
  4. 按 packet 接收数据

写流程:

  1. 客户端先请求 NameNode
  2. NameNode 返回目标 DataNode 列表
  3. 建立写入 pipeline
  4. 客户端按 packet 向 DataNode 链路写入数据

reduceByKeygroupByKey 哪个性能更好?为什么?

通常 reduceByKey 更好。

原因:

  • reduceByKey 会在 map 端先做局部聚合
  • 可显著减少网络传输量

groupByKey 会把更多原始数据直接拉到 reduce 端,容易造成:

  • 网络开销更大
  • 内存压力更高

Kafka 的数据存在内存还是磁盘?

Kafka 的核心设计是以磁盘为主,而不是只放内存。

原因包括:

  • 顺序读写磁盘性能很高
  • OS 页缓存会参与加速
  • 避免 JVM 堆过大导致 GC 问题
  • 数据持久化更可靠

如何解决 Kafka 数据丢失问题?

要分 Producer、Broker、Consumer 三端来看。

常见手段:

  • Producer 端开启确认机制
  • Broker 端做好副本和 ISR 配置
  • Consumer 端关闭自动提交,处理完成后再提交 offset

核心目标是保证:

  • 消息写入可靠
  • 消费确认时机正确

宽依赖和窄依赖有什么区别?

  • 窄依赖:父 RDD 的一个分区只会被子 RDD 的一个分区使用
  • 宽依赖:父 RDD 的分区会被多个子分区依赖

通常:

  • 宽依赖往往伴随 shuffle
  • 窄依赖更适合流水线执行

Spark Streaming 读取 Kafka 数据有哪些方式?

常见两种:

  1. Receiver-based
  2. Direct

通常更推荐 Direct 方式,因为:

  • offset 控制更清晰
  • 更容易做可靠性保障

设计题:如何采集海量 Nginx 日志并提供实时查询?

这是典型的日志采集和实时分析题。

常见链路:

  1. 日志采集:Logstash / Filebeat
  2. 消息缓冲:Kafka
  3. 实时计算:Spark Streaming / Flink
  4. 结果存储:Redis / Elasticsearch / OLAP 引擎
  5. 查询展示:报表或服务接口

如果要求 3 秒内查询响应,通常需要把统计结果提前聚合,而不是临时扫原始日志。

海量 Query 统计 Top K 应该怎么做?

这是经典 Top K 题。

常见思路:

  1. 先按 hash 分桶,把大文件拆成多个小文件
  2. 在每个桶内做词频统计
  3. 维护每个桶的局部 Top K
  4. 最后归并得到全局 Top K

如果机器内存足够,也可以直接用哈希表统计后再堆排序。

在海量整数中找出不重复的整数,内存不足怎么办?

经典做法之一是位图或 2-Bitmap。

例如:

  • 00:未出现
  • 01:出现一次
  • 10:出现多次

扫描完后,把状态为“只出现一次”的数输出即可。

给 40 亿个不重复的 unsigned int,如何快速判断某个数是否存在?

经典做法是位图(Bitmap)。

思路:

  1. 每个数对应一个 bit 位
  2. 读入数据后把对应 bit 置为 1
  3. 查询时直接看目标 bit 是否为 1

这种做法非常适合“海量整数 + 存在性判断”问题。

海量数据中如何找出重复次数最多的一个?

常见思路:

  1. 先 hash 分桶
  2. 每个桶内统计出现次数最多的元素
  3. 最后在所有桶结果中再比较一次

本质上仍然是“分治 + 统计 + 汇总”。

上亿数据中统计出现次数最多的前 N 个,怎么做?

典型套路:

  1. 哈希统计频次
  2. 用最小堆维护 Top N

如果数据过大无法一次放内存,就先分桶,再在每个桶里做局部统计。

一个文本文件中统计出现最频繁的前 10 个词,怎么做?

如果数据量不大,可以直接:

  1. 遍历文件
  2. 用哈希表统计词频
  3. 用最小堆维护前 10

如果题目强调超大数据量,则需要进一步考虑:

  • 分桶
  • 外排序
  • 分布式处理

100 万个数中找出最大的 100 个数,怎么做?

经典方法是维护一个大小为 100 的最小堆。

过程:

  1. 先用前 100 个数建堆
  2. 遍历剩余元素
  3. 如果新元素大于堆顶,就替换堆顶并调整堆

这样时间复杂度更可控。


来源引用