- HDFS 小文件过多会导致什么问题,怎么处理这个问
- 你是怎么考虑你的数据分层的
- spark 的懒加载机制
- HDFS 的主要组件是哪些
- union 和 union all 的区别是什么
- mysql的 binlog 日志
- 数据压缩机
- 项目里遇到的难点
答案如下:
1. HDFS 小文件过多会导致什么问题,怎么处理这个问题
考察知识点
- HDFS架构特性(元数据存储机制)
- 小文件对集群性能的影响
- 小文件治理的常用方案
参考回答
问题:
HDFS设计用于存储大文件(默认块大小128MB/256MB),小文件(远小于块大小)过多会引发两个核心问题:
- NameNode内存压力激增:NameNode将文件元数据(路径、块信息等)存储在内存中,每个文件约占150字节。若有1亿个小文件,元数据需占用约15GB内存,可能导致NameNode内存溢出,影响集群稳定性。
- 读写效率下降:小文件的寻址时间(定位块存储位置)远大于实际读写时间,且MapReduce/Spark处理时会生成大量小Task(每个小文件对应一个Task),导致Task调度开销远超计算开销,集群资源利用率降低。
处理方案:
- 离线合并:
- 用
Hadoop Archive(HAR)
:将多个小文件归档为一个HAR文件(元数据集中存储),减少NameNode内存占用(1万个小文件归档后元数据仅占约1KB),但不改变文件内容,适合冷数据归档。 - 批量合并为大文件:通过MapReduce/Spark任务,将同目录下的小文件合并为大文件(如按日期合并日志文件),写入HDFS时设置合理块大小(如128MB),适合热数据处理。
- 用
- 实时写入优化:
- 用
SequenceFile/ORC/Parquet
:将小文件按Key-Value结构写入SequenceFile,或用列存格式ORC/Parquet(支持块级压缩和合并),减少文件数量。例如,实时日志采集时,用Flink将10分钟内的小日志合并为一个ORC文件写入HDFS。
- 用
- 存储层适配:
- 小文件量极大时(如数十亿个),改用HBase存储:HBase将小文件按RowKey聚合存储在HFile中,元数据由HMaster和RegionServer管理,减轻NameNode压力,适合随机读写的小文件场景(如用户头像、小尺寸日志)。
- 源头控制:
- 数据采集端限制小文件生成:如Flume设置
batchSize
(批量写入,积累到一定大小再提交),Kafka设置log.segment.bytes
(控制日志段大小,避免频繁滚动生成小文件)。
- 数据采集端限制小文件生成:如Flume设置
注意要点
- 合并策略需区分“热数据”和“冷数据”:热数据(频繁查询)适合合并为大文件(提升读写效率),冷数据(归档)适合HAR(节省内存)。
- 避免过度合并:单个大文件不宜超过10GB(否则Map Task处理时拆分过多块,反而降低效率)。
2. 你是怎么考虑你的数据分层的
考察知识点
- 数据仓库分层逻辑(ODS/DWD/DWS/ADS)
- 分层设计的核心目的(复用、维护、性能)
- 分层与业务的结合
参考回答
数据分层的核心思路是“按数据加工粒度和用途拆分,实现数据复用、降低维护成本、提升查询效率”,结合实习项目,我采用经典的4层架构:
- ODS层(操作数据存储层):
- 定位:存储原始数据,完全保留数据源格式(如日志、业务库表),不做清洗,仅做格式转换(如JSON→Parquet)。
- 作用:作为数据入口,支持数据回溯(如原始日志异常时,可重新从ODS层加工)。
- 实例:用户行为日志(raw_log_${dt})、MySQL订单表同步数据(ods_order_${dt},通过Sqoop/CDC同步)。
- DWD层(数据明细层):
- 定位:对ODS层数据清洗、转换、脱敏,生成细粒度明细数据(一条记录对应一个具体行为/业务事件)。
- 核心操作:① 清洗(过滤空值、异常值,如user_id=null的日志);② 脱敏(手机号、身份证号加密);③ 关联(补充维度信息,如用user_id关联用户表,补充用户等级)。
- 作用:为上层提供干净、一致的明细数据,避免重复清洗。
- 实例:dwd_user_click_detail(用户点击明细,含清洗后的商品id、点击时间、用户等级)。
- DWS层(数据服务层/汇总层):
- 定位:按业务主题(如用户、商品、订单)聚合明细数据,生成中粒度汇总数据(如用户日活、商品周销量)。
- 聚合维度:时间(天/周/月)、业务实体(用户/商品/渠道)。
- 作用:减少上层查询的重复计算(如运营查“用户日活”可直接读DWS层,无需扫全量DWD明细)。
- 实例:dws_user_active_day(用户日活表,按user_id和dt聚合,标记是否活跃)。
- ADS层(应用数据层):
- 定位:面向具体业务需求(报表、dashboard、API),生成最终可直接使用的数据。
- 特点:数据粒度粗(如全平台月GMV)、格式适配应用(如JSON/CSV,供Superset/BI工具直接读取)。
- 实例:ads_gmv_month(月GMV报表,含各品类GMV占比)。
分层考虑因素:
- 业务需求:高频查询的指标(如实时GMV)在DWS层预聚合,低频复杂分析(如用户行为路径)直接基于DWD层。
- 性能:DWD/DWS层用ORC/Parquet压缩,按时间分区,提升查询效率;ODS层保留原始格式,便于回溯。
- 维护成本:每层职责明确,修改某层数据不影响其他层(如DWD清洗逻辑变更,仅需重新生成DWD及上层数据)。
注意要点
- 避免过度分层:中小规模业务可简化为ODS→DWD→ADS,避免层级冗余增加维护成本。
- 分层需“向上兼容”:上层数据必须完全由下层数据生成,确保数据血缘可追溯。
3. Spark 的懒加载机制
考察知识点
- Spark SQL中“转换操作”与“行动操作”的区分
- 懒加载的核心原理(逻辑计划构建与延迟执行)
- 懒加载在SQL场景中的优化逻辑(如执行计划优化、减少无效计算)
- 实际工作中对懒加载机制的验证与应用
参考回答
Spark的懒加载机制(Lazy Evaluation)是指在Spark SQL中,所有对数据的“转换操作”仅会记录逻辑处理步骤,不会立即执行计算;只有当遇到“行动操作”时,才会触发之前所有转换操作的实际执行。这一机制是Spark优化计算效率的核心特性,在SQL场景中表现如下:
(1)核心原理
- Spark SQL将操作分为两类:
- 转换操作(Transformation):对数据进行处理但不生成最终结果的操作(如
SELECT
、WHERE
、JOIN
、GROUP BY
等)。这类操作仅会被Spark解析为“逻辑计划”(记录“要做什么”),不实际读取数据或执行计算。 - 行动操作(Action):触发计算并生成结果的操作(如
SHOW
、COUNT
、INSERT INTO
、CREATE TABLE ... AS SELECT
等)。这类操作会触发Spark对之前所有转换操作的逻辑计划进行优化(如合并步骤、谓词下推),并生成物理计划(确定“如何执行”),最终提交任务到集群执行。
- 转换操作(Transformation):对数据进行处理但不生成最终结果的操作(如
(2)SQL场景示例
假设我们有一张用户行为表user_behavior
(含user_id
、age
、action
字段),需求是“筛选30岁以上用户的行为记录,并统计其数量”。
-- 步骤1:定义转换操作(仅记录逻辑计划,不执行)
-- 转换1:筛选30岁以上用户
CREATE OR REPLACE TEMPORARY VIEW filtered_users AS
SELECT user_id, action
FROM user_behavior
WHERE age > 30; -- WHERE属于转换操作
-- 转换2:按用户ID分组统计行为次数
CREATE OR REPLACE TEMPORARY VIEW user_action_cnt AS
SELECT user_id, COUNT(action) AS action_count
FROM filtered_users
GROUP BY user_id; -- GROUP BY属于转换操作
此时,执行上述SQL后,Spark仅会解析语法并生成逻辑计划(可通过EXPLAIN user_action_cnt;
查看),但不会读取user_behavior
表的数据,也不会执行筛选或聚合计算——这就是“懒加载”的体现。
This post is for subscribers on the 网站会员 and 成为小万的高级会员 tiers only
Subscribe NowAlready have an account? Sign In