Elasticsearch 介紹 – 基本概念篇
內容目錄
Elasticsearch 既是資料庫,也是搜尋引擎
Elasticsearch 不僅是一個強大的搜尋引擎,也是一個分散式資料庫。它同時具備數據搜索、數據分析、高可用和處理各類型數據的能力,多元的使用場景與豐富的開源社群,使它盤據 DB-Engines 的搜尋引擎第一名 (2022年)。本篇文章將介紹 Elasticsearch 的基本概念,讓大家從頭了解這個強大的軟體。
Elasticsearch 數據儲存類型
Elasticsearch 可以儲存結構化與非結構化等不同類型的數據。
結構化數據:
一般來說,可以整理成表單的資料就是結構化數據,它們通常具有固定欄位、固定格式與固定順序。舉個例子,若我們想要申請一張信用卡,就需要填寫結構化資料表:
姓名 | 歐小威 |
性別 | 男 |
出生年月日 | 98/08/18 |
聯絡電話 | 02-25582656 |
地址 | 台北市大同區 |
非結構化數據:
結構化數據以外的資料,皆可以視為非結構化數據,例如:聲音、圖片、影片等。它們缺乏可識別的架構、沒有固定的欄位及格式,無法被放入預定義的框架內。
在網路時代,非結構化資料量快速增長,有別於傳統的關聯式資料庫 (RDBMS) 如 Oracle, MS SQL 將資料轉為行列式的欄位進行儲存,Elasticsearch 是將數據以 JSON 格式儲存,因為不須預先定義格式,使用上更靈活,這也是能夠快速儲存、搜索與分析各類數據的 Elasticsearch 被廣泛使用的原因之一。
雖然 Elasticsearch 使用的術語和 SQL 不同,但本質上是差不多的,差異可參考下方術語對照表 [1]:
Elasticsearch | MongoDB | SQL |
---|---|---|
index | collection | table |
document | document | row |
field | field | column |
Inverted index | index | index |
Elasticsearch 數據搜索方式
Elasticsearch 的搜尋方式,可以分為兩種:
- 全文檢索 (full-text search)
- 倒排索引 (Inverted index)
全文檢索
將非結構化的數據提取出來並重新組織,使其變得有一定結構,並對此結構的數據進行搜尋。因此先建立索引,再對索引進行搜尋的過程,叫做全文檢索。
舉例來說,有一筆資料如下:
id | 資料內容 |
---|---|
1 | 登入成功 |
2 | 登入失敗 |
3 | 異常連線 |
Elasticsearch 和傳統的 RDBMS 一樣,透過對 table 設定 primary key 將其設為索引,透過搜尋索引快速找到相關的資料內容。
但是,若想要針對關鍵字「登入」進行查詢,則會搜尋整個 table,因此資料量越大,效能就會越慢。因此,Elasticsearch 還使用了「倒排索引」來提升搜尋速度。
倒排索引
紀錄每個字詞出現在哪些文檔及文檔中的位置,藉由搜尋字詞,快速地定位到有包含這些字詞的文檔及其出現位置。
假設有一筆資料如下表:
id | 資料內容 |
---|---|
1 | 登入成功 |
2 | 登入失敗 |
3 | 異常連線 |
首先,我們可以對資料進行切分,至於要切分成多細,可自行規劃設定。例如:
keyword | id |
---|---|
登入 | 1,2 |
成功 | 1 |
失敗 | 2 |
異常 | 3 |
連線 | 3 |
若今天想要針對關鍵字「登入」進行查詢,可以知道 「id:1,2」內有此關鍵字。再藉由 id 找到對應的資料內容。因為不需要搜尋整張 table,因此查詢效率大大地提高。
近即時搜索 (Near Real-time, NRT)
近即時搜索是 Elasticsearch 的另一項重要特性,以往因為硬體所造成的效能瓶頸,導致每一筆新資料皆需等待 fsync 將 segment 寫入硬碟後,才能對 segment 進行檢索,從寫入到檢索往往會超過 1 分鐘。
傳統資料寫入流程如下:
- 一筆新資料寫入記憶體的 buffer 中
- 每隔一段時間,進行 commit:將 buffer 的資料寫入新的 segment
- 新 segment 寫入作業系統的快取區 (cache)
- 透過 fsync 將快取區的 segment 寫入硬碟,並清空 buffer
- 可對 segment 進行檢索
Elasticsearch 優化這項流程:
- 一筆新資料寫入記憶體的 buffer 中
- 每隔一段時間,buffer 的資料寫入新的 segment
- 新 segment 優先寫入作業系統的快取區
- 寫入至快取區的 segment,不須等到 commit,便可直接檢索
在 Elasticsearch 中,寫入和開啟新 segment 的過程,稱為 refresh,並且預設每 1 秒刷新一次,Elasticsearch 以此實現近即時搜索。
核心基本概念
節點 (Node)
一個 Elasticsearch node 代表在一台主機上安裝 Elasticsearch 引擎,我們也可稱其為一個 Elasticsearch instance。
節點負責的工作有:
- 傳遞數據
- 節點之間的通訊
- 網路 (HTTP) 的流量傳輸等
因應不同的工作任務,Elasticsearch 節點可以劃分出多個不同功能的角色 [2],常用的有:
節點角色 | 全名 | 說明 |
---|---|---|
master | Master-eligible node | 控制節點的角色,如:負責創建、刪除索引、分配分片 |
data | Data node | 用於保存數據及處理數據,如:CRUD、搜尋、聚合等等 |
ml | Machine learning node | 用於 machine learning,若有需要,最少設置一個 |
集群 (Cluster)
一般來說,集群通常都具備以下幾種特性:
- 高可用性 (HA)
- 易擴展性
- 負載平衡 (Load Balance)
一個 Elasticsearch 集群通常「至少」由 3 個到數個節點組成 (如下方架構圖),我們可以透過增加節點擴大集群規模,不僅可以提高整體效能、也能增加儲存空間。另外,Elasticsearch 會自動分配分片 (primary shard) 和副本 (replica shard) 至集群的各節點上,用來確保資料的安全性,也就是雞蛋不要放在同一個籃子的概念。
文檔 (Document)
- Elasticsearch 最小數據單元
- 通常以 json 格式表示
- 資料使用 key:value 的形式
- 可以是一條客戶數據、商品分類數據、訂單數據等。
一個 document 裡有多個 field,一個 field 為一個數據字串,document 的重要結構名詞解釋整理如下:
filed | 說明 |
---|---|
_index | document 所屬的 index 名稱 |
_type | document 類型 |
_id | document ID 編號 |
_version | 版本訊息,每進行一次更新、刪除,都會增加 version 的值 |
_seq_no [3] | sequence number 就是序列號,避免更新後的 document 被舊版本覆蓋,Elasticsearch 會藉由追蹤序列號來判斷 document 的新舊 |
_primary_term [3] | 當主分片有更動時,其值會增加 |
_source | 此 document 的原始 json 資料 |
索引 (Index)
- Elasticsearch 的 index 就像是關聯式資料庫中的 database
- index 在 Elasticsearch 中是用來儲存 document 的容器,而這些 document 數據皆具有相似結構
- index 重要結構名詞解釋整理如下 [4]:
mappings | 定義 document 和其 field,如何儲存和被搜尋 |
type: text | 代表以全文檢索方式搜尋 |
settings | 定義和控制所有與 index 相關的內容 |
number_of_shards | 定義主分片數量 |
number_of_replicas | 定義副本數量 |
類型 (Type)
⚠️ 注意:版本 7 已棄用 Mapping Type [5]
- type 是 index 中,一個邏輯數據分類
- 每個 index 裡,可以有一個或多個 type
- 一個 type 下的 document,都有相同 field,例如:
type:日常商品 type、電器商品 type、生鮮商品 type- 日常商品 type:product_id, product_name, product_desc, category_id, category_name
- 電器商品 type:product_id, product_name, product_desc, category_id, category_name, service_period
- 生鮮商品 type:product_id, product_name, product_desc, category_id, category_name, eat_period
分片 (Shard)
Shard 全名為 primary shard,用於存放 index 數據。當資料量過大,單一節點無法儲存時,就需要利用 Shard 拆分資料來儲存。
舉例來說,我們有三個節點,每個節點有 500G 的硬碟空間,當資料量為 1TB 時,此時任一節點都無法承載。因此,透過切分 index 數據,使每個 Shard 皆包含一部分的 index,這樣便能將大量的資料分散並儲存在 Elasticsearch 集群的節點中,進而實現資料擴充以及效能提升。
Shard 可以實現:
- 在多台伺服器上分散式執行搜尋和分析等操作,以此提高性能和流量
- 快速橫向擴展 (scale),彈性滿足使用需求
補充:在建立 index 時,可以同時定義 primary_shard 數量,一旦設定完成並且建立 index 後,便無法再做修改。若無指定,預設的 shard 數量為 1。
副本 (Replica)
Replica 全名為 replica shard,是 shard 的副本,replica 數量可以隨時修改,預設一個 shard 最少配一個 replica (版本 7.0.0 開始,shard 和 replica 預設從 5 個改為 1 個)。
Replica 的目的有兩個:
- 高可用性:
是最主要的目的,防止服務器故障,造成 shard 數據丟失。為了避免一個節點掛掉實影響到整個集群運作,可以為每個 shard 建立多個 replica 確保資料安全性。shard 和 replica 絕對不會同時存在同一個 Elasticsearch 節點上,以保持高可用性,但「單節點模式」例外。 - 提升流量和性能:
由於查詢時會在所有的 replica shard 上執行,因此可以提高查詢效率。
參考網址
- [1] Mapping concepts across SQL and Elasticsearch | Elasticsearch Guide [8.3] | Elastic
- [2] Node | Elasticsearch Guide [8.3] | Elastic
- [3] Sequence IDs: Coming Soon to an Elasticsearch Cluster Near You | Elastic Blog
- [4] Index modules | Elasticsearch Guide [8.3] | Elastic
- [5] Removal of mapping types | Elasticsearch Guide [7.17] | Elastic
本文章由歐立威技術顧問撰寫而成,轉載請註明出處,內容若有侵權請來信告知