目錄
寫在最前:
1、Hive 與 HDFS 之間的關係
- Hive 是基於 Hadoop 的一個數據倉庫工具,可以將結構化的數據文件映射爲一張數據庫表,並提供完整的 sql 查詢功能,可以將 sql 語句轉換爲 MapReduce 任務進行運行。其優點是學習成本低,可以通過類 SQL 語句快速實現簡單的 MapReduce 統計,不必開發專門的 MapReduce 應用,十分適合數據倉庫的統計分析。
- Hive 是建立在 Hadoop 上的數據倉庫基礎構架。它提供了一系列的工具,可以用來進行數據提取轉化加載(ETL),這是一種可以存儲、查詢和分析存儲在 Hadoop 中的大規模數據的機制。Hive 定義了簡單的類 SQL 查詢語言,稱爲 HQL,它允許熟悉 SQL 的用戶查詢數據。同時,這個語言也允許熟悉 MapReduce 開發者的開發自定義的 mapper 和 reducer 來處理內建的 mapper 和 reducer 無法完成的複雜的分析工作。
- Hadoop Distributed File System,簡稱 HDFS,是一個分佈式文件系統。HDFS 有着高容錯性(fault-tolerent)的特點,並且設計用來部署在低廉的(low-cost)硬件上。
2、Hive 與關係型數據庫的區別
使用 Hive 的命令行接口,感覺很像操作關係數據庫,但是 Hive 和關係數據庫還是有很大的不同,以下從宏觀的角度比較 Hive 和關係型數據庫的區別:
- Hive 和關係數據庫存儲文件的系統不同,Hive 使用的是 hadoop 的 HDFS(hadoop 的分佈式文件系統),關係數據庫則是服務器本地的文件系統;
- Hive 使用的計算模型是 mapreduce,而關係數據庫則是自己設計的計算模型;
- 關係數據庫都是爲實時查詢的業務進行設計的,而 Hive 則是爲海量數據做數據挖掘設計的,實時性很差;實時性的區別導致 Hive 的應用場景和關係數據庫有很大的不同;
- Hive 很容易擴展自己的存儲能力和計算能力,這個是繼承 Hadoop 的,而關係數據庫在這個方面要比數據庫差很多。
一、通過 HDFS 的垃圾回收站恢復
使用這種方式的前提是在 HDFS 上面開啓 trash 功能,默認是沒有開啓的。interval 的默認值爲 0,單位是分鐘。只需要 Hadoop 的配置文件 core-site.xml 中添加下面的內容:
<!--Enable Trash -->
<property>
<name>fs.trash.interval</name>
<value>1440</value>
<description>Number of minutes between trash checkpoints.
If zero, the trash feature is disabled.
</description>
</property>
添加好上述內容後,不需要重啓後臺程序,直接就會生效。
執行刪除操作後,會先將文件移動到當前操作用戶的 .Trash/Current 目錄下面(eg: /user/hadoop/.Trash/Current),舉個例子:
# 通過 scribe 用戶上傳一個測試文件 #
[root@yz-bi-web00 ~]# su - scribe
[scribe@yz-bi-web00 ~]$ cd scribe_log_treater_metl/lib/
[scribe@yz-bi-web00 lib]$ ll
total 67148
-rw-rw-r-- 1 scribe scribe 34401742 May 15 16:30 LogExtractor.tar.gz
...。。
[scribe@yz-bi-web00 lib]$ hdfs dfs -put /home/scribe/scribe_log_treater_metl/lib/LogExtractor.tar.gz /user/scribe/
# 上傳成功查看 #
[scribe@yz-bi-web00 lib]$ hdfs dfs -ls /user/scribe/
Found 4 items
drwx------ - scribe hadoop 0 2020-05-19 08:00 /user/scribe/.Trash
-rw-r--r-- 3 scribe hadoop 34401742 2020-05-19 12:27 /user/scribe/LogExtractor.tar.gz
...。。
# 切換用戶(爲了測試效果),通過 hadoop 用戶執行刪除操作 #
[scribe@yz-bi-web00 lib]$ exit
logout
[root@yz-bi-web00 ~]# su - hadoop
[hadoop@yz-bi-web00 ~]$ hdfs dfs -ls /user/scribe/
Found 4 items
drwx------ - scribe hadoop 0 2020-05-19 08:00 /user/scribe/.Trash
-rw-r--r-- 3 scribe hadoop 34401742 2020-05-19 12:27 /user/scribe/LogExtractor.tar.gz
...。。
# 刪除 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -rm -r -f /user/scribe/LogExtractor.tar.gz
20/05/19 12:30:50 INFO fs.TrashPolicyDefault: Namenode trash configuration: Deletion interval = 1440 minutes, Emptier interval = 0 minutes.
Moved: 'hdfs://yz-higo-nn1:9000/user/scribe/LogExtractor.tar.gz' to trash at: hdfs://yz-higo-nn1:9000/user/hadoop/.Trash/Current
# 通過 hadoop 用戶刪除後,會將文件移動到 /user/hadoop/.Trash/Current 目錄下面,而且是刪除文件在 HDFS 上的絕對路徑 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -ls /user/hadoop/.Trash/Current/user/scribe
Found 1 items
-rw-r--r-- 3 scribe hadoop 34401742 2020-05-19 12:27 /user/hadoop/.Trash/Current/user/scribe/LogExtractor.tar.gz
# 恢復 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -mv /user/hadoop/.Trash/Current/user/scribe/LogExtractor.tar.gz /user/scribe/
[hadoop@yz-bi-web00 ~]$ hdfs dfs -ls /user/scribe/
Found 4 items
drwx------ - scribe hadoop 0 2020-05-19 08:00 /user/scribe/.Trash
-rw-r--r-- 3 scribe hadoop 34401742 2020-05-19 12:27 /user/scribe/LogExtractor.tar.gz
...。。
# 如果確定要刪除的文件,直接將文件或目錄 drop 掉,不放到 trash 裏面,刪除的時候使用參數-skipTrash #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -rm -r -f -skipTrash /user/scribe/LogExtractor.tar.gz
Deleted /user/scribe/LogExtractor.tar.gz
[hadoop@yz-bi-web00 ~]$
二、通過快照恢復
Hadoop 從 2.1 版本後開始支持 HDFS 快照(SnapShot)功能:
- 快照創建瞬時性:除去 inode 的查詢時間,算法消耗 0(1)複雜度;
- 只有在對快照修改時纔會消耗額外內存:內存使用 0(M),M 是被修改的文件或者目錄數;
- DateNode 的 block 不被複制:快照文件記錄 block 列表和文件大小,不做數據的拷貝複製;
- 快照不會對正常 HDFS 操作產生影響:所有修改都按時間倒序排序,因此當前數據總能被訪問到,快照數據是根據與當前數據進行變更部分的差值計算得來的。
一個可以快照的目錄最多可以允許同時 65536 個快照同時存在,嵌套的可快照目錄目前還不允許。
管理員操作:
1、允許快照
[root@yz-bi-web00 ~]# su - hadoop
[hadoop@yz-bi-web00 ~]$ hdfs dfsadmin -allowSnapshot <path>
## <path> 即想創建快照的目錄的路徑。通過上述命令將一個目錄變成可快照的目錄
## 恢復 Hive 數據,必須事先把 /user/hive/warehouse 目錄變爲可快照目錄,並且定期創建新快照
2、創建快照:
一般使用普通用戶操作,此用戶需要有操作可快照目錄的權限,最好是該目錄的 owner。管理員可以進行任何操作。
[hadoop@yz-bi-web00 ~]$ hdfs dfs -createSnapshot <path> [<snapshotName>]
## <path> 可快照目錄的路徑,<snapshotName> 快照的名稱,可以不寫,默認會生成一個格式爲 's'yyyyMMdd-HHmmss.SSS
3、刪除快照
[hadoop@yz-bi-web00 ~]$ hdfs dfs -deleteSnapshot <path> <snapshotName>
## <path> 可快照目錄的路徑 ,<snapshotName> 快照的名稱
4、重命名快照
[hadoop@yz-bi-web00 ~]$ hdfs dfs -renameSnapshot <path> <oldname> <newname>
<path> 可快照目錄的路徑,<oldname> 老名字, <newname> 新名字
5、獲取可快照的目錄信息
[hadoop@yz-bi-web00 ~]$ hdfs lsSnapshottableDir
6、獲取快照差異報告
[hadoop@yz-bi-web00 ~]$ hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot>
<path> 可快照目錄的路徑,<fromSnapshot> 源快照名,<toSnapshot> 目的快照名
7、結果
+ | 文件或目錄被創建 |
- | 文件或目錄被刪除 |
M | 文件或目錄被修改 |
R | 文件或目錄被重命名 |
8、使用案例
# 切換爲 hadoop 用戶操作 #
[root@yz-bi-web00 ~]# su - hadoop
# 創建一個目錄 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -mkdir /user/snapshot
# 將目錄變成可快照的目錄 #
[hadoop@yz-bi-web00 ~]$ hdfs dfsadmin -allowSnapshot /user/snapshot
Allowing snaphot on /user/snapshot succeeded
# 獲取可快照目錄信息 #
[hadoop@yz-bi-web00 ~]$ hdfs lsSnapshottableDir
drwxr-xr-x 0 hadoop hadoop 0 2020-05-19 16:31 1 65536 /user/snapshot
# 上傳一個測試文件到可快照的目錄 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -put /home/hadoop/LogExtractor.tar.gz /user/snapshot/
# 查看 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -ls /user/snapshot/
Found 1 items
-rw-r--r-- 3 hadoop hadoop 34401742 2020-05-19 16:01 /user/snapshot/LogExtractor.tar.gz
# 創建快照 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -createSnapshot /user/snapshot import-data
Created snapshot /user/snapshot/.snapshot/import-data
# 查看 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -ls /user/snapshot/.snapshot/import-data
Found 1 items
-rw-r--r-- 3 hadoop hadoop 34401742 2020-05-19 16:01 /user/snapshot/.snapshot/import-data/LogExtractor.tar.gz
# 將 LogExtractor.tar.gz 文件刪除
[hadoop@yz-bi-web00 ~]$ hdfs dfs -rm -r -f /user/snapshot/LogExtractor.tar.gz
20/05/19 16:29:03 INFO fs.TrashPolicyDefault: Namenode trash configuration: Deletion interval = 1440 minutes, Emptier interval = 0 minutes.
Moved: 'hdfs://yz-higo-nn1:9000/user/snapshot/LogExtractor.tar.gz' to trash at: hdfs://yz-higo-nn1:9000/user/hadoop/.Trash/Current
# 誤刪除後就可以使用快照目錄進行恢復 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -cp -ptopax /user/snapshot/.snapshot/import-data/LogExtractor.tar.gz /user/snapshot
20/05/19 16:31:43 WARN hdfs.DFSClient: DFSInputStream has been closed already
# 查看 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -ls /user/snapshot/
Found 1 items
-rw-r--r-- 3 hadoop hadoop 34401742 2020-05-19 16:01 /user/snapshot/LogExtractor.tar.gz
# 刪除快照 #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -deleteSnapshot /user/snapshot import-data
# 如果確定要刪除的文件,直接將文件或目錄 drop 掉,不放到 trash 裏面,刪除的時候使用參數-skipTrash #
[hadoop@yz-bi-web00 ~]$ hdfs dfs -rm -r -f -skipTrash /user/snapshot
Deleted /user/snapshot
三、通過源數據恢復到 Hive
以上兩種回收站和快照均無法恢復時,再根據實際情況分析來恢復 Hive 數據。
1、Hive 數據來源分析
首先要搞清楚 Hive 中數據來源,在 HIGO,數據主要來源可分爲四部分:
- 日誌數據:利用 Scribe 對各日誌源機器的日誌進行匯聚後,通過 Python 對匯聚端日誌的監視、下載、解析、上傳至 Hive 庫;
- 業務數據:均來源於 MySQL,通過 Sqoop + Python + Shell 的管理腳本來實現上傳至 Hive 庫;
- 中間層數據:通過 HIGO 數據分析平臺的調度任務處理上傳至 Hive 庫;
- 商家端及其它 BI 數據:主要通過 Shell 管理腳本,Python 輔助解析來上傳至 Hive 庫;
2、日誌數據恢復
只要 Scribe 日誌匯聚端日誌在,就能通過 Python 日誌處理 METL 系統 恢復所有日誌數據。
重新部署 METL 時需要檢查 Hadoop 作業模塊是否正常,若命令行 Hadoop 作業拋錯,則需要檢查代碼,檢查上傳到 Hadoop 的代碼包,可嘗試本地打包上傳到 HDFS 指定目錄。
[root@yz-bi-web00 ~]# su - scribe
[scribe@yz-bi-web00 ~]$ hdfs dfs -put /home/scribe/scribe_log_treater_metl/lib/LogExtractor.tar.gz /user/scribe/lib/
以下是命令行檢查 Hadoop 作業命令:
/hadoop/hadoop/bin/hadoop jar /hadoop/hadoop/share/hadoop/tools/lib/hadoop-streaming-2.7.1.jar \
-Dmapreduce.output.fileoutputformat.compress=true \
-Dmapreduce.output.fileoutputformat.compress.codec=com.hadoop.compression.lzo.LzopCodec \
-Dmapreduce.job.name=[LogExtract][gz_higo_v_log][10.20.0.102_v_higo_nginx-2020-05-14_00066_parselog_10.20.0.102] \
-libjars /home/scribe/scribe_log_treater_metl/bin/../lib/NoSeparatorTextOutputFormat-1.0.jar \
-archives hdfs://yz-higo-nn1:9000/user/scribe/lib/LogExtractor.tar.gz#LogExtractor \
-mapper 'LogExtractor/run.sh ./core/template_parse_script.py gz_higo_v_log' \
-input /user/scribe/data/gz_higo_v_log/10.20.0.102_v_higo_nginx-2020-05-14_00066 \
-output /user/scribe/data/gz_higo_v_log/10.20.0.102_v_higo_nginx-2020-05-14_00066_parselog_10.20.0.102_temp \
-outputformat com.lehe.data.NoSeparatorTextOutputFormat \
-numReduceTasks 0 \
-lazyOutput
如何修復歷史數據❓主要就是修復 log_block_galaxy 表數據。
Create Table: CREATE TABLE `log_block_galaxy` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`group_id` varchar(100) NOT NULL DEFAULT '',
`block_name` varchar(100) NOT NULL DEFAULT '',
`block_file_path_in_client` varchar(250) DEFAULT '',
`block_file_path_in_server` varchar(250) DEFAULT '',
`block_parselog_file_in_server` varchar(250) DEFAULT '',
`status` tinyint(4) DEFAULT '0',
`create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`log_date` date DEFAULT '0000-00-00',
`modify_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`cleanlog` tinyint(4) DEFAULT '0',
`last_update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`client_host` varchar(50) NOT NULL DEFAULT '',
`client_user` varchar(50) NOT NULL DEFAULT '',
`parse_file_hive_path` varchar(256) DEFAULT '',
`md5_tag` varchar(50) DEFAULT '',
`hive_table` varchar(50) DEFAULT '',
`error_times` int(10) unsigned DEFAULT '0',
`input_num` int(11) DEFAULT '0',
`valid_num` int(11) DEFAULT '0',
`abandon_num` int(11) DEFAULT '0',
`server_user` varchar(50) DEFAULT NULL,
`server_host` varchar(100) DEFAULT NULL,
`send_to_kafka_status` int(11) DEFAULT '0' COMMENT '0:not send,1:sending,2:complete',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_group_block_name_client` (`group_id`,`block_name`,`client_host`),
KEY `log_date` (`log_date`),
KEY `idx_group_id_status_create_time` (`group_id`,`status`,`create_time`),
KEY `create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2.1 將對應的未處理的 block 的 status 重置爲 0,error_times 重置爲 0 即可重新自動進行 METL
或者
|
= ... |
in(...) | |
between ... and ... | |
group_id:gz_higo_v_log、gz_higo_main_log、gz_higo_wap_log、gz_higo_utm_log、gz_higo_glk_log、higo_php_statistics_register_log |
2.2 如果 MySQL 中記錄缺失,舉個例子以此形式插入,即可重新自動進行 METL
replace into log_block_galaxy(group_id,block_name,create_time,modify_time,log_date,block_file_path_in_client,status,last_update_time,client_host,client_user,error_times) values('gz_higo_v_log','v_higo_nginx-2020-05-12_00083','2020-05-12 00:00:01','2020-05-12 00:30:00','2020-05-12','/data/web/glk_higo_nginx/v_higo_nginx-2020-05-12_00083',0,'2020-05-12 00:30:00','10.20.0.102','scribe',0);
2.3 如果 MySQL 中記錄缺失過多時也可以通過以下 Shell 腳本(replace_log_block_galaxy.sh)進行插入,然後重新自動進行 METL
#!/bin/bash
function mysql_conn(){
mysql -u'wfwriter' -p'wFW#1^iPo16QPsd' -h10.20.2.22 -P3411
}
function mysql_e(){
mysql -u'wfwriter' -p'wFW#1^iPo16QPsd' -h10.20.2.22 -P3411 -Ne "${1}"
}
replace_data='2020-05-12'
logfile_prefix='m_higo_nginx'
group_id_name='gz_higo_wap_log'
i=0
y=94
while (( $i <= $y ))
do
lastfix=$(printf "%05d\n" $i)
filename="${logfile_prefix}-${replace_data}_"${lastfix}
is_replace=`mysql_e "use higo_bilog;select count(*) from log_block_galaxy where log_date='${replace_data}' and block_name='${filename}'"`
if [[ 1 -eq "${backup_0k}" ]]; then
echo "replace status: ${is_replace}"
else
echo "replace status: ${is_replace}"
echo "use higo_bilog;replace into log_block_galaxy(group_id,block_name,create_time,modify_time,log_date,block_file_path_in_client,status,last_update_time,client_host,client_user,error_times) values('${group_id_name}','${filename}','${replace_data} 00:00:01','${replace_data} 00:30:00','${replace_data}','/data/web/${logfile_prefix}/${filename}',0,'${replace_data} 00:30:00','10.20.0.102','scribe',0);" | mysql_conn
fi
let "i++"
done
3、業務數據恢復
只要 MySQL 集羣正常, Sqoop + Python + Shell 的管理腳本(SQOOP 部署及導入數據到 Hive 的實際應用)會根據 crontab 設置的腳本執行時間自動恢復 MySQL-Hive 配置的一一對應的表數據。
也可以隨時手動強制進行某個已配置的數據導入 Hive 庫。
服務器 | 服務 | 部署路徑 | 任務級別 | crontab 定期調用腳本 | 備註 | 狀態 |
---|---|---|---|---|---|---|
Sqoop + Python | [email protected]:/home/sqoop/sqoop | 小時 | 5 * * * * sh /home/sqoop/sqoop/bin/sqoop_import_hour.sh > /tmp/sqoop_import_hour.log 2>&1 & | ✅ | ||
天 | 20 0 * * * sh /home/sqoop/sqoop/bin/sqoop_import_day.sh > /tmp/sqoop_import_day.log 2>&1 & | ✅ | ||||
Sqoop + Shell | [email protected]:/home/sqoop/mysql_hive: | 天 | 13 5 * * * bash /home/sqoop/mysql_hive/bin/adx_mysql_hive_wf.sh -a all > /home/sqoop/mysql_hive/log/error.log 2>&1 & | ✅ | ||
可導入 Hadoop 的 MySQL 配置 | HOST:10.20.2.22; PORT:3411; DATABASE:higo_bilog; TABLE:t_dolphin_stat_db_info | |||||
異常情況處理:手動的形式強制進行某個已配置的數據庫的導入 | cd /home/sqoop/sqoop && python bin/sqoop_import.py -t <hive_table_name>(通過 Sqoop + Python 的方式,將強制對 MySQL 中未進行分表操作的普通表進行一次 <mysql_table_name> 到 hive 中 <hive_table_name> 的導入操作) |
特別注意01:MySQL 進行過分表操作的表重新導入 Hive(Hive 未進行分區)時,需要先在 Hive 上 drop table hive_tablename; 然後清理 SQOOP 通過 MyCat 從 MySQL 導入數據到 Hive 相關記錄文件,直接刪除就行,最後直接執行 bash /home/sqoop/mysql_hive/bin/adx_mysql_hive_wf.sh -a all 就可以了。
## (mysql -> hive)t_im_message -> ods_im_message、t_im_msg -> ods_im_msg
[root@yz-bi-web01 ~]# su - sqoop
[sqoop@yz-bi-web01 ~]$ hive
hive> drop table ods_im_message;
hive> drop table ods_im_msg;
hive> quit;
[sqoop@yz-bi-web01 ~]$ rm -rf mysql_hive/var/t_im_*
[sqoop@yz-bi-web01 ~]$ bash /home/sqoop/mysql_hive/bin/im_mysql_hive_wf.sh -a all > /home/sqoop/mysql_hive/log/error.log 2>&1 &
特別注意02:MySQL 中未進行分表操作的普通表導入 Hive 中需要進行分區時,即 SQOOP 從 MySQL 導入到 Hive 之 Python 腳本 的配置文件中含有 partition_keys=dt 的表,根據具體需求手動進行特殊處理。
## ods_pandora_guaranty_account
[sqoop@yz-bi-web01 ~]$ cat sqoop/conf/higo_order.conf
[ods_pandora_guaranty_account]
db=higo_order
rank=110
mytbname=t_pandora_guaranty_account
hivetbname=ods_pandora_guaranty_account
partition_keys=dt
owner=wufei
...。。
[sqoop@yz-bi-web01 ~]$ hive
hive> use default;
hive> insert overwrite table ods_pandora_guaranty_account partition (dt='2020-05-12') select account_id,balance,limit,mtime,shop_id,fast_amount from ods_pandora_guaranty_account where dt='2020-05-17';
hive> ...。。
hive> quit;
[sqoop@yz-bi-web01 ~]$
4、中間層數據恢復
中間數據主要依賴以上(日誌數據、業務數據)必須先恢復。選定日期,重啓執行 HIGO 數據分析平臺的調度任務即可。注意各調度任務間的依賴關係,可通過調度任務的具體 HQL (運行詳情)分析去恢復。
5、商家端及其它 BI 數據恢復
商家端及其它 BI 數據恢復主要依賴以上數據必須先恢復。根據 yz-bi-web00(腳本梳理)在 work 用戶下 [work@yz-bi-web00 ~ ]$ crontab -l 執行對應腳本,恢復歷史數據執行在執行腳本時傳入具體日期(eg:2020-05-12)參數即可。
報表類數恢復據同理,選定日期,重啓執行 HIGO 數據分析平臺的調度任務即可,建議根據具體報表的具體 HQL(運行詳情) 分析去恢復。