自定义Spark Partitioner提升es-hadoop Bulk效率
http://www.jianshu.com/p/cccc56e39429/comments/2022782 和 https://github.com/elastic/elasticsearch-hadoop/issues/745 都有提到通过自定义Spark Partitioner提升es-hadoop Bulk效率,但是无可运行代码,自己针对其思路在spark-shell里实现了一份。
思路:
spark streming监控/tmp/data下的新文件,并将文中每行内容存储到ES的web/blog索引里!
注意:代码里使用了doc ID来定制路由,该id为自动生成的uuid!因此在启动ES后,需要:
curl -s -XPUT localhost:/web -d '
{
"mappings": {
"blog": {
"_id": {
"path": "uuid"
},
"properties": {
"title": {
"type": "string",
"index": "analyzed"
}
}
}
}
}'
告诉ES使用blog document中的uuid字段作为_id。ES 2.0以后见 http://stackoverflow.com/questions/32334709/how-to-set-id-in-elasticsearch-2-0
下面是spark-shell代码:
import org.apache.spark._
import org.apache.spark.streaming._
import org.elasticsearch.spark._
import org.apache.spark.Partitioner
import org.elasticsearch.hadoop.cfg.PropertiesSettings
import org.elasticsearch.spark.cfg.SparkSettingsManager
import org.elasticsearch.hadoop.cfg.Settings
import org.elasticsearch.hadoop.rest.RestRepository
import scala.collection.JavaConversions._ // 为方便测试,下面是自己用scala实现的es hash函数
// 尤其注意:在生产环境下,使用ES jar包里的函数,位置为:
// https://github.com/elastic/elasticsearch/blob/master/core/src/main/java/org/elasticsearch/cluster/routing/Murmur3HashFunction.java
object Murmur3HashFunction {
def hash(routing: String): Int = {
val bytesToHash = Array.ofDim[Byte](routing.length * 2)
for (i <- 0 until routing.length) {
val c = routing.charAt(i)
val b1 = c.toByte
val b2 = (c >>> 8).toByte
assert(((b1 & 0xFF) | ((b2 & 0xFF) << 8)) == c)
bytesToHash(i * 2) = b1
bytesToHash(i * 2 + 1) = b2
}
hash(bytesToHash, 0, bytesToHash.length)
} def hash(bytes: Array[Byte], offset: Int, length: Int): Int = {
murmurhash3_x86_32(bytes, offset, length, 0)
} def murmurhash3_x86_32(data: Array[Byte],
offset: Int,
len: Int,
seed: Int): Int = {
val c1 = 0xcc9e2d51
val c2 = 0x1b873593
var h1 = seed
val roundedEnd = offset + (len & 0xfffffffc)
var i = offset
while (i < roundedEnd) {
var k1 = (data(i) & 0xff) | ((data(i + 1) & 0xff) << 8) | ((data(i + 2) & 0xff) << 16) |
(data(i + 3) << 24)
k1 *= c1
k1 = (k1 << 15) | (k1 >>> 17)
k1 *= c2
h1 ^= k1
h1 = (h1 << 13) | (h1 >>> 19)
h1 = h1 * 5 + 0xe6546b64
i += 4
}
var k1 = 0
len & 0x03 match {
case 3 => k1 = (data(roundedEnd + 2) & 0xff) << 16
case 2 => k1 |= (data(roundedEnd + 1) & 0xff) << 8
case 1 =>
k1 |= (data(roundedEnd) & 0xff)
k1 *= c1
k1 = (k1 << 15) | (k1 >>> 17)
k1 *= c2
h1 ^= k1
case _ => //break
}
h1 ^= len
h1 ^= h1 >>> 16
h1 *= 0x85ebca6b
h1 ^= h1 >>> 13
h1 *= 0xc2b2ae35
h1 ^= h1 >>> 16
h1
}
} // 自定义Partitioner
class ESShardPartitioner(settings: String) extends Partitioner {
protected var _numPartitions = -1 override def numPartitions: Int = {
val newSettings = new PropertiesSettings().load(settings)
// 生产环境下,需要自行设置索引的 index/type,我是以web/blog作为实验的index
newSettings.setResourceRead("web/blog") // ******************** !!! modify it !!! ********************
newSettings.setResourceWrite("web/blog") // ******************** !!! modify it !!! ********************
val repository = new RestRepository(newSettings)
val targetShards = repository.getWriteTargetPrimaryShards(newSettings.getNodesClientOnly())
repository.close()
_numPartitions = targetShards.size()
_numPartitions
} override def getPartition(docID: Any): Int = {
var shardId = Murmur3HashFunction.hash(docID.toString()) % _numPartitions;
if (shardId < 0) {
shardId += _numPartitions;
}
shardId
}
} sc.getConf.setMaster("local").setAppName("RDDTest").set("es.nodes", "127.0.0.1").set("spark.serializer", "org.apache.spark.serializer.KryoSerializer").set("es.index.auto.create", "true");
val ssc = new StreamingContext(sc, Seconds(2));
val fileStream = ssc.textFileStream("/tmp/data"); fileStream.foreachRDD { rdd => {
def makeItem(content: String) : (String, Map[String,String]) = {
val uuid = java.util.UUID.randomUUID.toString();
(uuid, Map("content"->content, "uuid"->uuid))
}
println("********************start*************************");
var r2 = rdd.map(makeItem);
val sparkCfg = new SparkSettingsManager().load(rdd.sparkContext.getConf)
val settings = sparkCfg.save();
var r3 = r2.partitionBy(new ESShardPartitioner(settings));
r3.map(x=>x._2).saveToEs("web/blog")
println("data count: " + rdd.count.toString);
println("*********************end************************");
}}; ssc.start();
ssc.awaitTermination();
运行方法:
./spark-shell --jars ../lib/elasticsearch-spark-1.2_2.10-2.1.2.jar
然后在spark shell里运行上述代码。
通过shell 伪造数据:
mkdir /mmp/data
#rm -rf /tmp/ ata"
rm -f "/tmp/data/*"
for ((j=;j<;j++)); do
{
for ((i=;i<;i++)); do
file_name=`python -c 'import random;print random.random()'`
echo "$j $i is sad story." >"/tmp/data/$file_name.log"
done
sleep
}
done
echo "OK, waiting..."
echo "done"
运行上述脚本,看到spark shell里显示:
见http://www.cnblogs.com/bonelee/p/6078956.html ES路由底层实现!
自定义Spark Partitioner提升es-hadoop Bulk效率的更多相关文章
- 自定义Spark Partitioner提升es-hadoop Bulk效率——续
对于es 2.4版本,要能定制spark partitioner需要如下方式启动spark shell: spark-2.0.0-bin-hadoop2.6/bin/spark-shell --jar ...
- Spark自定义分区(Partitioner)
我们都知道Spark内部提供了HashPartitioner和RangePartitioner两种分区策略,这两种分区策略在很多情况下都适合我们的场景.但是有些情况下,Spark内部不能符合咱们的需求 ...
- 提升 Hive Query 执行效率 - Hive LLAP
从 Hive 刚推出到现在,得益于社区对它的不断贡献,使得 Hive执行 query 效率显著提升.其中比较有代表性的功能如 Tez (将多个 job整合为一个DAG job)以及 CBO(Cost- ...
- 提升你的开发效率,10 个 NPM 使用技巧
对于一个项目,常用的一些npm简单命令包含的功能有:初始化一个文件夹(npm init),下载npm模块(npm install),创建测试(npm test) 和自定义脚本(npm run).但是, ...
- atitit.提升软件开发的效率and 质量的那些强大概念and方法总结
atitit.提升软件开发的效率and 质量的那些强大概念and方法总结 1. 主流编程中三个最糟糕的问题 1 1.1. 从理解问题后到实现的时间很长 1 1.2. 理解和维护代码 2 1.3. 学 ...
- Spark环境搭建(五)-----------Spark生态圈概述与Hadoop对比
Spark:快速的通用的分布式计算框架 概述和特点: 1) Speed,(开发和执行)速度快.基于内存的计算:DAG(有向无环图)的计算引擎:基于线程模型: 2)Easy of use,易用 . 多语 ...
- 面试系列九 es 提高查询效率
,es性能优化是没有什么银弹的,啥意思呢?就是不要期待着随手调一个参数,就可以万能的应对所有的性能慢的场景.也许有的场景是你换个参数,或者调整一下语法,就可以搞定,但是绝对不是所有场景都可以这样. 一 ...
- 分布式协同AI基准测试项目Ianvs:工业场景提升5倍研发效率
摘要:全场景可扩展的分布式协同AI基准测试项目 Ianvs(雅努斯),能为算法及服务开发者提供全面开发套件支持,以研发.衡量和优化分布式协同AI系统. 本文分享自华为云社区<KubeEdge|分 ...
- CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率
CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率 当场景中有比较复杂的模型时,条件渲染能够加速对复杂模型的渲染. 条件渲染(Conditio ...
随机推荐
- P3810 【模板】三维偏序(陌上花开)
P3810 [模板]三维偏序(陌上花开) cdq分治+树状数组 三维偏序模板题 前两维用cdq分治,第三维用树状数组进行维护 就像用树状数组搞逆序对那样做--->存权值的出现次数 attenti ...
- Delphi XE5 for Android (五)
Android程序开发必然用到按钮,在XE5下,按钮的一个比较重要的属性就是StyleLookup,预置了一系列常用的图标,如下图: 另外2个常用属性就是: GroupName和IsPressed:一 ...
- Linux驱动模块的Makefile分析【转】
本文转载自:http://blog.chinaunix.net/uid-29307109-id-3993784.html 1. 获取内核版本 当设备驱动需要同时支持不同版本内核时,在编译阶段,内核模块 ...
- 64bit ubuntu如何使能安装32bit软件
答:使用一下命令即可: sudo dpkg --add-architecture i386
- 棋盘状态压缩dp
状态压缩入门DP整理 只针对入门 一般都是用2进制的方法,压缩成一个数,所以n的范围都会特变小 一些套路 状态一般是很多的,可以搜索或者位运算筛选一下,基本都是这样的吧 当要存两个状态或者数组存不下的 ...
- 史丰收速算|2014年蓝桥杯B组题解析第四题-fishers
史丰收速算 史丰收速算法的革命性贡献是:从高位算起,预测进位.不需要九九表,彻底颠覆了传统手算! 速算的核心基础是:1位数乘以多位数的乘法. 其中,乘以7是最复杂的,就以它为例. 因为,1/7 是个循 ...
- ISSCC 2017论文导读 Session 14:A 0.62mW Ultra-Low-Power Convolutional-Neural-Network Face-Recognition Pro
A 0.62mW Ultra-Low-Power Convolutional-Neural-Network Face-Recognition Processor and a CIS Integrate ...
- 【入门教程】kafka环境搭建以及基础教程
问题导读 1.Kafka独特设计在什么地方?2.Kafka如何搭建及创建topic.发送消息.消费消息?3.如何书写Kafka程序?4.数据传输的事务定义有哪三种?5.Kafka判断一个节点是否活着有 ...
- Android Studio Design界面不显示layout控件的解决方法
发现更改了 layout里面的xml文件后 切换到design后,没有显示控件 解决方法 解决办法: 在 res/values/styles.xml 文件中 将原有的 前面添加 Base. The ...
- BZOJ2724 [Violet]蒲公英 分块
题目描述 经典区间众数题目 然而是权限题,所以题目链接放Luogu的 题解 因为太菜所以只会$O(n*\sqrt{n}+n*\sqrt{n}*log(n))$的做法 就是那种要用二分的,并不会clj那 ...