我们做的项目涉及到的软件架构: clouderaManager + HDFS + YARN + SQOOP + HIVE + HUE + OOZIE + FINEBI

  • 架构流程:
    当前项目是基于clouderaManager构建CDH的大数据分析平台, 在此平台之上,我们搭建有HDFS YARN HIVE SQOOP OOZIE HUE Presto 等相关的大数据组件
    我们首先使用SQOOP从业务数据库中将数据导入到HIVE中, 在HIVE中构建数仓分层, 对数据进行ETL相关操作, 对数据进行了统计分析处理, 最后将统计分析的结果导出到Mysql数据库中, 然后通过FINEBI实现图表展示操作, 同时整个项目需要周期化运行的, 所以这里引入了OOZIE完成工作流定时调度操作, 当然采用OOZIE原因是因为我们基于HUE进行数据统计, 同时可以直接基于HUE对接oozie完成调度配置的

我将从项目的整个流程划分为4步

MySQL - ods - dwd - dwb - dm

Step1

通过sqoop将业务数据库中的数据采集同步到在线教育数仓的ODS层中

  • Sqoop导入数据又四种方式,分别是全量覆盖、全量同步、增量同步、新增及更新同步

Step2

基于ODS层数据进行清洗转换处理的工作, 根据分析需求区分事实表、维度表,后将数据同步至DWD层, 同时在DWD层完成了历史数据维护工作,项目采用拉链表的方案;

在进行DWD层建表设计的时候,我们发现如果拉链表和数据清洗的工作的话,SQL代码量的会相当庞大,于是我们决定要把数据清洗的工作和维护历史数据的工作用两张表来实现.我们的拉链表有6张,

  • 三张事实表为拉链表,customer_relationshi客户关系表,customer_clue线索表,以及访问咨询表

  • 学科表,校区表,部门表不需要做拉链表

  • 客户表,员工表,客户申诉表需要做拉链表

  • 拉链表实现

拉链表是缓慢渐变维2(Showly Changed Dimension2),之所以叫拉链表是因为他能维护历史数据,

拉链表的方式是通过start_time 和 end_time 两个字段来实现的,DWD层实现拉链表主要是看分区字段是否是以开始时间(start_time)作为分区字段的,如果是就只需要追加’9999-12-31’的结束字段,即end_time

如果没有就需要同时添加start_time和end_time两个字段

  • 清洗转换实现:
  • cr (customer_relationship) 客户关系表:

    • 将create_date_time 通过substring函数转换为 yearinfo monthinfo dayinfo hourinfo
    • 将origin_type 转换为 origin_type_state(NETSERVICE,PRESIGNUP 认为线上,其余线下)
    • 将校区和学科的id字段进行转换, 如果为 0 或者 null 转换为 -1
  • cc(customer_clue) 客户线索表

    • clue_state 判断字段是新用户还是老用户 转为clue_state_stat
    • 将无效线索过滤customer_clue 中clue_appeal_state 判断有效无效: 0 有效 1 无效(表customer_clue cc)

Step3

接着对DWD层基于业务模块进行数据维度退化处理工作, 将退化后的宽表数据灌入到DWB层中, 构建了整个项目数据中心

对DWD层数据进行处理的时候,我们关联了事实表和维度表,结合需求分析中的各种指标维度进行7表关联操作

(客户表,员工表,客户申诉表,客户关系表,客户线索表,学科表,校区表),而且使用了分桶字段代替关联字段,实现了join优化,从而降维形成宽表

建表原则是宁滥勿缺,

Step4

第四步: 开始进行主题统计分析, 根据分析业务需求得来的维度和指标进行统计分析, 在统计的时候, 先进行提前聚合处理工作, 将聚合统计后宽表数据同步到DM层中

在DM层中,我们发现第7个需求后面的需求需要用到访问咨询表中的字段,来实现对需求的分析实现,

于是我们没有拘泥于DWB层的数据,而是直接使用DWD层的访问咨询表来统计访客咨询产生的有效线索的占比

我们在这里将粗粒度和细粒度汇总都放在了DM层,根据需求分析得到的结果对数据进行分析

固有维度: 时间维度 新老维度 线上线下

产品属性维度: 总意向量 地区(区域)维度 学科维度 校区维度 来源渠道 咨询中心

优化

  • 在ODS层使用了zlib压缩协议,因为ODS层是和业务数据库中的数据保持相同的粒度,故不需要频繁读取数据,故使用zlib压缩
  • 在除了ODS层的其它层使用了列存储ORC+ snappy
  • 使用了分桶表join分桶表,在join的时候用分桶字段代替原来的关联字段,这里需要注意一张表的分桶数量必须是另一张表分桶数量的偶数倍

遇到的问题:

  • reduce阶段内存不足

    • 解决方案:(通过set设置Reduce阶段的最大内存)

      1
      2
      3
      4
      5
      6
      -- map阶段内存不足
      set mapreduce.map.memory.mb=10150;
      set mapreduce.map.java.opts=-Xmx6144m;
      -- reduce阶段内存不足
      set mapreduce.reduce.memory.mb=10150;
      set mapreduce.reduce.java.opts=-Xmx8120m;
  • 插入分区表超过上限

    • 解决方案: (设置最大分区数量)

      1
      2
      3
      4
      5
      6
      --分区
      SET hive.exec.dynamic.partition=true;
      SET hive.exec.dynamic.partition.mode=nonstrict;
      set hive.exec.max.dynamic.partitions.pernode=10000;
      set hive.exec.max.dynamic.partitions=100000;
      set hive.exec.max.created.files=150000;
  • 映射:MySQL抽取数据全量到ODS层时,由于数据量过大,导致数据采集失败,

    • 解决方案;后面写了一个Shell脚本分批循环导入