Yige

Yige

Build

ElasticSearch系列 - ElasticSearch基礎總結

一、基本概念#

  • NRT:
    Near Realtime,近實時,有兩個層面的含義,一是從寫入一條數據到這條數據可以被搜索,有一段非常小的延遲(大約 1 秒左右),二是基於 Elasticsearch 的搜索和分析操作,耗時可以達到秒級。

  • Cluster
    集群,對外提供索引和搜索的服務,包含一個或多個節點,每個節點屬於哪個集群是通過集群名稱來決定的(默認名稱是 elasticsearch)

  • Node
    單獨一個 Elasticsearch 伺服器實例稱為一個 node,node 是集群的一部分,每個 node 有獨立的名稱,默認是啟動時獲取一個 UUID 作為名稱,也可以自行配置。一個 node 只能加入一個 Elasticsearch 集群當中。

  • primary shard
    主分片,數據存儲單位,通過增加分片進行橫向擴展,創建索引時指定且創建後不能再修改。

  • replica shard
    副本分片,作為 shard 的數據拷貝,保障數據不丟失高可用,同時分擔 shard 的搜索請求,提升整個集群的吞吐量和性能。

  • Index
    索引,相同結構的文檔集合,類比於數據庫的數據庫實例(Es 6.0 廢除 type 後其實就相當於單個數據表了)。

  • type
    類型,Es 6.0 以後廢除,參考鏈接: Removal of mapping types

  • Document
    文檔,Elasticsearch 最小的數據存儲單元,JSON 數據格式,類似於關係型數據庫的表記錄(一行數據),結構定義多樣化,同一個索引下的 document,結構儘可能相同。

Lucence 檢索#

Lucence 概念#

image-20201012212234564

檢索基本流程:查詢分析 => 分詞 => 關鍵詞檢索 => 搜索排序

倒排索引#

傳統的我們的檢索是通過文章,逐個遍歷找到對應關鍵詞的位置。而倒排索引,是通過分詞策略,形成了詞和文章的映射關係表,從而能夠在 O (1) 時間裡通過關鍵詞查找到文章列表。簡單來說就是根據內容找文檔,而像 MySQL 等的正排索引是根據 ID 找文檔

底層實現是基於:FST(Finite State Transducer)數據結構。lucene 從 4 + 版本後開始大量使用的數據結構是 FST。FST 有兩個優點:

  • 空間佔用小。通過對詞典中單詞前綴和後綴的重複利用,壓縮了存儲空間;

  • 查詢速度快。O (len (str)) 的查詢時間複雜度。

參考鏈接🔗:

elasticsearch 倒排索引原理

關於 Lucene 的詞典 FST 深入剖析

二、Elasticsearch 使用#

增刪改查#

  • Get API
  • Delete API
  • Update API
  • Bulk API

搜索#

  • Search API
  • Aggregrations
  • Query DSL
  • Elasticsearch SQL

Analyzer 分詞#

  • Standard Analyzer:默認的分詞器,按照詞切分,並作大寫轉小寫處理。
  • Simple Analyzer:按照非字母切分(符號被過濾),並作大寫轉小寫處理。
  • Stop Anayzer:停用詞(the、is)切分,並作大寫轉小寫處理。
  • Whitespace Anayzer:空格切分,不做大寫轉小寫處理。
  • IK:中文分詞器,需要插件安裝。
  • ICU:國際化的分詞器,需要插件安裝。
  • jieba分詞:時下流行的一個中文分詞器。

索引管理#

alias 別名#

  • 給多個索引分組

    按照月來建立索引的時候,可以考慮先按天建立索引,使用 索引模板 (indices templates) 可以讓日誌類數據按天自動創建索引,然後使用月度的索引別名完成按天索引的分類。

  • 靈活變更索引,對索引進行修改的時候無需修改代碼,零停機遷移索引數據。

    比如需要變更索引(修改分片、mapping 映射、重命名...)的時候只需要將新建的索引綁定對應的別名,等數據遷移完畢後再將舊索引與別名綁定關係刪除即可。

    零停機遷移參考官方文檔: Changing Mapping with Zero Downtime

  • 可以用於創建相同索引的不同 "視圖"。

    適用於多租戶的場景,比如需要針對不同用戶看到的某個索引下不同數據,就可以通過創建 filtered alias(篩選別名)來進行篩選。

  • 多個物理索引並且需要通過 alias 寫入的場景。

    針對多個物理索引並且需要通過 alias 寫入的時候可以通過指定 write index,然後針對指向多個索引的別名的所有索引和更新請求將嘗試解析為一個索引,即寫索引。每個別名只能將一個索引分配為一次 write 索引。 如果未指定 write 索引且別名引用了多個索引,則不允許寫入

示例操作:

curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
    "actions" : [
        { "remove" : { "index" : "test1", "alias" : "alias1" } },
        { "add" : { "index" : "test2", "alias" : "alias1" } }
    ]
}
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
    "actions" : [
        {
            "add" : {
                 "index" : "test1",
                 "alias" : "alias2",
                 "filter" : { "term" : { "user" : "kimchy" } }
            }
        }
    ]
}

參考鏈接 : Index Aliases

rollover API#

根據日期滾動創建索引。

參考鏈接 : Rollover Index

索引映射#

  • Mapping 設置
  • Index Template
  • Dynamic Template: 根據 Elasticsearch 識別的數據類型,結合字段名稱,來動態設定字段類型。

參考鏈接:

routing 路由#

當索引一個文檔的時候,文檔會被存儲到一個主分片中。Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?當我們創建文檔時,它如何決定這個文檔應當被存儲在分片 1 還是分片 2 中呢?

實際上,這個過程是根據下面這個公式決定的:

shard = hash(routing) % number_of_primary_shards

routing 是一個可變值,默認是文檔的 _id ,也可以設置成一個自定義的值。 routing 通過 hash 函數生成一個數字,然後這個數字再除以 number_of_primary_shards (主分片的數量)後得到 餘數。這個分布在 0number_of_primary_shards-1 之間的餘數,就是我們所尋求的文檔所在分片的位置。

這也是我們為什麼要在創建索引的時候就確定好主分片的數量並且永遠不會改變這個數量:因為如果數量變化了,那麼所有之前路由的值都會無效,文檔也再也找不到了。(新版本裡 Es 可以支持在一定條件限制下,對某個索引的主分片進行Split拆分或 Shrink縮小,只能拆分成 n 倍或縮小至 主分片數 /n 個,而不能從 8 =》9 或者 9 =》8 這種)。

三、集群架構#

集群角色#

  • Master Node 主節點:全局唯一,集群選舉。負責集群層面的相關操作、管理集群變更。主節點也可以作為數據節點,但不推薦。
  • Data Node 數據節點:負責保存數據、執行數據相關操作。一般數據讀寫流程也只與數據節點交互。
  • Ingest Node預處理節點: Es 5.0 版本引入的概念。預處理操作允許在索引文檔之前,即數據寫入之前通過定義processors處理器和pipeline管道對數據進行某種轉換。參考鏈接:Ingest Node
  • Coordinating node 協調節點:協調節點將客戶端請求轉發給保存數據的 Data Node,每個數據節點在本地執行請求,並將結果返回協調節點,協調節點收集這些數據結果然後合併為單個全局結果。
  • Tribe Node部落節點,被廢除,被 Cross-cluster search取代。

集群健康狀態#

  • Green: 所有主分片和副本分片正常運行。
  • Yellow: 主分片正常,但不是所有的副本分片都正常運行,這意味著可能存在單點故障風險。
  • Red: 有主分片不能正常運行。

每個索引也有以上三個狀態,假設其中某個副本分片不正常即為 Yellow 狀態。

可以通過 curl -X GET "localhost:9200/_cluster/health?pretty" 查詢集群狀態,具體參考:Cluster health API

集群擴容#

當擴容集群、添加節點時,分片會均衡地分配到集群的各個節點,從而對索引和搜索過程進行負載均衡,這些都是系統自動完成的。

參考: 擴容設計

主要內部模塊#

####Cluster

Cluster 模塊是主節點執行集群管理的封裝實現,管理集群狀態,維護集群層面的配置信息。主要功能如下:

  • 管理集群狀態,將新生成的集群狀態發布到集群所有節點。
  • 調用 allocation 模塊執行分片分配,決策哪些分片應該分配到哪個節點。
  • 在集群各節點中直接遷移分片,保持數據平衡。

allocation#

封裝了分片分配相關的功能和策略,包括主分片的分配和副分片的分配,本模塊由主節點調用。創建新索引、集群完全重啟都需要分片分配的過程。

Discovery 發現模塊#

負責發現集群中的節點,以及選舉主節點。當節點加入或退出集群時,主節點會採取相應的行動。從某種角度來說,發現模塊起到類似 ZooKeep 的作用,選主並管理集群拓撲。

gateway#

負責對收到 Master 廣播下來的集群狀態(clusterstate)數據的持久化存儲,並在集群完全重啟時恢復它們。

Indices 索引模塊#

管理全局級的索引設置,不包括索引級的(索引設置分為全局級和每個索引級)。它還封裝了索引數據恢復功能。集群啟動階段需要的主分片恢復和副分片恢復就是在這個模塊實現的。

HTTP#

HTTP 模塊允許通過 JSON over HTTP 的方式訪問 ES 的 API。HTTP 模塊本質上是完全異步的,這意味著沒有阻塞線程等待響應。使用異步通信進行 HTTP 的好處是解決了 C10k 問題。10k 量級的並發連接)。在部分場景下,可考慮使用 HTTP keepalive 以提升性能。注意:不要在客戶端使用 HTTP chunking

Transport 傳輸模塊#

用於集群內節點之間的內部通信。從一個節點到另一個節點的每個請求都使用傳輸模塊。如同 HTTP 模塊,傳輸模塊本質上也是完全異步的。傳輸模塊使用 TCP 通信,每個節點都與其他節點維持若干 TCP 長連接。內部節點間的所有通信都是本模塊承載的。

Engine#

Engine 模塊封裝了對 Lucene 的操作及 translog 的調用,它是對一個分片讀寫操作的最終提供者。

ES 使用 Guice 框架進行模塊化管理。Guice 是 Google 開發的輕量級依賴注入框架 IoC)。軟件設計中經常說要依賴於抽象而不是具象,IoC 就是這種理念的實現方式,並且在內部實現了對象的創建和管理。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。