面试题答案
一键面试1. 数据存储模式
- 表设计:
- 行键设计:根据业务分析维度,例如时间、地域、用户ID等重要维度组合设计行键。比如按时间戳倒序 + 地域编码 + 用户ID 组合,这样可以方便按时间范围、地域等快速检索数据。时间戳倒序能让新数据排在前面,便于获取最新数据。
- 列族设计:将相关的数据放在同一个列族,如将用户基本信息放在一个列族,行为数据放在另一个列族。减少I/O操作,提高数据读取效率。
- 版本设计:根据业务需求,合理设置数据版本,如对于一些需要保留历史变更的数据,设置合适的版本数,默认为1以节省空间。
- 数据分区:
- 预分区:基于行键分布,提前创建分区。例如根据地域编码的范围进行预分区,每个分区对应一个Region,避免数据热点问题,提高并行处理能力。
2. MapReduce作业调度策略
- 优先级设置:
- 根据业务紧急程度为MapReduce作业设置优先级。例如,对于实时性要求高的分析任务,如实时监控类的作业设置为高优先级;对于日常的统计分析作业设置为低优先级。
- 在Hadoop的调度器(如YARN的Capacity Scheduler或Fair Scheduler)中配置优先级规则,确保高优先级作业优先获取资源。
- 依赖调度:
- 如果作业之间存在依赖关系,如某些汇总作业依赖于明细数据处理作业的结果,使用Oozie等工作流调度工具来管理作业依赖。Oozie可以定义作业的执行顺序,确保依赖的作业完成后再启动后续作业。
- 定时调度:
- 对于周期性的分析任务,如每日、每周的报表统计作业,使用Linux的Cron或Hadoop的调度工具(如Azkaban)设置定时调度,按照指定的时间间隔自动触发作业执行。
3. 资源分配
- YARN资源管理器配置:
- 内存分配:根据集群节点的内存总量,合理分配给Map和Reduce任务。例如,对于一个拥有128GB内存的节点,分配80GB给YARN管理,其中60GB用于Map任务,20GB用于Reduce任务,具体比例根据实际作业特点调整。
- CPU分配:根据节点的CPU核心数,为Map和Reduce任务分配CPU资源。如每个Map任务分配2个CPU核心,每个Reduce任务分配4个CPU核心,依据任务的计算复杂度调整。
- 动态资源分配:
- 启用YARN的动态资源分配功能,根据作业运行情况实时调整资源。例如,当某个作业的Map任务完成速度快,而Reduce任务资源紧张时,动态地将空闲的Map任务资源分配给Reduce任务,提高资源利用率。
4. 性能调优
- Map端优化:
- 输入数据格式优化:使用SequenceFile、ORC等高效的二进制格式作为MapReduce的输入格式,减少数据序列化和反序列化的开销。
- Map任务并行度:根据数据量和集群节点数合理设置Map任务数量。一般每个HDFS块对应一个Map任务,例如每个HDFS块大小为128MB,若总数据量为10GB,则可启动约80个Map任务,充分利用集群并行处理能力。
- Combiner使用:在Map端使用Combiner,对本地数据进行初步聚合。例如在求总和的场景下,Combiner先在每个Map任务本地对数据求和,减少传输到Reduce端的数据量。
- Reduce端优化:
- Reduce任务并行度:根据数据的分布和聚合逻辑设置Reduce任务数量。避免Reduce任务数量过多导致资源竞争,或过少导致处理时间过长。例如通过对数据的预估,每个Reduce任务处理1GB左右的数据,据此计算Reduce任务数量。
- 数据排序优化:在数据量较大时,调整MapReduce的排序缓冲区大小,默认是100MB,可以根据集群内存情况适当增大,如调整到200MB,减少排序次数,提高Reduce端数据处理效率。
- 整体优化:
- 压缩使用:在MapReduce作业的输入、输出和中间数据传输过程中启用压缩。例如使用Snappy压缩算法,在保证较高压缩速度的同时,减少数据传输量和存储空间,提高作业执行效率。
- JVM重用:启用JVM重用,避免每个Map或Reduce任务都启动新的JVM,减少JVM启动开销。可以设置每个JVM执行的任务数,如设置为10,即一个JVM执行10个Map或Reduce任务。