文章目录
分布式搜索引擎ElasticSearch
学习目标
- 了解Elasticsearch的特点及体系结构
- 完成Elasticsearch安装,能够调用RestAPI完成基本增删改查操作
- 完成Head插件安装,熟悉Head插件的基本使用方法
- 完成IK分词器的安装,能够使用IK分词器进行分词
- 使用SpringDataElasticsearch完成搜索微服务的开发(重点)
- 使用logstash完成mysql与Elasticsearch的同步工作
- 完成Elasticsearch在docker下的安装
1 ElasticSearch简介
1.1 什么是ElasticSearch
Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
讲课中画了一张图解释作用
1.2 ElasticSearch特点
-
可以作为一个大型分布式集群(数百台服务器)技术,处理PB级数据,服务大公司;也可以运行在单机上
-
将全文检索、数据分析以及分布式技术,合并在了一起,才形成了独一无二的ES;
-
开箱即用的,部署简单
-
全文检索,同义词处理,相关度排名,复杂数据分析,海量数据的近实时处理
1.3 ElasticSearch体系结构
下表是Elasticsearch与MySQL数据库逻辑结构概念的对比
Elasticsearch | 关系型数据库Mysql |
---|---|
索引(index) | 数据库(databases) |
类型(type) | 表(table) |
文档(document) | 行(row) |
2 安装ElasticSearch,IK,head
2.1 在windows环境下部署与启动
2.1.1 ElasticSearch部署与启动
下载ElasticSearch 5.6.8版本
https://www.elastic.co/downloads/past-releases/elasticsearch-5-6-8
资源\配套软件中也提供了安装包
无需安装,解压安装包后即可使用
在命令提示符下,进入ElasticSearch安装目录下的bin目录,执行命令
elasticsearch
即可启动。
我们打开浏览器,在地址栏输入http://127.0.0.1:9200/ 即可看到输出结果
9300是java用,9200是其他用
{
"name" : "uV2glMR",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "RdV7UTQZT1-Jnka9dDPsFg",
"version" : {
"number" : "5.6.8",
"build_hash" : "688ecce",
"build_date" : "2018-02-16T16:46:30.010Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}
2.1.2 Head插件的安装
-
下载head插件:https://github.com/mobz/elasticsearch-head
配套资料中已提供。 elasticsearch-head-master.zip
-
解压到任意目录,但是要和elasticsearch的安装目录区别开。
-
安装node js ,安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
-
将grunt安装为全局命令 。Grunt是基于Node.js的项目构建工具。它可以自动运行你所设定的任务
npm install -g grunt-cli
-
安装依赖
cnpm install
-
进入head目录启动head,在命令提示符下输入命令
grunt server
-
打开浏览器,输入 http://localhost:9100
-
点击连接按钮没有任何相应,按F12发现有如下错误
No 'Access-Control-Allow-Origin' header is present on the requested resource
这个错误是由于elasticsearch默认不允许跨域调用,而elasticsearch-head是属于前端工程,所以报错。
我们这时需要修改elasticsearch的配置,让其允许跨域访问。
修改elasticsearch配置文件:elasticsearch.yml,增加以下两句命令:
http.cors.enabled: true http.cors.allow-origin: "*"
此步为允许elasticsearch跨越访问,点击连接即可看到相关信息
2.1.3 IK分词器的安装
下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
下载5.6.8版本,课程配套资源也提供了: 资源\配套软件\elasticsearch\elasticsearch-analysis-ik-5.6.8.zip
- 先将其解压,将解压后的elasticsearch文件夹重命名文件夹为ik
- 将ik文件夹拷贝到elasticsearch/plugins 目录下。
- 重新启动,即可加载IK分词器3。重新启动,即可加载IK分词器
2.2 Elasticsearch在Docker环境下安装
2.2.1 容器的创建与远程连接
-
下载镜像
hub.docker.com上查到的版本没有lasted,只有版本号
6.5.1 (6/Dockerfile)
5.6.13, 5.6, 5 (5/Dockerfile)
5.6.13-alpine, 5.6-alpine, 5-alpine (5/alpine/Dockerfile)
docker pull elasticsearch:5
-
创建容器
docker run -di --name=tensquare_elasticsearch -p 9200:9200 -p 9300:9300 elasticsearch:5
启动出错,查看docker日志命令
$ sudo docker logs -f -t --tail 行数 容器名
例:实时查看docker容器名为s12的最后10行日志$ sudo docker logs -f -t --tail 10 s12
如果启动容器出错,一般是内存大小问题,es5默认2g,解决办法参考
https://blog.csdn.net/qq_35022052/article/details/81584014
https://blog.csdn.net/wangshuminjava/article/details/79189953 -
浏览器输入地址:
http://192.168.184.134:9200/ 即可看到如下信息
{ "name" : "WmBn0H-", "cluster_name" : "elasticsearch", "cluster_uuid" : "2g-VVbm9Rty7J4sksZNJEg", "version" : { "number" : "5.6.8", "build_hash" : "688ecce", "build_date" : "2018-02-16T16:46:30.010Z", "build_snapshot" : false, "lucene_version" : "6.6.1" }, "tagline" : "You Know, for Search" }
-
我们修改demo的application.yml
spring: data: elasticsearch: cluster-nodes: 192.168.184.135:9300
-
运行测试程序,发现会报如下错误
NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{exvgJLR-RlCNMJy-hzKtnA}{192.168.184.135}{192.168.184.135:9300}] ] at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:347) at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:245) at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59)
这是因为elasticsearch从5版本以后默认不开启远程连接,需要修改配置文件
-
我们进入容器
docker exec -it tensquare_elasticsearch /bin/bash
此时,我们看到elasticsearch所在的目录为/usr/share/elasticsearch ,进入config看到了配置文件
elasticsearch.yml
我们通过vi命令编辑此文件,尴尬的是容器并没有vi命令 ,咋办?我们需要以文件挂载的方式创建容器才行,这样我们就可以通过修改宿主机中的某个文件来实现对容器内配置文件的修改
-
拷贝配置文件到宿主机
首先退出容器,然后执行命令:
docker cp tensquare_elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml /usr/share/elasticsearch.yml
-
停止和删除原来创建的容器
docker stop tensquare_elasticsearch docker rm tensquare_elasticsearch
-
修改/usr/share/elasticsearch.yml 将
transport.host: 0.0.0.0
前的#去掉后保存文件退出。其作用是允许任何ip地址访问elasticsearch .开发测试阶段可以这么做,生产环境下指定具体的IP -
重新执行创建容器命令
docker run -di --name=tensquare_elasticsearch -p 9200:9200 -p 9300:9300 -v /usr/share/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml elasticsearch:5.6.8
-
也可以先创建容器,改文件后,重启启动
docker restart tensquare_elasticsearch
重启后发现重启启动失败了,这时什么原因呢?这与我们刚才修改的配置有关,因为elasticsearch在启动的时候会进行一些检查,比如最多打开的文件的个数以及虚拟内存区域数量等等,如果你放开了此配置,意味着需要打开更多的文件以及虚拟内存,所以我们还需要系统调优。
-
系统调优
我们一共需要修改两处
修改/etc/security/limits.conf ,追加内容
* soft nofile 65536 * hard nofile 65536
nofile是单个进程允许打开的最大文件个数,soft nofile是软限制,hard nofile是硬限制
修改/etc/sysctl.conf,追加内容
vm.max_map_count=655360
限制一个进程可以拥有的VMA(虚拟内存区域)的数量
执行下面命令 修改内核参数马上生效
sysctl -p
-
重新启动虚拟机,再次启动容器,发现已经可以启动并远程访问
2.2.2 IK分词器安装
-
快捷键alt+p进入sftp , 将ik文件夹上传至宿主机
sftp> put -r d:\setup\ik
-
在宿主机中将ik文件夹拷贝到容器内 /usr/share/elasticsearch/plugins 目录下。
docker cp ik tensquare_elasticsearch:/usr/share/elasticsearch/plugins/
-
重新启动,即可加载IK分词器
docker restart tensquare_elasticsearch
2.2.3 HEAD插件安装
-
修改/usr/share/elasticsearch.yml ,添加允许跨域配置
http.cors.enabled: true http.cors.allow-origin: "*"
-
重新启动elasticseach容器
-
下载head镜像(此步省略)
docker pull mobz/elasticsearch-head:5
-
创建head容器
docker run -di --name=myhead -p 9100:9100 mobz/elasticsearch-head:5
3 Postman调用RestAPI
3.1 新建索引
例如我们要创建一个叫articleindex的索引 ,就以put方式提交
http://127.0.0.1:9200/articleindex/
3.2 新建文档
以post方式提交 http://127.0.0.1:9200/articleindex/article
body:
{
"title":"SpringBoot2.0",
"content":"发布啦"
}
返回结果如下:
{
"_index": "articleindex",
"_type": "article",
"_id": "AWPKsdh0FdLZnId5S_F9",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
_id是由系统自动生成的。 为了方便之后的演示,我们再次录入几条测试数据。
3.3 查询全部文档
查询某索引某类型的全部数据,以get方式请求
http://127.0.0.1:9200/articleindex/article/_search
返回结果如下:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "articleindex",
"_type": "article",
"_id": "AWPKrI4pFdLZnId5S_F7",
"_score": 1,
"_source": {
"title": "SpringBoot2.0",
"content": "发布啦"
}
},
{
"_index": "articleindex",
"_type": "article",
"_id": "AWPKsdh0FdLZnId5S_F9",
"_score": 1,
"_source": {
"title": "elasticsearch入门",
"content": "零基础入门"
}
}
]
}
}
3.4 修改文档
以put形式提交以下地址:
http://192.168.184.134:9200/articleindex/article/AWPKrI4pFdLZnId5S_F7
body:
{
"title":"SpringBoot2.0正式版",
"content":"发布了吗"
}
返回结果:
{
"_index": "articleindex",
"_type": "article",
"_id": "AWPKsdh0FdLZnId5S_F9",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": false
}
如果我们在地址中的ID不存在,则会创建新文档
以put形式提交以下地址:
http://192.168.184.134:9200/articleindex/article/1
body:
{
"title":"十次方课程好给力",
"content":"知识点很多"
}
返回信息:
{
"_index": "articleindex",
"_type": "article",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
再次查询,看是否有新增的这条文档
3.5 按ID查询文档
GET方式请求
http://192.168.184.134:9200/articleindex/article/1
3.6 基本匹配查询
根据某列进行查询,get方式提交下列地址:
http://192.168.184.134:9200/articleindex/article/_search?q=title:十次方课程好给力
以上为按标题查询,返回结果如下:
{
"took": 10,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 2.0649285,
"hits": [
{
"_index": "articleindex",
"_type": "article",
"_id": "1",
"_score": 2.0649285,
"_source": {
"title": "十次方课程好给力",
"content": "知识点很多"
}
}
]
}
}
3.7 模糊查询
我们可以用*代表任意字符:
http://192.168.184.134:9200/articleindex/article/_search?q=title:*s*
3.8 删除文档
根据ID删除文档,删除ID为1的文档 DELETE方式提交
http://192.168.184.134:9200/articleindex/article/1
返回结果如下:
{
"found": true,
"_index": "articleindex",
"_type": "article",
"_id": "1",
"_version": 2,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
再次查看全部是否还存在此记录
4 Head插件的使用
如果都是通过rest请求的方式使用Elasticsearch,未免太过麻烦,而且也不够人性化。我们一般都会使用图形化界面来实现Elasticsearch的日常管理,最常用的就是Head插件
4.1 新建索引
选择“索引”选项卡,点击“新建索引”按钮
输入索引名称点击OK
4.2 新建或修改文档
在复合查询中提交地址,输入内容,提交方式为PUT
点击数据浏览 ,点击要查询的索引名称,右侧窗格中显示文档信息
点击文档信息:
我们再次回到刚才的界面
修改数据后重新提交请求 , 此时因为ID已经存在,所以执行的是修改操作。
重新查询此记录,发现版本为2 。也就是说每次修改后版本都会增加1.
4.3 搜索文档
4.4 删除文档
5 IK分词器使用
5.1 什么是IK分词器
IK分词是一款国人开发的相对简单的中文分词器。虽然开发者自2012年之后就不在维护了,但在工程应用中IK算是比较流行的一款!介绍一下使用方法。
我们在浏览器地址栏输入http://127.0.0.1:9200/_analyze?analyzer=chinese&pretty=true&text=我是程序员
,浏览器显示效果如下
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "<IDEOGRAPHIC>",
"position" : 0
},
{
"token" : "是",
"start_offset" : 1,
"end_offset" : 2,
"type" : "<IDEOGRAPHIC>",
"position" : 1
},
{
"token" : "程",
"start_offset" : 2,
"end_offset" : 3,
"type" : "<IDEOGRAPHIC>",
"position" : 2
},
{
"token" : "序",
"start_offset" : 3,
"end_offset" : 4,
"type" : "<IDEOGRAPHIC>",
"position" : 3
},
{
"token" : "员",
"start_offset" : 4,
"end_offset" : 5,
"type" : "<IDEOGRAPHIC>",
"position" : 4
}
]
}
默认的中文分词是将每个字看成一个词,这显然是不符合要求的,所以我们需要安装中文分词器来解决这个问题。
5.2 IK分词器测试
IK提供了两个分词算法ik_smart 和 ik_max_word
其中 ik_smart 为最少切分,ik_max_word为最细粒度划分
我们分别来试一下
-
最小切分:在浏览器地址栏输入地址
http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员
输出的结果为:
{ "tokens" : [ { "token" : "我", "start_offset" : 0, "end_offset" : 1, "type" : "CN_CHAR", "position" : 0 }, { "token" : "是", "start_offset" : 1, "end_offset" : 2, "type" : "CN_CHAR", "position" : 1 }, { "token" : "程序员", "start_offset" : 2, "end_offset" : 5, "type" : "CN_WORD", "position" : 2 } ] }
-
最细切分:在浏览器地址栏输入地址
http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是程序员
输出的结果为:
{ "tokens" : [ { "token" : "我", "start_offset" : 0, "end_offset" : 1, "type" : "CN_CHAR", "position" : 0 }, { "token" : "是", "start_offset" : 1, "end_offset" : 2, "type" : "CN_CHAR", "position" : 1 }, { "token" : "程序员", "start_offset" : 2, "end_offset" : 5, "type" : "CN_WORD", "position" : 2 }, { "token" : "程序", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 3 }, { "token" : "员", "start_offset" : 4, "end_offset" : 5, "type" : "CN_CHAR", "position" : 4 } ] }
5.3 自定义词库
我们现在测试"传智播客",浏览器的测试效果如下:
http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=传智播客
{
"tokens" : [
{
"token" : "传",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "智",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "播",
"start_offset" : 2,
"end_offset" : 3,
"type" : "CN_CHAR",
"position" : 2
},
{
"token" : "客",
"start_offset" : 3,
"end_offset" : 4,
"type" : "CN_CHAR",
"position" : 3
}
]
}
默认的分词并没有识别“传智播客”是一个词。如果我们想让系统识别“传智播客”是一个词,需要编辑自定义词库。
步骤:
-
进入elasticsearch/plugins/ik/config目录
-
新建一个my.dic文件,编辑内容:
传智播客
修改IKAnalyzer.cfg.xml(在ik/config目录下)
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">my.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
</properties>
重新启动elasticsearch,通过浏览器测试分词效果
{
"tokens" : [
{
"token" : "传智播客",
"start_offset" : 0,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 0
}
]
}
docker下暂时使用cp ik目录到容器中,然后重启容器的方法
[root@localhost ~]# docker cp /usr/local/docker/docker_file/elasticsearch/ik tensquare_elasticsearch:/usr/share/elasticsearch/plugins/
[root@localhost ~]# docker restart tensquare_elasticsearch
挂载方法会出现问题,暂时还没找到解决办法。
docker run -di --name=tensquare_elasticsearch -p 9200:9200 -p 9300:9300 -v /usr/share/elasticsearch.yml:/usr/local/docker/docker_file/elasticsearch/elasticsearch.yml -v /usr/share/elasticsearch/plugins/ik:/usr/local/docker/docker_file/elasticsearch/ik elasticsearch:5
解决办法:
- 修改文件路径。/user/改为/usr/
- docker挂载命令写反了。
docker run -di --name=tensquare_elasticsearch -p 9200:9200 -p 9300:9300 -v /usr/local/docker/docker_file/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch.yml -v /usr/local/docker/docker_file/elasticsearch/ik:/usr/share/elasticsearch/plugins/ik elasticsearch:5 ```