分布式搜索引擎Elasticsearch講解專題(一)
?作者主頁(yè):
作者簡(jiǎn)介:Java領(lǐng)域優(yōu)質(zhì)創(chuàng)作者、CSDN博客專家 、掘金特邀作者、多年架構(gòu)師設(shè)計(jì)經(jīng)驗(yàn)、騰訊課堂常駐講師
主要內(nèi)容:Java項(xiàng)目、畢業(yè)設(shè)計(jì)、簡(jiǎn)歷模板、學(xué)習(xí)資料、面試題庫(kù)、技術(shù)互助
文末獲取源碼?
? ? ? Elasticsearch在分布式的架構(gòu)應(yīng)用中,經(jīng)常被用來(lái)進(jìn)行全文檢索服務(wù),由于它出色的性能,獲得了很好的口碑,目前來(lái)講在實(shí)際中被廣泛使用,本系列主要講解elasticsearch的相關(guān)知識(shí),從單節(jié)點(diǎn)安裝部署,到基本的索引庫(kù)CRUD和文檔的CRUD,以及集群部署和操作,都會(huì)講解到,希望對(duì)大家有所幫助。
1.初識(shí)elasticsearch
1.1 什么是elasticsearch
elasticsearch是一款非常強(qiáng)大的開(kāi)源搜索引擎,具備非常多強(qiáng)大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容
例如:
在電商網(wǎng)站搜索商品

在百度搜索答案
?

在打車軟件搜索附近的車

什么是elasticsearch?
一個(gè)開(kāi)源的分布式搜索引擎,可以用來(lái)實(shí)現(xiàn)搜索、日志統(tǒng)計(jì)、分析、系統(tǒng)監(jiān)控等功能
什么是elastic stack(ELK)?
是以elasticsearch為核心的技術(shù)棧,包括beats、Logstash、kibana、elasticsearch
什么是Lucene?
是Apache的開(kāi)源搜索引擎類庫(kù),提供了搜索引擎的核心API
1.2.倒排索引
倒排索引的概念是基于MySQL這樣的正向索引而言的。
1.2.1.正向索引
正向索引:根據(jù)文檔查詢數(shù)據(jù)
反向索引:根據(jù)數(shù)據(jù)查詢文檔
那么什么是正向索引呢?例如給下表(tb_goods)中的id創(chuàng)建索引:

如果是根據(jù)id查詢,那么直接走索引,查詢速度非常快。
但如果是基于title做模糊查詢,只能是逐行掃描數(shù)據(jù),流程如下:
1)用戶搜索數(shù)據(jù),條件是title符合"%手機(jī)%"
2)逐行獲取數(shù)據(jù),比如id為1的數(shù)據(jù)
3)判斷數(shù)據(jù)中的title是否符合用戶搜索條件
4)如果符合則放入結(jié)果集,不符合則丟棄?;氐讲襟E1
逐行掃描,也就是全表掃描,隨著數(shù)據(jù)量增加,其查詢效率也會(huì)越來(lái)越低。當(dāng)數(shù)據(jù)量達(dá)到數(shù)百萬(wàn)時(shí),就是一場(chǎng)災(zāi)難。
1.2.2.倒排索引
倒排索引中有兩個(gè)非常重要的概念:
文檔(
Document
):用來(lái)搜索的數(shù)據(jù),其中的每一條數(shù)據(jù)就是一個(gè)文檔。例如一個(gè)網(wǎng)頁(yè)、一個(gè)商品信息詞條(
Term
):對(duì)文檔數(shù)據(jù)或用戶搜索數(shù)據(jù),利用某種算法分詞,得到的具備含義的詞語(yǔ)就是詞條。例如:我是中國(guó)人,就可以分為:我、是、中國(guó)人、中國(guó)、國(guó)人這樣的幾個(gè)詞條
創(chuàng)建倒排索引是對(duì)正向索引的一種特殊處理,流程如下:
將每一個(gè)文檔的數(shù)據(jù)利用算法分詞,得到一個(gè)個(gè)詞條
創(chuàng)建表,每行數(shù)據(jù)包括詞條、詞條所在文檔id、位置等信息
因?yàn)樵~條唯一性,可以給詞條創(chuàng)建索引,例如hash表結(jié)構(gòu)索引
如圖:

倒排索引的搜索流程如下(以搜索"華為手機(jī)"為例):
1)用戶輸入條件"華為手機(jī)"
進(jìn)行搜索。
2)對(duì)用戶輸入內(nèi)容分詞,得到詞條:華為
、手機(jī)
。
3)拿著詞條在倒排索引中查找,可以得到包含詞條的文檔id:1、2、3。
4)拿著文檔id到正向索引中查找具體文檔。
如圖:

雖然要先查詢倒排索引,再查詢倒排索引,但是無(wú)論是詞條、還是文檔id都建立了索引,查詢速度非常快!無(wú)需全表掃描。
1.2.3.正向和倒排
那么為什么一個(gè)叫做正向索引,一個(gè)叫做倒排索引呢?
正向索引是最傳統(tǒng)的,根據(jù)id索引的方式。但根據(jù)詞條查詢時(shí),必須先逐條獲取每個(gè)文檔,然后判斷文檔中是否包含所需要的詞條,是根據(jù)文檔找詞條的過(guò)程。
而倒排索引則相反,是先找到用戶要搜索的詞條,根據(jù)詞條得到保護(hù)詞條的文檔的id,然后根據(jù)id獲取文檔。是根據(jù)詞條找文檔的過(guò)程。
是不是恰好反過(guò)來(lái)了?
那么兩者方式的優(yōu)缺點(diǎn)是什么呢?
正向索引:
優(yōu)點(diǎn):
可以給多個(gè)字段創(chuàng)建索引
根據(jù)索引字段搜索、排序速度非???/p>
缺點(diǎn):
根據(jù)非索引字段,或者索引字段中的部分詞條查找時(shí),只能全表掃描。
倒排索引:
優(yōu)點(diǎn):
根據(jù)詞條搜索、模糊搜索時(shí),速度非???/p>
缺點(diǎn):
只能給詞條創(chuàng)建索引,而不是字段
無(wú)法根據(jù)字段做排序
正向索引:根據(jù)文檔找關(guān)鍵字
倒排索引:根據(jù)關(guān)鍵字找文檔(索引創(chuàng)建慢,查詢速度快)
1.3.es的一些概念
elasticsearch中有很多獨(dú)有的概念,與mysql中略有差別,但也有相似之處。
1.3.1.文檔和字段
elasticsearch是面向文檔(Document)存儲(chǔ)的,可以是數(shù)據(jù)庫(kù)中的一條商品數(shù)據(jù),一個(gè)訂單信息。文檔數(shù)據(jù)會(huì)被序列化為json格式后存儲(chǔ)在elasticsearch中:

而Json文檔中往往包含很多的字段(Field),類似于數(shù)據(jù)庫(kù)中的列。
1.3.2.索引和映射
索引(Index),就是相同類型的文檔的集合。
例如:
所有用戶文檔,就可以組織在一起,稱為用戶的索引;
所有商品的文檔,可以組織在一起,稱為商品的索引;
所有訂單的文檔,可以組織在一起,稱為訂單的索引;

因此,我們可以把索引當(dāng)做是數(shù)據(jù)庫(kù)中的表。
數(shù)據(jù)庫(kù)的表會(huì)有約束信息,用來(lái)定義表的結(jié)構(gòu)、字段的名稱、類型等信息。因此,索引庫(kù)中就有映射(mapping),是索引中文檔的字段約束信息,類似表的結(jié)構(gòu)約束。
1.3.3.mysql與elasticsearch
我們統(tǒng)一的把mysql與elasticsearch的概念做一下對(duì)比:
MySQL Elasticsearch 說(shuō)明 Table Index 索引(index),就是文檔的集合,類似數(shù)據(jù)庫(kù)的表(table) Row Document 文檔(Document),就是一條條的數(shù)據(jù),類似數(shù)據(jù)庫(kù)中的行(Row),文檔都是JSON格式 Column Field 字段(Field),就是JSON文檔中的字段,類似數(shù)據(jù)庫(kù)中的列(Column) Schema Mapping Mapping(映射)是索引中文檔的約束,例如字段類型約束。類似數(shù)據(jù)庫(kù)的表結(jié)構(gòu)(Schema) SQL DSL DSL是elasticsearch提供的JSON風(fēng)格的請(qǐng)求語(yǔ)句,用來(lái)操作elasticsearch,實(shí)現(xiàn)CRUD
是不是說(shuō),我們學(xué)習(xí)了elasticsearch就不再需要mysql了呢?
并不是如此,兩者各自有自己的擅長(zhǎng)支出:
Mysql:擅長(zhǎng)事務(wù)類型操作,可以確保數(shù)據(jù)的安全和一致性
Elasticsearch:擅長(zhǎng)海量數(shù)據(jù)的搜索、分析、計(jì)算
因此在企業(yè)中,往往是兩者結(jié)合使用:
對(duì)安全性要求較高的寫操作,使用mysql實(shí)現(xiàn)
對(duì)查詢性能要求較高的搜索需求,使用elasticsearch實(shí)現(xiàn)
兩者再基于某種方式,實(shí)現(xiàn)數(shù)據(jù)的同步,保證一致性

2.安裝es、kibana
ES和kibana為方便起見(jiàn),直接安裝在docker容器中供我們使用,沒(méi)學(xué)過(guò)docker的可自行補(bǔ)充。kibana主要是作為一個(gè)工具來(lái)和ES交互使用,也可以使用postman來(lái)發(fā)送rest請(qǐng)求es接口。
2.1 安裝ES
因?yàn)槲覀冞€需要部署kibana容器,因此需要讓es和kibana容器互聯(lián)。這里先創(chuàng)建一個(gè)網(wǎng)絡(luò):
docker network create es-net
拉取es的鏡像:
docker pull elasticsearch:7.12.1
運(yùn)行docker命令,部署單點(diǎn)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
命令解釋:
-e "cluster.name=es-docker-cluster"
:設(shè)置集群名稱-e "http.host=0.0.0.0"
:監(jiān)聽(tīng)的地址,可以外網(wǎng)訪問(wèn)-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
:內(nèi)存大小-e "discovery.type=single-node"
:非集群模式-v es-data:/usr/share/elasticsearch/data
:掛載邏輯卷,綁定es的數(shù)據(jù)目錄-v es-logs:/usr/share/elasticsearch/logs
:掛載邏輯卷,綁定es的日志目錄-v es-plugins:/usr/share/elasticsearch/plugins
:掛載邏輯卷,綁定es的插件目錄--privileged
:授予邏輯卷訪問(wèn)權(quán)--network es-net
:加入一個(gè)名為es-net的網(wǎng)絡(luò)中-p 9200:9200
:端口映射配置
在瀏覽器中輸入:?http://192.168.136.160:9200 即可看到elasticsearch的響應(yīng)結(jié)果:

kibana可以給我們提供一個(gè)elasticsearch的可視化界面,便于我們學(xué)習(xí)。
2.2.部署kibana
運(yùn)行docker命令,部署kibana
?docker run -d \
?--name kibana \
?-e ELASTICSEARCH_HOSTS=http://es:9200 \
?--network=es-net \
?-p 5601:5601 ?\
?kibana:7.12.1
--network es-net
:加入一個(gè)名為es-net的網(wǎng)絡(luò)中,與elasticsearch在同一個(gè)網(wǎng)絡(luò)中-e ELASTICSEARCH_HOSTS=http://es:9200"
:設(shè)置elasticsearch的地址,因?yàn)閗ibana已經(jīng)與elasticsearch在一個(gè)網(wǎng)絡(luò),因此可以用容器名直接訪問(wèn)elasticsearch-p 5601:5601
:端口映射配置
kibana啟動(dòng)一般比較慢,需要多等待一會(huì),可以通過(guò)命令:
?docker logs -f kibana
訪問(wèn)http://192.168.136.160:5601訪問(wèn),可以看到kibana運(yùn)行的主頁(yè)

?表示安裝成功:不過(guò)啟動(dòng)可能慢一定,它需要連接ES服務(wù),所以先要啟動(dòng)ES服務(wù),再啟動(dòng)kibana.
2.3.使用kibana
按下圖選擇DevTools

可以在此處編寫DSL來(lái)訪問(wèn)es的rest接口:

2.4.安裝IK分詞器
ES在對(duì)內(nèi)容進(jìn)行分詞時(shí),默認(rèn)不支持中文分詞,只能對(duì)英語(yǔ)進(jìn)行分詞,所以如果操作中文需要安裝中文分詞器來(lái)進(jìn)行使用。
# 進(jìn)入容器內(nèi)部docker exec -it es /bin/bash# 在線下載并安裝./bin/elasticsearch-plugin ?install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip#退出exit#重啟容器docker restart es
IK分詞器包含兩種模式:
ik_smart
:最少切分ik_max_word
:最細(xì)切分
測(cè)試:
GET /_analyze
{ ?"analyzer": "ik_max_word", ?"text": "指南針畢業(yè)設(shè)計(jì)太棒了"}
結(jié)果:
{ ?"tokens" : [
? ?{ ? ? ?"token" : "指南針", ? ? ?"start_offset" : 0, ? ? ?"end_offset" : 3, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 0
? ?},
? ?{ ? ? ?"token" : "指南", ? ? ?"start_offset" : 0, ? ? ?"end_offset" : 2, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 1
? ?},
? ?{ ? ? ?"token" : "南針", ? ? ?"start_offset" : 1, ? ? ?"end_offset" : 3, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 2
? ?},
? ?{ ? ? ?"token" : "畢業(yè)設(shè)計(jì)", ? ? ?"start_offset" : 3, ? ? ?"end_offset" : 7, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 3
? ?},
? ?{ ? ? ?"token" : "畢業(yè)", ? ? ?"start_offset" : 3, ? ? ?"end_offset" : 5, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 4
? ?},
? ?{ ? ? ?"token" : "設(shè)計(jì)", ? ? ?"start_offset" : 5, ? ? ?"end_offset" : 7, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 5
? ?},
? ?{ ? ? ?"token" : "太棒了", ? ? ?"start_offset" : 7, ? ? ?"end_offset" : 10, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 6
? ?},
? ?{ ? ? ?"token" : "太棒", ? ? ?"start_offset" : 7, ? ? ?"end_offset" : 9, ? ? ?"type" : "CN_WORD", ? ? ?"position" : 7
? ?},
? ?{ ? ? ?"token" : "了", ? ? ?"start_offset" : 9, ? ? ?"end_offset" : 10, ? ? ?"type" : "CN_CHAR", ? ? ?"position" : 8
? ?}
?]
}
也可以根據(jù)需要來(lái)設(shè)置IK分詞器的擴(kuò)展詞和停用詞,這里就不再介紹。