1. 程式人生 > 其它 >HM-SpringCloud微服務系列5.1【初識elasticsearch】

HM-SpringCloud微服務系列5.1【初識elasticsearch】

1 瞭解ES

1.1 ES作用

elasticsearch是一款非常強大的開源搜尋引擎,具備非常多強大功能,可以幫助我們從海量資料中快速找到需要的內容。例如:

  1. 在GitHub搜尋程式碼
  2. 在電商網站搜尋商品
  3. 在百度搜索java異常問題
  4. 在打車軟體搜尋附近的車

1.2 ELK技術棧

  1. elasticsearch結合kibana、Logstash、Beats,也就是elastic stack(ELK)。被廣泛應用在日誌資料分析、實時監控等領域。
  2. 而elasticsearch是elastic stack的核心,負責儲存、搜尋、分析資料。

1.3 elasticsearch和lucene

  1. elasticsearch底層是基於lucene來實現的。
  2. Lucene是一個Java語言的搜尋引擎類庫,是Apache公司的頂級專案,由DougCutting於1999年研發。官網地址:https://lucene.apache.org/
  3. elasticsearch的發展歷史:
    • 2004年Shay Banon基於Lucene開發了Compass
    • 2010年Shay Banon 重寫了Compass,取名為Elasticsearch。
    • 官網地址: https://www.elastic.co/cn/

1.4 為什麼不是其他搜尋技術,而是ES?(為什麼學習ES)

  1. 目前比較知名的搜尋引擎技術排名:
  2. 雖然在早期,Apache Solr是最主要的搜尋引擎技術,但隨著發展elasticsearch已經漸漸超越了Solr,獨佔鰲頭:

1.5 小結

  1. 什麼是elasticsearch?
    • 一個開源的分散式搜尋引擎,可以用來實現搜尋、日誌統計、分析、系統監控等功能
  2. 什麼是elastic stack(ELK)?
    • 是以elasticsearch為核心的技術棧,包括beats、Logstash、kibana、elasticsearch
  3. 什麼是Lucene?
    • 是Apache的開源搜尋引擎類庫,提供了搜尋引擎的核心API

2 倒序索引

2.1 正向索引

  1. 倒排索引的概念是基於MySQL這樣的正向索引而言的。
  2. 那麼什麼是正向索引呢?例如給下表(tb_goods)中的id建立索引:
  3. 如果是根據id查詢,那麼直接走索引,查詢速度非常快。
  4. 但如果是基於title做模糊查詢,只能是逐行掃描資料,流程如下:
    • 1)使用者搜尋資料,條件是title符合"%手機%"
    • 2)逐行獲取資料,比如id為1的資料
    • 3)判斷資料中的title是否符合使用者搜尋條件
    • 4)如果符合則放入結果集,不符合則丟棄。回到步驟1
  5. 逐行掃描,也就是全表掃描,隨著資料量增加,其查詢效率也會越來越低。當資料量達到數百萬時,就是一場災難。

2.2 倒排索引

  1. 倒排索引中有兩個非常重要的概念:
    • 文件(Document):用來搜尋的資料,其中的每一條資料就是一個文件。例如一個網頁、一個商品資訊
    • 詞條(Term):對文件資料或使用者搜尋資料,利用某種演算法分詞,得到的具備含義的詞語就是詞條。例如:我是中國人,就可以分為:我、是、中國人、中國、國人這樣的幾個詞條
  2. 建立倒排索引是對正向索引的一種特殊處理,流程如下:
    • 將每一個文件的資料利用演算法分詞,得到一個個詞條
    • 建立表,每行資料包括詞條、詞條所在文件id、位置等資訊
    • 因為詞條唯一性,可以給詞條建立索引,例如hash表結構索引
  3. 倒排索引的搜尋流程如下(以搜尋"華為手機"為例,如圖):
    • 1)使用者輸入條件"華為手機"進行搜尋。
    • 2)對使用者輸入內容分詞,得到詞條:華為手機
    • 3)拿著詞條在倒排索引中查詢,可以得到包含詞條的文件id:1、2、3。
    • 4)拿著文件id到正向索引中查詢具體文件。
  4. 雖然要先查詢倒排索引,再查詢倒排索引,但是無論是詞條、還是文件id都建立了索引,查詢速度非常快!無需全表掃描。

2.3 正向和倒排

  1. 那麼為什麼一個叫做正向索引,一個叫做倒排索引呢?
    • 正向索引是最傳統的,根據id索引的方式。但根據詞條查詢時,必須先逐條獲取每個文件,然後判斷文件中是否包含所需要的詞條,是根據文件找詞條的過程
    • 倒排索引則相反,是先找到使用者要搜尋的詞條,根據詞條得到保護詞條的文件的id,然後根據id獲取文件。是根據詞條找文件的過程
  2. 正向索引
    • 優點:
      • 可以給多個欄位建立索引
      • 根據索引欄位搜尋、排序速度非常快
    • 缺點:
      • 根據非索引欄位,或者索引欄位中的部分詞條查詢時,只能全表掃描。
  3. 倒排索引
    • 優點:
      • 根據詞條搜尋、模糊搜尋時,速度非常快
    • 缺點:
      • 只能給詞條建立索引,而不是欄位
      • 無法根據欄位做排序

2.4 小結

3 ES的一些概念

3.1 文件和欄位

  1. elasticsearch是面向文件Document儲存的,可以是資料庫中的一條商品資料,一個訂單資訊。
  2. 文件資料會被序列化為json格式後儲存在elasticsearch中:
  3. 而Json文件中往往包含很多的欄位Field,類似於資料庫中的列。

3.2 索引和對映

  1. 索引(Index):相同型別的文件的集合。
  2. 例如:
    • 所有使用者文件,就可以組織在一起,稱為使用者的索引;
    • 所有商品的文件,可以組織在一起,稱為商品的索引;
    • 所有訂單的文件,可以組織在一起,稱為訂單的索引
  3. 因此,我們可以把索引當做是資料庫中的表。
  4. 資料庫的表會有約束資訊,用來定義表的結構、欄位的名稱、型別等資訊。因此,索引庫中就有對映(mapping),是索引中文件的欄位約束資訊,類似表的結構約束。

3.3 mysql與elasticsearch

  1. 概念對比
  2. 架構對比
    • Mysql:擅長事務型別操作,可以確保資料的安全和一致性
    • Elasticsearch:擅長海量資料的搜尋、分析、計算
  3. 是不是說,我們學習了elasticsearch就不再需要mysql了呢?並不是如此,兩者各自有自己的擅長之處(如上)。
  4. 因此在企業中,往往是兩者結合使用(如圖):
    • 對安全性要求較高的寫操作,使用mysql實現
    • 對查詢效能要求較高的搜尋需求,使用elasticsearch實現
    • 兩者再基於某種方式,實現資料的同步,保證一致性

3.4 小結

4 安裝ES、kibana

4.1 安裝

4.1.1 centos7虛擬機器docker環境啟動

QDU實驗室-->虛擬機器IP:10.193.193.141


4.1.2 單點部署ES

  1. 建立網路

    • 因為我們還需要部署kibana容器,因此需要讓es和kibana容器互聯。這裡先建立一個網路:docker network create es-net
  2. 載入映象

    • 這裡我們採用elasticsearch的7.12.1版本的映象,這個映象體積非常大,接近1G。不建議大家自己pull。課前資料提供了映象的tar包:
    • 將其上傳到虛擬機器中,然後執行命令docker load -i es.tar載入即可;同理還有kibana的tar包也需要這樣做。
    • 通過Xftp7軟體將本地兩個壓縮映象包上傳到虛擬機器
  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
  • 命令解釋:
    • -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

  1. 部署
    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,即可看到結果

  1. 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分詞器

  1. 線上安裝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
  1. 離線安裝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 小結

  1. 分詞器的作用是什麼?
    • 建立倒排索引時對文件分詞
    • 使用者搜尋時,對輸入的內容分詞
  2. IK分詞器有幾種模式?
    • ik_smart:智慧切分,粗粒度
    • ik_max_word:最細切分,細粒度
  3. IK分詞器如何拓展詞條?如何停用詞條?
    • 利用config目錄的IkAnalyzer.cfg.xml檔案新增拓展詞典和停用詞典
    • 在詞典中新增拓展詞條或者停用詞條