HM-SpringCloud微服務系列5.1【初識elasticsearch】
阿新 • • 發佈:2022-03-01
1 瞭解ES
1.1 ES作用
elasticsearch是一款非常強大的開源搜尋引擎,具備非常多強大功能,可以幫助我們從海量資料中快速找到需要的內容。例如:
- 在GitHub搜尋程式碼
- 在電商網站搜尋商品
- 在百度搜索java異常問題
- 在打車軟體搜尋附近的車
1.2 ELK技術棧
- elasticsearch結合kibana、Logstash、Beats,也就是elastic stack(ELK)。被廣泛應用在日誌資料分析、實時監控等領域。
- 而elasticsearch是elastic stack的核心,負責儲存、搜尋、分析資料。
1.3 elasticsearch和lucene
- elasticsearch底層是基於lucene來實現的。
- Lucene是一個Java語言的搜尋引擎類庫,是Apache公司的頂級專案,由DougCutting於1999年研發。官網地址:https://lucene.apache.org/ 。
- elasticsearch的發展歷史:
- 2004年Shay Banon基於Lucene開發了Compass
- 2010年Shay Banon 重寫了Compass,取名為Elasticsearch。
- 官網地址: https://www.elastic.co/cn/
1.4 為什麼不是其他搜尋技術,而是ES?(為什麼學習ES)
- 目前比較知名的搜尋引擎技術排名:
- 雖然在早期,Apache Solr是最主要的搜尋引擎技術,但隨著發展elasticsearch已經漸漸超越了Solr,獨佔鰲頭:
1.5 小結
- 什麼是elasticsearch?
- 一個開源的分散式搜尋引擎,可以用來實現搜尋、日誌統計、分析、系統監控等功能
- 什麼是elastic stack(ELK)?
- 是以elasticsearch為核心的技術棧,包括beats、Logstash、kibana、elasticsearch
- 什麼是Lucene?
- 是Apache的開源搜尋引擎類庫,提供了搜尋引擎的核心API
2 倒序索引
2.1 正向索引
- 倒排索引的概念是基於MySQL這樣的正向索引而言的。
- 那麼什麼是正向索引呢?例如給下表(tb_goods)中的id建立索引:
- 如果是根據id查詢,那麼直接走索引,查詢速度非常快。
- 但如果是基於title做模糊查詢,只能是逐行掃描資料,流程如下:
- 1)使用者搜尋資料,條件是title符合
"%手機%"
- 2)逐行獲取資料,比如id為1的資料
- 3)判斷資料中的title是否符合使用者搜尋條件
- 4)如果符合則放入結果集,不符合則丟棄。回到步驟1
- 1)使用者搜尋資料,條件是title符合
- 逐行掃描,也就是全表掃描,隨著資料量增加,其查詢效率也會越來越低。當資料量達到數百萬時,就是一場災難。
2.2 倒排索引
- 倒排索引中有兩個非常重要的概念:
- 文件(
Document
):用來搜尋的資料,其中的每一條資料就是一個文件。例如一個網頁、一個商品資訊 - 詞條(
Term
):對文件資料或使用者搜尋資料,利用某種演算法分詞,得到的具備含義的詞語就是詞條。例如:我是中國人,就可以分為:我、是、中國人、中國、國人這樣的幾個詞條
- 文件(
- 建立倒排索引是對正向索引的一種特殊處理,流程如下:
- 將每一個文件的資料利用演算法分詞,得到一個個詞條
- 建立表,每行資料包括詞條、詞條所在文件id、位置等資訊
- 因為詞條唯一性,可以給詞條建立索引,例如hash表結構索引
- 倒排索引的搜尋流程如下(以搜尋"華為手機"為例,如圖):
- 1)使用者輸入條件
"華為手機"
進行搜尋。 - 2)對使用者輸入內容分詞,得到詞條:
華為
、手機
。 - 3)拿著詞條在倒排索引中查詢,可以得到包含詞條的文件id:1、2、3。
- 4)拿著文件id到正向索引中查詢具體文件。
- 1)使用者輸入條件
- 雖然要先查詢倒排索引,再查詢倒排索引,但是無論是詞條、還是文件id都建立了索引,查詢速度非常快!無需全表掃描。
2.3 正向和倒排
- 那麼為什麼一個叫做正向索引,一個叫做倒排索引呢?
- 正向索引是最傳統的,根據id索引的方式。但根據詞條查詢時,必須先逐條獲取每個文件,然後判斷文件中是否包含所需要的詞條,是根據文件找詞條的過程。
- 而倒排索引則相反,是先找到使用者要搜尋的詞條,根據詞條得到保護詞條的文件的id,然後根據id獲取文件。是根據詞條找文件的過程。
- 正向索引:
- 優點:
- 可以給多個欄位建立索引
- 根據索引欄位搜尋、排序速度非常快
- 缺點:
- 根據非索引欄位,或者索引欄位中的部分詞條查詢時,只能全表掃描。
- 優點:
- 倒排索引:
- 優點:
- 根據詞條搜尋、模糊搜尋時,速度非常快
- 缺點:
- 只能給詞條建立索引,而不是欄位
- 無法根據欄位做排序
- 優點:
2.4 小結
3 ES的一些概念
3.1 文件和欄位
- elasticsearch是面向文件Document儲存的,可以是資料庫中的一條商品資料,一個訂單資訊。
- 文件資料會被序列化為json格式後儲存在elasticsearch中:
- 而Json文件中往往包含很多的欄位Field,類似於資料庫中的列。
3.2 索引和對映
- 索引(Index):相同型別的文件的集合。
- 例如:
- 所有使用者文件,就可以組織在一起,稱為使用者的索引;
- 所有商品的文件,可以組織在一起,稱為商品的索引;
- 所有訂單的文件,可以組織在一起,稱為訂單的索引
- 因此,我們可以把索引當做是資料庫中的表。
- 資料庫的表會有約束資訊,用來定義表的結構、欄位的名稱、型別等資訊。因此,索引庫中就有對映(mapping),是索引中文件的欄位約束資訊,類似表的結構約束。
3.3 mysql與elasticsearch
- 概念對比
- 架構對比
- Mysql:擅長事務型別操作,可以確保資料的安全和一致性
- Elasticsearch:擅長海量資料的搜尋、分析、計算
- 是不是說,我們學習了elasticsearch就不再需要mysql了呢?並不是如此,兩者各自有自己的擅長之處(如上)。
- 因此在企業中,往往是兩者結合使用(如圖):
- 對安全性要求較高的寫操作,使用mysql實現
- 對查詢效能要求較高的搜尋需求,使用elasticsearch實現
- 兩者再基於某種方式,實現資料的同步,保證一致性
3.4 小結
4 安裝ES、kibana
4.1 安裝
4.1.1 centos7虛擬機器docker環境啟動
QDU實驗室-->虛擬機器IP:10.193.193.141
4.1.2 單點部署ES
-
建立網路
- 因為我們還需要部署kibana容器,因此需要讓es和kibana容器互聯。這裡先建立一個網路:
docker network create es-net
- 因為我們還需要部署kibana容器,因此需要讓es和kibana容器互聯。這裡先建立一個網路:
-
載入映象
- 這裡我們採用elasticsearch的7.12.1版本的映象,這個映象體積非常大,接近1G。不建議大家自己pull。課前資料提供了映象的tar包:
- 將其上傳到虛擬機器中,然後執行命令
docker load -i es.tar
載入即可;同理還有kibana
的tar包也需要這樣做。 - 通過Xftp7軟體將本地兩個壓縮映象包上傳到虛擬機器
-
執行測試
- 執行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
- 命令解釋:
-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
:授予邏輯卷訪問權--network es-net
:加入一個名為es-net的網路中-p 9200:9200
:埠對映配置
- 在瀏覽器中輸入:http://10.193.193.141:9200 即可看到elasticsearch的響應結果
4.1.3 部署kibana
- 部署
kibana可以給我們提供一個elasticsearch的視覺化介面,便於我們學習。
執行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
:加入一個名為es-net的網路中,與elasticsearch在同一個網路中-e ELASTICSEARCH_HOSTS=http://es:9200"
:設定elasticsearch的地址,因為kibana已經與elasticsearch在一個網路,因此可以用容器名直接訪問elasticsearch-p 5601:5601
:埠對映配置
kibana啟動一般比較慢,需要多等待一會,可以通過命令:docker logs -f kibana
檢視執行日誌,當檢視到下面的日誌,說明成功:
此時,在瀏覽器輸入地址訪問:http://10.193.193.141:5601,即可看到結果
- DevTools
kibana中提供了一個DevTools介面。
這個介面中可以編寫DSL來操作elasticsearch。並且對DSL語句有自動補全功能。
4.2 分詞器
4.2.1 先導實驗
4.2.2 IK分詞器
https://github.com/medcl/elasticsearch-analysis-ik
4.2.3 安裝IK分詞器
- 線上安裝ik外掛(較慢,不推薦)
# 進入容器內部
docker exec -it elasticsearch /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 elasticsearch
- 離線安裝ik外掛(推薦)
1)檢視資料卷目錄
安裝外掛需要知道elasticsearch的plugins目錄位置,而我們用了資料卷掛載,因此需要檢視elasticsearch的資料卷目錄,通過命令docker volume inspect es-plugins
檢視
說明plugins目錄被掛載到了:/var/lib/docker/volumes/es-plugins/_data
這個目錄中。
2)解壓縮分詞器安裝包
我們需要把課前資料中的ik分詞器解壓縮,重新命名為ik
3)上傳到es容器的外掛資料卷中
也就是/var/lib/docker/volumes/es-plugins/_data
4)重啟容器
重啟es容器:docker restart es
檢視es日誌:docker logs -f es
5)測試
IK分詞器包含兩種模式:
ik_smart
:最少切分
ik_max_word
:最細切分
{
"tokens" : [
{
"token" : "ithm",
"start_offset" : 0,
"end_offset" : 4,
"type" : "ENGLISH",
"position" : 0
},
{
"token" : "學習",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "java-sc",
"start_offset" : 6,
"end_offset" : 13,
"type" : "LETTER",
"position" : 2
},
{
"token" : "java",
"start_offset" : 6,
"end_offset" : 10,
"type" : "ENGLISH",
"position" : 3
},
{
"token" : "sc",
"start_offset" : 11,
"end_offset" : 13,
"type" : "ENGLISH",
"position" : 4
},
{
"token" : "太棒了",
"start_offset" : 13,
"end_offset" : 16,
"type" : "CN_WORD",
"position" : 5
},
{
"token" : "太棒",
"start_offset" : 13,
"end_offset" : 15,
"type" : "CN_WORD",
"position" : 6
},
{
"token" : "了",
"start_offset" : 15,
"end_offset" : 16,
"type" : "CN_CHAR",
"position" : 7
}
]
}
4.2.4 詞典先導實驗
4.2.5 擴充套件詞詞典
- 隨著網際網路的發展,“造詞運動”也越發的頻繁。出現了很多新的詞語,在原有的詞彙列表中並不存在。比如:“奧力給”,“傳智播客” 等。
- 所以我們的詞彙也需要不斷的更新,IK分詞器提供了擴充套件詞彙的功能。
4.2.6 停用詞詞典
- 在網際網路專案中,在網路間傳輸的速度很快,所以很多語言是不允許在網路上傳遞的,如:關於宗教、政治等敏感詞語,那麼我們在搜尋時也應該忽略當前詞彙。
- IK分詞器也提供了強大的停用詞功能,讓我們在索引時就直接忽略當前的停用詞彙表中的內容。
4.2.6 自定義詞典實操
{
"tokens" : [
{
"token" : "傳智教育",
"start_offset" : 0,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "課程",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "可以",
"start_offset" : 7,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "白嫖",
"start_offset" : 9,
"end_offset" : 11,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "而且",
"start_offset" : 12,
"end_offset" : 14,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "學員",
"start_offset" : 14,
"end_offset" : 16,
"type" : "CN_WORD",
"position" : 5
},
{
"token" : "就業率",
"start_offset" : 16,
"end_offset" : 19,
"type" : "CN_WORD",
"position" : 6
},
{
"token" : "很高",
"start_offset" : 19,
"end_offset" : 21,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "奧利給",
"start_offset" : 22,
"end_offset" : 25,
"type" : "CN_WORD",
"position" : 8
}
]
}
4.3 小結
- 分詞器的作用是什麼?
- 建立倒排索引時對文件分詞
- 使用者搜尋時,對輸入的內容分詞
- IK分詞器有幾種模式?
- ik_smart:智慧切分,粗粒度
- ik_max_word:最細切分,細粒度
- IK分詞器如何拓展詞條?如何停用詞條?
- 利用config目錄的IkAnalyzer.cfg.xml檔案新增拓展詞典和停用詞典
- 在詞典中新增拓展詞條或者停用詞條