详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践

‍作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
上期文章:详解SpringCloud微服务技术栈:一文速通RabbitMQ,入门到实践
订阅专栏:微服务技术全家桶
希望文章对你们有所帮助

ElasticSearch已经是非常常见和必须要掌握的技术了。这篇文章包括ElasticSearch原理的描述,安装与实践,还没有涉及到java层代码,就跟当初学MySQL一样,先学完这部分内容,之后再结合RestClient操作ElasticSearch。

ElasticSearch速成

  • 了解ES
  • 倒排索引
  • ES与MySQL的概念对比
  • 安装ES
  • 安装kibana
  • 安装IK分词器
  • IK分词器的拓展和停用词典
  • 操作索引库
    • mapping属性
    • 创建索引库
    • 查询、删除、修改索引库
  • 文档操作
    • 新增、查询、删除文档
    • 修改文档

了解ES

ElasticSearch是一个非常强大的开源搜索引擎,可以帮助我们从海量数据中心快速找到需要的内容。
我们常用的GitHub,搜索仓库的时候,不仅可以搜索到仓库,还可以把其中的代码片段都给搜出来,高亮显示。
ElasticSearch结合kibana、Logstash、Beats,也就是elastic stack(ELK,即以ElasticSearch为核心的技术栈),被广泛应用在日志数据分析、实时监控等领域。
ElasticSearch就是elastic stack的核心,负责存储、搜索、分析数据。
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第1张图片
其中数据抓取和数据可视化就不一定要用上图的组件,可以自行实现,核心还是ElasticSearch

倒排索引

传统数据库(MySQL)采用正向索引,即利用表中的id来创建索引,形成一颗B+树,所以根据id来检索的速度会非常的快。但如果是根据标题或者内容来进行检索,就会逐条扫描,非常慢。
而倒排索引,在创建的时候会形成一个新的表,有2个字段:

文档(document):每条数据就是一个文档
词条(term):文档按照语义分成的词语

例如:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第2张图片
可以很直观的发现,词条是唯一的,因此可以基于词条去做哈希,或者基于词条去设计B+树,这样就可以大大提高检索标题、内容的速度,而不像正向索引那样必须用模糊匹配这种非常慢的方式。

例如,检索’华为手机’:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第3张图片

ES与MySQL的概念对比

首先需要弄明白ElasticSearch中的2个概念:文档、索引
文档:
ElasticSearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息。
文档数据会被序列化为json格式后存储在ElasticSearch中。
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第4张图片
索引:
索引:相同类型的文档的集合
例如下面的若干文档,ElasticSearch会将相同类型的文档放在一起:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第5张图片
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第6张图片
上面的步骤就是索引的映射,即索引中文档的字段约束信息,相当于表结构的约束。
因此,可以将MySQL的一些概念与ElasticSearch进行对比:

MySQL ElasticSearch 说明
Table Index 索引(index),就是文档的集合,类似数据库的表(table)
Row Document 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式
Column Field 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)
Schema Mapping Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)
SQL DSL DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

但ElasticSearch并不能替代MySQL。

MySQL擅长事务类型操作,可以确保数据的安全和一致性
ElasticSearch没有事务的概念,它擅长海量数据的搜索、分析、计算

因此,两个联合使用是可以结合两者的优点的,当我们进行写操作的时候,写到MySQL是更好的选择,而当我们需要进行搜索的时候,在ElasticSearch中搜索效率更高,因此这就要求ElasticSearch中也要存储数据,只不过不是处理请求的时候写,那样并不安全,而是写入MySQL之后,由MySQL去做数据同步给ElasticSearch。
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第7张图片

安装ES

1、创建网络
因为我们还需要部署kibana容器,因此需要让es和kibana容器互联,这里先创建一个网络:

docker network create es-net

2、加载镜像
这里采用elasticsearch的7.12.1版本的镜像,接近1G,不建议直接pull,直接用百度网盘的镜像tar包:

链接:https://pan.baidu.com/s/1fyquyv0tEWyNG9kOQj97cg?pwd=upej
提取码:upej

上传完毕后,运行加载命令即可:

docker load -i es.tar

详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第8张图片
3、运行
运行docker命令,部署单点ES:

docker run -d \
	--name es \
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    -e "discovery.type=single-node" \
    -v es-data:/usr/share/elasticsearch/data \
    -v es-plugins:/usr/share/elasticsearch/plugins \
    --privileged \
    --network es-net \
    -p 9200:9200 \
    -p 9300:9300 \
elasticsearch:7.12.1

配置了内存大小为512M,单点模式,并将ES容器加入到es-net中,而且指定了插件的目录,之后如果需要一些插件就放在这个目录下。其中9200端口为暴露的HTTP协议端口,9300是各个ES容器互联的端口。
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第9张图片

安装kibana

kibana可以帮助我们编写ES中的DSL语句,从而操作ES。
给一个kibana.tar的文件:

链接:https://pan.baidu.com/s/1AeEJZ1VBn8jEO031S7r5Ww?pwd=0699
提取码:0699

和上面步骤一样,拖到\tmp目录下再执行docker load -i kibana.tar就行,接着运行docker命令,部署kibana:

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601  \
kibana:7.12.1

详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第10张图片
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第11张图片
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第12张图片
在这个控制台上,就可以直接发送请求给ES了。

安装IK分词器

ES在创建倒排索引时需要对文档分词;在搜索时,需要对用户输入内容分词。但默认的分词规则对中文处理并不友好。标准的分词规则会是一字一分,这显然是不符合需求的。
IK分词的安装,需要知道elasticsearch的plugins目录位置,用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过docker volume inspect es-plugins查看:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第13张图片
把tar包在本地解压一下上传到这个文件夹下,tar包可以从网盘获取:

链接:https://pan.baidu.com/s/1beOMuAA6uns4CFM1UPoVAg?pwd=b0zi
提取码:b0zi

上传了以后需要重启ES:docker restart es
IK分词器包含2种模式:

ik_smart:粗粒度切分,例如程序员单纯被切成程序员
ik_max_word:细粒度切分,例如程序员被切成程序员程序+

具体用哪个模式,需要看具体的业务。
可以自行

IK分词器的拓展和停用词典

测试IK分词器是可以查看到效果还是很不错的,其底层不用想,一定是有一个中文字典的,其他分词器也肯定是这样的。但是字典里面不一定就包含全部的中文词语,而且现在是会产生一些新词的,但字典里面却没有,就会导致一些情况下拆分的准确率大打折扣。
所以理论上我们可以手动进行分词器的拓展,也就是拓展这个词典。
另外一个重要的地方,一些不重要的词,例如,它无法和其他词组成在一起,而且没有什么含义,没有必要单独划分出来还占空间,而IK分词器正好具有停用字典的功能选项。

要拓展IK分词器的词库或者禁用某些词条,只需要修改IK分词器目录中的config目录中的IKAnalyzer.cfg.xml文件:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第14张图片
填写一下文件名:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第15张图片
这两个文件就在该xml文件的所在目录下,其中ext.dic需要我们自行去创建。
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第16张图片
而stopword.dic已经是有一些现成的了,可以自行再添加一些:
详解SpringCloud微服务技术栈:ElasticSearch原理精讲、安装、实践_第17张图片
接着要用docker restart es重启,这个拓展和停用就可以生效了。

操作索引库

类似MySQL,MySQL是要现有表才能插入数据,而ES是先要有索引库才能插入文档。MySQL的表在创建的时候要建立约束,ES的索引库在创建的时候要建立mapping映射属性。

mapping属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

type:字段数据类型,常见的简单类型有:
(1)字符串:text(可分词的文本)、keyword(精确值,例如毛里求斯不可拆)
(2)数值:long、integer、short、byte、double、float
(3)布尔:boolean
(4)日期:date
(5)对象:object
index:是否创建倒排索引,默认为true
analyzer:使用那种分词器
properties:该字段的子字段

创建索引库

ES中通过Restful请求操作索引库、文档。请求内容用DSL来表示。创建索引库和mapping的DSL语法如下:

PUT /user
{
	"mappings": {
		"properties": {
			"info": {
				"type": "text",
				"analyzer": "ik_smart"
			},
			"email": {
				"type": "keyword",
				"index": "false"
			}
			"name": {
				"properties": {
					"firstName": {
						"type": "keyword"
					}
				}
			}
		}
	}
}

info内容太多所以用ik_smart来分词,email没必要用来搜索,就没有必要建立倒排索引,name里面可能还有别的属性。
总之,看具体应用场景来选择参数。

查询、删除、修改索引库

索引库的查询和修改操作都是很容易实现的。
查看索引库:

GET /索引库名

删除索引库:

DELETE /索引库名

而索引库的修改并不那么容易,实际上是不允许修改的,因为当创建好索引库之后,其mapping映射都已经创建好了,ES也做好了倒排索引了,修改索引库带来的影响就会很大。
但是mapping映射虽然不允许修改,但是可以在原有的那些映射中再加新的映射,语法如下:

PUT /索引库名/_mapping
{
	"properties": {
		"新字段名":{
			"type": "integer"
		}
	}
}

新字段名一定是不能和之前的字段名是重复的,否则就禁止修改。

文档操作

文档的操作可以对标MySQL中对数据的操作,使用的语言是DSL,与MySQL使用的SQL语言对标。

新增、查询、删除文档

新增文档的DSL语法如下:

POST /索引库名/_doc/文档id
{
	"字段1": "值1",
	"字段2": "值2",
	"字段3": {
		"子属性1": "值3",
		"子属性2": "值4"
	}
}

查询文档的DSL语法:

GET /索引库名/_doc/文档id

删除文档的DSL语法:

DELETE /索引库名/_doc/文档id

其实这就是一种Restful风格的,做起来都挺容易的,也容易记住。

修改文档

修改文档就相对复杂一点。

方式一:全量修改,会删除旧文档,添加新文档

PUT /索引库名/_doc/文档id
{
	"字段1": "值1",
	"字段2": "值2",
	"字段3": {
		"子属性1": "值3",
		"子属性2": "值4"
	}
}

这种方式有一个好处,当文档id不存在的时候,这条指令相当于执行了新增操作,因此它是可以直接替代掉之前所说的新增POST请求。

方式二:增量修改,修改指定字段值

POST /索引库名/_update/文档id
{
	"doc": {
		"字段名": "新的值"
	}
}

你可能感兴趣的:(微服务技术全家桶,spring,cloud,微服务,elasticsearch,spring,中文分词,kibana)