Hive抽數到ElasticSearch實現

一、背景

有關ES的詳細介紹參考:https://www.cnblogs.com/cjsblog/p/9439331.html
公司有些比如使用算法訓練的模型數據等需要快速的檢索性能,最終選擇使用ES來存儲,然後使用別名來區分每一批次的最新數據,對外(web接口)只需暴露別名即可。

二、常規實現

  • ES數據全量數據攝入(Overwrite模式)
    覆蓋方式或許是公司最常用的方式,每天T+1或者T+0去更新數據,然後切換索引和別名,以下是具體的實現方式。
    1)使用Hadoop導入
    add jar /xxx/scripts/jars/elasticsearch-hadoop-6.6.1.jar;
    CREATE TEMPORARY TABLE IF NOT EXISTS dm_user_xx_df_temp(user_id bigint, is_paid_in_youke int,payment_cnt bigint) 
    STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
    TBLPROPERTIES('es.resource' = '${index}/result','es.index.auto.create' = 'true','es.nodes' = '${ip}','es.port' = '${port}');
    INSERT OVERWRITE TABLE dm_user_xx_df_temp  
    select user_id,is_paid_in_youke,payment_cnt 
    from dm.dm_user_test_df where pt ='2019-09-29';
    

2)使用SparkSql方式導入

add jar hdfs://xxx/elasticsearch-spark-20_2.10-6.1.3.jar;
CREATE TEMPORARY TABLE dm_xxxx_df_temp(user_id bigint, is_paid_in_youke int,payment_cnt bigint)
USING org.elasticsearch.spark.sql
OPTIONS (resource '${index}/result', nodes '${ip}', port '${port}');

INSERT OVERWRITE TABLE dm_xxxx_df_temp
select user_id,is_paid_in_youke,payment_cnt
from dm.dm_user_xxx_df where pt ='${day}' limit 5;
  • ES數據增量數據攝入 (Append模式)
    增量的很簡單,無論OVERWRITE/Append對臨時表的直接操作都是追加,如果插入多次會出現數據重複,所以根據需要在使用上要去重處理。

三、工具平臺化處理

該功能是通用的,在公司的數據處理中大多還是集成在平臺之中,只需要必須的參數設置就能非常簡單的 配置一個Hive2Es的任務。其實真正的overwrite處理包含以下幾部:

  1. 如果存在同名索引要先刪掉
  2. 執行上述hive2es的sql代碼
  3. 刪除除了當前索引之外的其他索引
  4. 更新別名

這裏需要補充說明下,自定義的索引比如index_test, 後臺會處理成index_test_1108(小時分鐘),索引的別名:index_test_alias。 也即是說讓當前別名總是指向最新的索引。

結合到平臺的處理我認爲需要做到以下幾點:

  • 配置方式儘可能的簡便
  • 日誌儘可能詳細暴露出哪一步出現問題
  • 不要在抽數的時候做計算

四、遇到的問題

  • CDH版本的Hadoop集羣在運行使用Hadoop方式抽數到ES的時候報包找不到的問題。
Showing 4096 bytes of 93518 total. Click here for the full log.
OldReducer(ReduceTask.java:445)
	at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:393)
	at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:174)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1875)
	at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:168)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.httpclient.protocol.ProtocolSocketFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 22 more

這個問題在另外一套使用原生的Hadoop安裝的沒有出現此問題,而在線上使用CDH版本 **Cloudera Express 6.2.0 ** 使用Hadoop3.0的則會出現這樣的問題,暫時使用sparksql的方式解決。

五、總結

本文簡述了Hive數據導入到ES的一般處理方式,同時包含增量和覆蓋方式的處理,同時介紹了結合平臺處理需要注意的問題。其中ES的操作還是參照ES REST API去操作,簡單明瞭,希望你也能有所收穫!

參考:
https://www.cnblogs.com/liqiu/p/5687310.html
https://note4code.com/2016/06/17/hive-向-elasticsearch-導出數據/

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