基于Hadoop2.7.1 + Hbase 1.2.1 + HbaseClientAPI 1.2.8
1 | package com.jd.union.spark |
基于Hadoop2.7.1 + Hbase 1.2.1 + HbaseClientAPI 1.2.8
1 | package com.jd.union.spark |
读了上面的小故事,是不是觉得对ElasticSearch的前世今生,兴趣十足呢?!我计划写一篇ElasticSearch的系列学习笔记,深入浅出,不仅方便大家学习,还能够让我更加深入的了解这门技术。学习一门新技术的第一课就是hello world.
接下来的章节,实操ElasticSearch hello world。
许多年前,一个刚结婚的名叫 Shay Banon 的失业开发者,跟着他的妻子去了伦敦,他的妻子在那里学习厨师(感觉国内的女生很少有喜欢做饭的,反而男生喜欢做饭)。 在寻找一个赚钱的工作的时候,为了给他的妻子做一个食谱搜索引擎,他开始使用 Lucene 的一个早期版本。
直接使用 Lucene 是很难的,因此 Shay 开始做一个抽象层,Java 开发者使用它可以很简单的给他们的程序添加搜索功能。 他发布了他的第一个开源项目 Compass。
后来 Shay 获得了一份工作,主要是高性能,分布式环境下的内存数据网格。这个对于高性能,实时,分布式搜索引擎的需求尤为突出, 他决定重写 Compass,把它变为一个独立的服务并取名 Elasticsearch。
第一个公开版本在2010年2月发布,从此以后,Elasticsearch 已经成为了 Github 上最活跃的项目之一,他拥有超过300名 contributors(目前736名 contributors )。 一家公司已经开始围绕 Elasticsearch 提供商业服务,并开发新的特性,但是,Elasticsearch 将永远开源并对所有人可用。
据说,Shay 的妻子还在等着她的食谱搜索引擎…
读了上面的小故事,是不是觉得对ElasticSearch的前世今生,兴趣十足呢?!我计划写一篇ElasticSearch的系列学习笔记,深入浅出,不仅方便大家学习,还能够让我更加深入的了解这门技术。学习一门新技术的第一课就是hello world.
接下来的章节,实操ElasticSearch hello world。
1、Java环境的安装配置
2、brew install elasticSearch(仅适用于Mac)
3、brew info elasticSearch,会显示如下信息表示安装成功
elasticSearch: stable 6.2.4, HEAD
Distributed search & analytics engine
https://www.elastic.co/products/elasticsearch
/usr/local/Cellar/elasticSearch/6.2.4 (112 files, 30.8MB)
Built from source on 2018-05-29 at 11:10:53
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/elasticsearch.rb
==> Requirements
Required: java = 1.8 ✔
==> Options
--HEAD
Install HEAD version
==> Caveats
4、brew services start elasticsearch
启动后localhost:9200,打印如下,说明ElasticSearch启动成功
{
"name" : "yptOhLD",
"cluster_name" : "elasticsearch_1",
"cluster_uuid" : "_na_",
"version" : {
"number" : "6.2.4",
"build_hash" : "ccec39f",
"build_date" : "2018-04-12T20:37:28.497551Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
5、brew install kibana(仅适用于Mac)
6、brew services start kibana
7、打开kibana localhost:5601
基于以上7个步骤,环境问题搞定,下面来真实的操作一下ElasticSearch。
curl -XPUT "http://localhost:9200/goods_index"
curl -XGET "http://localhost:9200/goods_index"
{
"goods_index": { #索引名称
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1530627979046",
"number_of_shards": "5", #5个分片
"number_of_replicas": "1", #一个备份
"uuid": "kTy_hHlQQRaVPygKHZpUYQ",
"version": {
"created": "6020499"
},
"provided_name": "goods_index"
}
}
}
}
curl -XPUT "http://localhost:9200/goods_index/goods/12343333" -H 'Content-Type:application/json' -d'
{
"skuName": "华为手机",
"url":"https://item.jd.com/6946605.html"
}'
索引数据之后,再执行查看索引详情,会发现mappings属性多了一个名字叫goods的type,goods下面多了skuName和url两个properties。
{
"goods_index": {
"aliases": {},
"mappings": {
"goods": {
"properties": {
"skuName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"url": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
},
"settings": {
"index": {
"creation_date": "1530627979046",
"number_of_shards": "5",
"number_of_replicas": "1",
"uuid": "kTy_hHlQQRaVPygKHZpUYQ",
"version": {
"created": "6020499"
},
"provided_name": "goods_index"
}
}
}
}
curl -XGET "http://localhost:9200/goods_index/goods/_search"
执行上面的查询语句,得到如下的结果集。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "goods_index",
"_type": "goods",
"_id": "12343333",
"_score": 1,
"_source": {
"skuName": "华为手机",
"url": "https://item.jd.com/6946605.html"
}
}
]
}
}
ElasticSearch的Hello world,是不是比java,python难一些呢?不过还好,一个检索系统,就此拉开了帷幕。这就是ElasticSearch推崇的“开箱即用”的理念。但是要学好ElasticSearch可不是一件容易的事情,细心的同学,可能会发现有一些细节:
1、什么是索引?
2、什么是文档?
3、索引和文档是什么样的关系?
……
请持续关注我的博客,我们逐渐从ElasticSearch小白,变成大牛。
转自:https://donlianli.iteye.com/blog/2094305
es在查询时,可以指定搜索类型为QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCH和DFS_QUERY_AND_FEATCH。那么这4种搜索类型有什么区别?
分布式搜索背景介绍:
ES天生就是为分布式而生,但分布式有分布式的缺点。比如要搜索某个单词,但是数据却分别在5个分片(Shard)上面,这5个分片可能在5台主机上面。因为全文搜索天生就要排序(按照匹配度进行排名),但数据却在5个分片上,如何得到最后正确的排序呢?ES是这样做的,大概分两步。
step1、ES客户端会将这个搜索词同时向5个分片发起搜索请求,这叫Scatter,
step2、这5个分片基于本Shard独立完成搜索,然后将符合条件的结果全部返回,这一步叫Gather。
客户端将返回的结果进行重新排序和排名,最后返回给用户。也就是说,ES的一次搜索,是一次scatter/gather过程(这个跟mapreduce也很类似).
然而这其中有两个问题。
第一、数量问题。比如,用户需要搜索”双黄连”,要求返回最符合条件的前10条。但在5个分片中,可能都存储着双黄连相关的数据。所以ES会向这5个分片都发出查询请求,并且要求每个分片都返回符合条件的10条记录。当ES得到返回的结果后,进行整体排序,然后取最符合条件的前10条返给用户。这种情况,ES5个shard最多会收到10*5=50条记录,这样返回给用户的结果数量会多于用户请求的数量。
第二、排名问题。上面搜索,每个分片计算分值都是基于自己的分片数据进行计算的。计算分值使用的词频率和其他信息都是基于自己的分片进行的,而ES进行整体排名是基于每个分片计算后的分值进行排序的,这就可能会导致排名不准确的问题。如果我们想更精确的控制排序,应该先将计算排序和排名相关的信息(词频率等)从5个分片收集上来,进行统一计算,然后使用整体的词频率去每个分片进行查询。
这两个问题,估计ES也没有什么较好的解决方法,最终把选择的权利交给用户,方法就是在搜索的时候指定query type。
1、query and fetch
向索引的所有分片(shard)都发出查询请求,各分片返回的时候把元素文档(document)和计算后的排名信息一起返回。这种搜索方式是最快的。因为相比下面的几种搜索方式,这种查询方法只需要去shard查询一次。但是各个shard返回的结果的数量之和可能是用户要求的size的n倍。
2、query then fetch(默认的搜索方式)
如果你搜索时,没有指定搜索方式,就是使用的这种搜索方式。这种搜索方式,大概分两个步骤,第一步,先向所有的shard发出请求,各分片只返回排序和排名相关的信息(注意,不包括文档document),然后按照各分片返回的分数进行重新排序和排名,取前size个文档。然后进行第二步,去相关的shard取document。这种方式返回的document与用户要求的size是相等的。
3、DFS query and fetch
这种方式比第一种方式多了一个初始化散发(initial scatter)步骤,有这一步,据说可以更精确控制搜索打分和排名。
4、DFS query then fetch
比第2
种
方式多了一个
初始化散发(initial scatter)步骤。
DSF是什么缩写?初始化散发是一个什么样的过程?
从es的官方网站我们可以指定,初始化散发其实就是在进行真正的查询之前,先把各个分片的词频率和文档频率收集一下,然后进行词搜索的时候,各分片依据全局的词频率和文档频率进行搜索和排名。显然如果使用DFS_QUERY_THEN_FETCH这种查询方式,效率是最低的,因为一个搜索,可能要请求3次分片。但,使用DFS方法,搜索精度应该是最高的。
至于DFS是什么缩写,没有找到相关资料,这个D可能是Distributed,F可能是frequency的缩写,至于S可能是Scatter的缩写,整个单词可能是分布式词频率和文档频率散发的缩写。
总结一下,从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。从搜索的准确度来说,DFS要比非DFS的准确度更高。
1 | brew install mysql |
CREATE USER ‘test‘@’%’ IDENTIFIED BY ‘root@12’;
grant all privileges on . to ‘test‘@’%’;
Flush privileges;
下载Sequel Pro开始使用
本节主要介绍下ElasticSearch 理论基础。知其然知其所以然,如下的理论和算法,就是ElasticSearch的魂!
转自:https://www.felayman.com/articles/2017/11/10/1510291087246.html
Elasticsearch版本为 5.5.1
如果运行gradle idea会报如下错误:请修改elasticsearch源文件中的BuildPlugin.groory文件中的findJavaHome()方法的第一行代码,源码为 String javaHome = System.getenv(‘JAVA_HOME’),修改为String javaHome = “你的JAVA_HOME地址,输入echo $JAVA_HOME($)”
1 | What went wrong: |
这里我使用的是idea工具来调试源码,因此先不要用idea导入该项目,而是进入到下载的elasticsearch目录下,执行gradle idea,等待漫长的依赖下载,等待下载完成后 执行 gradle build -x test 对源码进行编译,等待编译完成.
1 | [2017-07-11T22:00:08,396][INFO ][o.e.n.Node ] [] initializing ... |
ERROR: the system property [es.path.conf] must be set
原因是没有指定es.path.conf,设置-Des.path.conf=你调试源码版本对应的conf目录
Exception in thread “main” java.lang.IllegalStateException: path.home is not configured
原因是因为没有为elasticsearch配置path.home参数,可以在Edit Configuation中设置虚拟机参数:-Des.path.home=你下载的对应的elasticsearch的安装目录,这么做的原因
是elasticsearch在启动中会加载一些默认配置以及插件,我们直接加载elasticsearch安装目录下的配置和插件即可,后面会在源码中体现
2017-06-23 14:00:44,760 main ERROR Could not register mbeans java.security.AccessControlException: access denied (“javax.management.MBeanTrustPermission” “register”)
原因是因为elasticsearch在启动过程中使用到了jmx,我们这里禁止使用即可,配置也是在Edit Configuation中设置虚拟机参数 -Dlog4j2.disable.jmx=true
org.elasticsearch.bootstrap.StartupException: org.elasticsearch.bootstrap.BootstrapException: java.lang.IllegalStateException: jar hell!或Classname: org.elasticsearch.search.aggregations.matrix.MatrixAggregationPlugin due to jar hell
原因是因为elasticsearch中大量存在一个类或一个资源文件存在多个jar中,我们注释掉相应代码即可,主要是PluginsService中374行的JarHell.checkJarHell(union)以及
Bootstrap中220行的JarHell.checkJarHell(),最简单的方式就是将JarHell.checkJarHell()中的方法体注释掉
org.elasticsearch.bootstrap.StartupException: java.lang.IllegalArgumentException: plugin [aggs-matrix-stats] is incompatible with version [7.0.0-alpha1]; was designed for version [5.6.1]
原因是一般情况下我们调试的源码非某个发布版本,有些配置项并未发布,我们的配置与当前代码的版本匹配不上,这个时候我们需要将调试的源码设置成某个发布版本,一般来说,Elasticsearch每发布
一个稳定版本,都会有一个对应的tag,我们进入到ES源码目录下执行git tag, 我这里调试的版本为v5.6.1,所以执行git checkout v5.6.1,切换到v5.6.1tag.
如果上面第五个报错之后解决不了无法继续进行,可以选择这种方式:
在 Elasticsearch 源码目录下打开 CMD,输入下面的命令启动一个 debug 实例
1 | gradle run --debug-jvm |
如果启动失败可能需要先执行 gradle clean
再 gradle run --debug-jvm
或者 先退出 IDEA
在 IDEA 中打开 Edit Configurations
,添加 remote
配置 host 和 port
点击 debug,浏览器访问 http://localhost:9200/
,即可看到ES返回的信息
随机调试一下, 打开 elasticsearch/server/src/main/org/elasticsearch/rest/action/cat
下的 RestHealthAction
类,在第 54 行出设置一个断点,然后浏览器访问 http://localhost:9200/_cat/health
,可以看到断点已经捕获到该请求了
运行成功,可以开始设置断点进行其他调试
在es源码根目录,执行 gradle assemble 命令,编译好之后工程ZIP包位于下图位置。
1. 错误信息如下
1 | JAVA8_HOME required to run tasks gradle |
配置环境变量 JAVA8_HOME
,值为 JDK8 的安装目录
2. 错误信息如下
1 | [2018-08-22T13:07:23,197][INFO ][o.e.t.TransportService ] [EFQliuV] publish_address {10.100.99.118:9300}, bound_addresses {[::]:9300} |
在 Edit Configurations
的 VM options
加入下面配置
-Xms2g
-Xmx2g