注:這裏用Hive泛指數據倉庫,數據還是存儲在HDFS裏。
想要從MongoDB往Hive導數據主要有兩種方式
1. Hive直接連接MongoDB
Hive連接MongoDB這篇講了怎麼連接。
使用這種方式的好處在於,直接創建一個Hive的表,用於映射MongoDB裏的數據。也就是數據仍然還在MongoDB內,創建映射表的時間非常短。
但是壞處也同樣在這,如果要把數據ETL到Hive表,這種方式必須執行map reduce,一直從MongoDB裏面取數據,連接的穩定性受到網絡環境影響。
在用這種方式導數據的時候遇到過兩個坑。
- 執行map reduce耗時太長,這裏一部分是網絡原因,還有一部分是起了太多的map 任務,也就是將任務切分的過細,每個map只處理很少的任務,耗費太多資源,坑在於設置map數的參數不同於hive默認的參數。要在執行HQL前輸入
set mongo.input.split_size=n
,這個n就是將mongo collection切分成若干份,每份的大小,單位是MB。默認的設置是8,將它改成128以後,mapper的數量明顯減少了,總的執行時間也提高了。還有一種設置方法, 是修改hadoop的yarn-site.xml
配置文件,添加
<property>
<name>mongo.input.split_size</name>
<value>128</value>
</property>
- 第二個坑是,MongoDB與Hadoop部署在不同的服務器上,服務器的帶寬變改變了,經常在map reduce執行的過程中中斷,報SocketTimeout錯誤,把timeout的時間從30s改成300s了,還是偶爾會出現錯誤,這對Data pipeline的穩定性影響就特別大。
考慮到data pipeline穩定性第一,只好採用稍微麻煩的第二種方法。
2. mongodump -> BSON -> HDFS
mongodump 是MongoDB備份的一種方式,可以dump下整個數據庫,也可以指定dump某個collection。dump下來的每個collection 都是BSON文件,也就是binary json 的意思。
關於mongodump詳細的內容,可以看官方文檔
https://docs.mongodb.com/manual/reference/program/mongodump/
mongodump 的過程比較穩定,效率也比較高。
mongodump -h $host -u $user -p $password -d $db -c $collection -o $output
使用上述命令就可以將指定的collection dump到$output目錄了。
然後再將bson文件放入hdfs內。
首先創建一個目錄
### 創建HDFS目錄
hdfs dfs -mkdir $hdfs_dir
### 將文件放入該目錄下,$file_path爲dump出的bson文件的路徑
hdfs dfs -put $file_path $hdfs_dir
這時候已經將數據都存放到hdfs內了。要想使用Hive查詢數據,再創建相應的表即可,建表的方式與直接連接MongoDB創建映射表類似,不過要修改一些參數,下面給出一個例子。
create table if not exists ${table_name}
(
...
)
comment '...'
row format serde 'com.mongodb.hadoop.hive.BSONSerDe'
with serdeproperties('mongo.columns.mapping'='{hive字段與mongo字段的映射關係}')
stored as inputformat 'com.mongodb.hadoop.mapred.BSONFileInputFormat'
outputformat 'com.mongodb.hadoop.hive.output.HiveBSONFileOutputFormat'
location
'{hdfs_dir}'
與直接連接mongo創建映射表相同的部分是with serdeproperties
,不同的是serde 爲com.mongodb.hadoop.hive.BSONSerde
存儲的輸入輸出控件也不同,並且多了location參數,location指示的是bson文件所在的HDFS目錄,也就是先前創建的那個目錄。
總結
如果爲了方便,偶爾使用Hive訪問MongoDB,使用第一種方式較爲方便。如果需要定時導數據,保證穩定性,則第二種方式更優。
還有,bson放入hdfs後記得刪除dump下的文件,數據量大的時候往往比較耗費磁盤空間。