一、背景
公司有些比如使用算法训练的模型数据等需要快速的检索性能,最终选择使用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处理包含以下几部:
- 如果存在同名索引要先删掉
- 执行上述hive2es的sql代码
- 删除除了当前索引之外的其他索引
- 更新别名
这里需要补充说明下,自定义的索引比如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的方式解决。
解决方式:add jar hdfs://nameservice1/lib/commons-httpclient-3.1.jar;
五、总结
本文简述了Hive数据导入到ES的一般处理方式,同时包含增量和覆盖方式的处理,同时介绍了结合平台处理需要注意的问题。其中ES的操作还是参照ES REST API去操作,简单明了,希望你也能有所收获!
参考:https://note4code.com/2016/06/17/hive-向-elasticsearch-导出数据/