如果把Lucene比喻成一台发动机,那么Solr就是一台家用汽车,而Elasticsearch就是一台c超级跑车。
2.1.简介
Elastic官网:免费且开放的搜索:Elasticsearch、ELK 和 Kibana 的开发者 | Elastic
Elastic是一系列产品的集合,比较知名的是ELK技术栈,其核心就是ElasticSearch:
Elasticsearch官网:Elasticsearch:官方分布式搜索和分析引擎 | Elastic
Elasticsearch是一个基于Lucene的搜索web服务,对外提供了一系列的Rest风格的API接口。因此任何语言的客户端都可以通过发送Http请求来实现ElasticSearch的操作。
ES的主要优势特点如下:
-
速度快:Elasticsearch 很快,快到不可思议。我们通过有限状态转换器实现了用于全文检索的倒排索引,实现了用于存储数值数据和地理位置数据的 BKD 树,以及用于分析的列存储。而且由于每个数据都被编入了索引,因此您再也不用因为某些数据没有索引而烦心。您可以用快到令人惊叹的速度使用和访问您的所有数据。实现近实时搜索,海量数据更新在Elasticsearch中几乎是完全同步的。
-
扩展性高:可以在笔记本电脑上运行,也可以在承载了 PB 级数据的成百上千台服务器上运行。原型环境和生产环境可无缝切换;无论 Elasticsearch 是在一个节点上运行,还是在一个包含 300 个节点的集群上运行,您都能够以相同的方式与 Elasticsearch 进行通信。它能够水平扩展,每秒钟可处理海量事件,同时能够自动管理索引和查询在集群中的分布方式,以实现极其流畅的操作。天生的分布式设计,很容易搭建大型的分布式集群(solr使用Zookeeper作为注册中心来实现分布式集群)
-
强大的查询和分析:通过 Elasticsearch,您能够执行及合并多种类型的搜索(结构化数据、非结构化数据、地理位置、指标),搜索方式随心而变。先从一个简单的问题出发,试试看能够从中发现些什么。找到与查询最匹配的 10 个文档是一回事。但如果面对的是十亿行日志,又该如何解读呢?Elasticsearch 聚合让您能够从大处着眼,探索数据的趋势和模式。如全文检索,同义词处理,相关度排名,复杂数据分析。
-
操作简单:客户端API支持Restful风格,简单容易上手。
使用ES的案例场景:
1、GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB 的数据,包括13亿文件和1300亿行代码”
2、维基百科:启动以elasticsearch为基础的核心搜索架构
3、SoundCloud:“SoundCloud使用ElasticSearch为1.8亿用户提供即时而精准的音乐搜索服务”
4、百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据。 新浪使用ES 分析处理32亿条实时日志。
5、阿里使用ES 构建自己的日志采集和分析体系
6、京东到家订单中心 Elasticsearch 演进历程
Elasticsearch 做为一款功能强大的分布式搜索引擎,支持近实时的存储、搜索数据,在京东到家订单系统中发挥着巨大作用,目前订单中心ES集群存储数据量达到10亿个文档,日均查询量达到5亿。
7、滴滴 2016 年初开始构建 Elasticsearch 平台,如今已经发展到超过 3500+ Elasticsearch 实例,超过 5PB 的数据存储,峰值写入 tps 超过了 2000w/s 的超大规模。
8、携程Elasticsearch应用案例
9、去哪儿:订单中心基于elasticsearch 的解决方案
......
本章是基于Docker安装
2.1 安装ElasticSearch
docker run -id --name elasticsearch \ -e "cluster.name=elastic-cluster" \ -e "http.host=0.0.0.0" \ -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \ -e "discovery.type=single-node" \ -e http.cors.enabled=true \ -e http.cors.allow-origin="*" \ -e http.cors.allow-headers=X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization \ -e http.cors.allow-credentials=true \ -v es-data:/usr/share/elasticsearch/data \ -v es-logs:/usr/share/elasticsearch/logs \ -v es-plugins:/usr/share/elasticsearch/plugins \ --privileged \ --hostname elasticsearch \ -p 9200:9200 -p 9300:9300 elasticsearch:7.4.2
命令解释:
-
-e "cluster.name=es-docker-cluster"
:设置集群名称 -
-e "http.host=0.0.0.0"
:监听的地址,可以外网访问 -
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
:内存大小 -
-e "discovery.type=single-node"
:非集群模式 -
-v es-data:/usr/share/elasticsearch/data
:挂载逻辑卷,绑定es的数据目录 -
-v es-logs:/usr/share/elasticsearch/logs
:挂载逻辑卷,绑定es的日志目录 -
-v es-plugins:/usr/share/elasticsearch/plugins
:挂载逻辑卷,绑定es的插件目录 -
--privileged
:授予逻辑卷访问权 -
-p 9200:9200
:端口映射配置
restart相关参数如下:
选项 | 作用 |
---|---|
--restart=no | 不自动重启容器. (默认) |
--restart=on-failure | 容器发生error而退出(容器退出状态不为0)重启容器 |
on-failure:3 | 在容器非正常退出时重启容器,最多重启3次 |
--restart=unless-stopped | 在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器 |
--restart=always | 在容器已经stop掉或Docker stoped/restarted的时候才重启容器 |
如果已经启动的容器项目,则使用update更新:
docker update --restart=always 容器名/ID
防火墙配置:
# 开放端口 9200 9300 5601 firewall-cmd --zone=public --add-port=9200/tcp --permanent # 重启防火墙 firewall-cmd --reload # 查看放行端口 firewall-cmd --list-ports
2.2 Kibana
ES提供了多种访问方式,官方推荐使用REST API,也是使用人数最多的访问方式。就是通过http协议,使用Restful的风格,按照es的api去操作数据,访问时我们需要传递给es json 参数,es处理后会给我们返回 json 的结果,不过浏览器不方便操作es 官方推荐使用kibana来操作ES
2.2.1 Kibana简介
Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等。
而且还提供了操作Elasticsearch索引数据的控制台,并且提供了一定的API提示,非常有利于我们学习Elasticsearch的语法。
2.2.2 安装Kibana
# 可以指定es地址:-e ELASTICSEARCH_URL=http://192.168.200.150:9200 # es和kibana在同一docker下 # 可以直接: --link后面的 es容器的名称:elasticsearch docker run -di --name kibana -p 5601:5601 --link elasticsearch:elasticsearch kibana:7.4.2
# Head 插件(了解) docker run -d --name es_admin -p 9100:9100 mobz/elasticsearch-head:5
输入地址访问:http://192.168.200.150:5601
2.3 分词器
根据我们之前讲解的倒排索引原理,当我们向elasticsearch插入一条文档数据时,elasticsearch需要对数据分词,分词到底如何完成呢?
ElasticSearch 内置分词器
-
Standard Analyzer - 默认分词器,按词切分,小写处理
-
Simple Analyzer - 按照非字母切分(符号被过滤), 小写处理
-
Stop Analyzer - 小写处理,停用词过滤(the,a,is)
-
Whitespace Analyzer - 按照空格切分,不转小写
-
Keyword Analyzer - 不分词,直接将输入当作输出
-
Patter Analyzer - 正则表达式,默认\W+(非字符分割)
-
Language - 提供了30多种常见语言的分词器
2.3.1 默认的分词器
kibana中可以测试分词器效果,我们来看看elasticsearch中的默认分词器。
在kibana的DevTools中输入一段命令:
POST /_analyze
{
"text": "程序员学习java太棒了",
"analyzer": "standard"
}
请求代表的含义:
-
请求方式:
POST
-
请求路径:
_analyze
,前面省略了http://127.0.0.1:9200,这个由Kibana帮我们补充 -
请求参数:风格,包含两个属性:
-
analyzer
:分词器名称,standard是默认的标准分词器 -
text
:要分词的文本内容
-
效果:
-
按词切分
-
单词大写变小写
2.3.2 IK分词器
标准分词器并不能很好处理中文,一般我们会用第三方的分词器,例如:IK分词器。
IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包,是一个基于Maven构建的项目,具有60万字/秒的高速处理能力,支持用户词典扩展定义。
IK分词器的 地址:GitHub - medcl/elasticsearch-analysis-ik: The IK Analysis plugin integrates Lucene IK analyzer into elasticsearch, support customized dictionary., 安装非常简单。
IK分词器可以用ik_max_word
和ik_smart
两种方式,分词粒度不同。
2.3.2.1 安装IK分词器
1、安装ik插件(在线较慢)
# 进入容器内部 docker exec -it elasticsearch /bin/bash # 在线下载并安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip #退出 exit #重启容器 docker restart elasticsearch
2、离线安装ik插件(推荐)
# 1、进入/var/lib/docker/volumes/es-plugins/_data/ cd /var/lib/docker/volumes/es-plugins/_data/ # 2、新建文件目录 ik 并且进入 mkdir ik cd ik # 3、解压elasticsearch-analysis-ik-7.4.2.zip yum -y install unzip unzip elasticsearch-analysis-ik-7.4.2.zip # 4、重启容器 docker restart elasticsearch# 查看es日志 docker logs -f elasticsearch
# 重启 Kibana
docker restart kibana
测试:
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "程序员学习java太棒了"
}
结果:
{
"tokens" : [
{
"token" : "程序员",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "程序",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "员",
"start_offset" : 4,
"end_offset" : 5,
"type" : "CN_CHAR",
"position" : 3
},
{
"token" : "学习",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "java",
"start_offset" : 7,
"end_offset" : 11,
"type" : "ENGLISH",
"position" : 5
},
{
"token" : "太棒了",
"start_offset" : 11,
"end_offset" : 14,
"type" : "CN_WORD",
"position" : 6
},
{
"token" : "太棒",
"start_offset" : 11,
"end_offset" : 13,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "了",
"start_offset" : 13,
"end_offset" : 14,
"type" : "CN_CHAR",
"position" : 8
}
]
}
小结:
-
ik_smart
:最小切分 -
ik_max_word
:最细切分
2.3.2.2 扩展词词典
随着社会的发展,在原有的词汇列表中不是一个词的,但是现在已经是一个词了。比如:“白富美”,“高富帅”,“程序员” 等。
所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。
1)打开IK分词器config目录:
2)IKAnalyzer.cfg.xml配置文件内容添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改
程序员
高富帅
白富美
4)重启elasticsearch
docker restart elasticsearch
docker restart kibana
# 查看 日志
docker logs -f elasticsearch
日志中已经成功加载ext.dic配置文件
2.3.2.3 停用词词典
在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。
IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。
1)IKAnalyzer.cfg.xml配置文件内容添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典-->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典 *** 添加停用词词典-->
<entry key="ext_stopwords">stopword.dic</entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
3)在 stopword.dic 添加停用词
特朗普选举
4)重启elasticsearch
docker restart elasticsearch
docker restart kibana
# 查看 日志
docker logs -f elasticsearch
日志中已经成功加载stopword.dic配置文件
5)测试效果:
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "特朗普选举失败"
}