電商數倉項目總結

技術選型

Hadoop-2.7.2,Zookeeper-3.4.10,Flume-1.7.0,Kafka-2.11.0,Kafka-manager-1.3.3.22,Sqoop-1.4.6,Mysql,HDFS,Hive-1.2.1,Tez-0.9.1,Presto0.196,yanagishima-18.0,azkaban-2.5.0,Ganglia

整體架構

在這裏插入圖片描述

數倉分層

ODS(原始數據層)不做處理,存放原始數據
DWD(明細數據層)進行簡單數據清洗,降維
DWS(服務數據層)進行輕度彙總(做寬表)
ADS(數據應用層)爲報表提供數據

分爲:用戶行爲數據倉庫和系統業務數據倉庫

基礎知識

表的分類: 實體表:商品表、用戶表
維度表:商品(一、二、三)級分類表
事物型事實表:訂單詳情表、支付流水錶
週期事實表:訂單表

同步策略: 全量表:實體表、維度表
增量表:事物型事實表
新增及變化表:週期型事實表
維度建模: 星型模型:模型維度只有一層
雪花模型:模型維度涉及多級
星座模型:基於多個事實表

拉鍊表

拉鍊表,記錄每條信息的生命週期,一旦一條記錄的生命週期結束,就重新開始一條新的記錄,並把當前日期放入生效開始日期
適用於:數據會發生變化,但大部分是不變的。
基本原理:生成一張與當前拉鍊表相同的臨時表,在最後插入當前拉鍊表沒有的數據,修改已存在的數據,最後將之前的拉鍊表覆蓋。
代碼實現:
1)建立拉鍊表

hive (gmall)>
drop table if exists dwd_order_info_his;
create external table dwd_order_info_his(
    `id` string COMMENT '訂單編號',
    `total_amount` decimal(10,2) COMMENT '訂單金額',
    `order_status` string COMMENT '訂單狀態',
    `user_id` string COMMENT '用戶id' ,
    `payment_way` string COMMENT '支付方式',
    `out_trade_no` string COMMENT '支付流水號',
    `create_time` string COMMENT '創建時間',
    `operate_time` string COMMENT '操作時間',
    `start_date`  string COMMENT '有效開始日期',
    `end_date`  string COMMENT '有效結束日期'
) COMMENT '訂單拉鍊表'
stored as parquet
location '/warehouse/gmall/dwd/dwd_order_info_his/'
tblproperties ("parquet.compression"="snappy");

2)初始化拉鍊表

hive (gmall)>
insert overwrite table dwd_order_info_his
select
    id,
    total_amount,
    order_status,
    user_id,
    payment_way,
    out_trade_no,
    create_time,
    operate_time,
    '2019-02-13',
    '9999-99-99'
from ods_order_info oi
where oi.dt='2019-02-13';

3)製作變動數據
4)先合併變動信息,再追加新增信息,插入到臨時表中
(1)創建臨時表

hive (gmall)>
drop table if exists dwd_order_info_his_tmp;
create table dwd_order_info_his_tmp( 
    `id` string COMMENT '訂單編號',
    `total_amount` decimal(10,2) COMMENT '訂單金額', 
    `order_status` string COMMENT '訂單狀態', 
    `user_id` string COMMENT '用戶id' ,
    `payment_way` string COMMENT '支付方式',  
    `out_trade_no` string COMMENT '支付流水號',  
    `create_time` string COMMENT '創建時間',  
    `operate_time` string COMMENT '操作時間',
    `start_date`  string COMMENT '有效開始日期',
    `end_date`  string COMMENT '有效結束日期'
) COMMENT '訂單拉鍊臨時表'
stored as parquet
location '/warehouse/gmall/dwd/dwd_order_info_his_tmp/'
tblproperties ("parquet.compression"="snappy");

(2)導入數據到臨時表

hive (gmall)>
insert overwrite table dwd_order_info_his_tmp
select * from 
(
select 
id,
    total_amount,
    order_status,
    user_id,
    payment_way,
    out_trade_no,
    create_time,
    operate_time,
    '2019-02-14' start_date,
    '9999-99-99' end_date
from dwd_order_info where dt='2019-02-14'

union all 
select oh.id,
    oh.total_amount,
    oh.order_status,
    oh.user_id,
    oh.payment_way,
    oh.out_trade_no,
    oh.create_time,
    oh.operate_time,
    oh.start_date,
    if(oi.id is null, oh.end_date, date_add(oi.dt,-1)) end_date
from dwd_order_info_his oh left join 
     (
select
*
from dwd_order_info
where dt='2019-02-14'
) oi
     on oh.id=oi.id and oh.end_date='9999-99-99'  
)his 
order by his.id, start_date;

5)將臨時表覆蓋拉鍊表

hive (gmall)>
insert overwrite table dwd_order_info_his 
select * from dwd_order_info_his_tmp;

hive中使用的函數

date_add
date_sub
date_format
next_date
last_date
concat
concat_ws
collec_set
get_json_object

問題總結

Sqoop問題

1)導入導出Null存儲一致性問題
Hive中的Null在底層是以“\N”來存儲,而MySQL中的Null在底層就是Null,爲了保證數據兩端的一致性。在導出數據時採用–input-null-string和–input-null-non-string兩個參數。導入數據時採用–null-string和–null-non-string。
2)數據一致性問題
(1)map數量設置爲1個
(2)添加–staging-table,即先將數據放到臨時表,待全部導入成功纔將數據寫入。(添加–clear-staging-table 即可刪除創建的臨時表)
3)sqoop底層運行
sqoop底層是隻有Map階段,沒有Reduce階段的任務;
原理是重新了MR的inputformat和outputformat

Flume問題

問題發現:在用戶行爲數據倉庫中,從kafka通過flume流向hdfs的過程中,發現數據無法在hdfs保存
問題解決:
(1)首先將問題鎖定在flume -> kafka -> flume -> hdfs 的過程中,利用二分查找檢查問題,首先利用kafka manager檢查kafka中已經生成對應的topic_start和topic_event,並在集羣上消費利用begging從頭消費兩個topic,發現數據已成功導入到kafka當中;將問題鎖定在flume 和 hdfs上
(2)由於flume採用的channel爲File channel,因此會在本地磁盤生成data和checkpoint,查看對應的data文件,發現數據已經讀入到File channel當中,問題鎖定到hdfs sink和hdfs上
(3)經查驗,發現hdfs sink當中使用的filetype爲CompressedStream,壓縮格式爲lzo,但經過檢查發現hdfs的lzo壓縮格式未配置成功,將sink的壓縮格式改爲bzip2後測試,發現採集通道運行正常,hdfs上有數據生成;最後重新添加hdfs的lzo壓縮格式,經測試,一切正常。
(4)Ads層數據用Sqoop往MySql中導入數據的時候,如果用了orc(Parquet)不能導入,需轉化成text格式

優化

1)利用parquet的文件格式,lzo的壓縮方式處理
2)對於flume的hdfs sink產生大量小文件,調整hdfs.rollInterval、hdfs.rollSize、hdfs.rollCount這三個參數的值,將小文件合併
3)將hive的計算引擎有MapReduce換成了Tez(Tez優點:基於內存進行運算,中間過程不落盤,能將多個有依賴的作業轉換成一個作業)
4)flume採用Taildir source,支持斷點續傳;file channel,數據落盤,提高數據可靠性。
5)使用自定義UDF和UDTF,能更方便的檢查錯誤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章