一、背景

公司有些比如使用算法训练的模型数据等需要快速的检索性能,最终选择使用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的方式解决。

解决方式:add jar hdfs://nameservice1/lib/commons-httpclient-3.1.jar;

五、总结

本文简述了Hive数据导入到ES的一般处理方式,同时包含增量和覆盖方式的处理,同时介绍了结合平台处理需要注意的问题。其中ES的操作还是参照ES REST API去操作,简单明了,希望你也能有所收获!

参考:https://note4code.com/2016/06/17/hive-向-elasticsearch-导出数据/