1. Elasticsearch 是什么?有哪些應用場景? Elasticsearch 整體原理流程?
Elasticsearch 是一個為海量數據提供近實時搜索和分析能力的分布式搜索引擎,廣泛應用于全文檢索、日志分析和大數據處理場景中。
Elasticsearch 整體原理流程:
1.建索引(Index)與定義 Mapping:建索引,相當于創建一個邏輯的數據容器,用于存放文檔。Mapping,定義索引中字段的數據類型、分詞器、是否索引等屬性,類似數據庫的 schema。通過 mapping,ES 知道如何解析和存儲每個字段的數據,如何分詞建立倒排索引。
2. 插入文檔(Document):用戶提交 JSON 格式的文檔,寫入到指定的索引中。ES 根據 mapping 解析字段,對需要分詞的字段進行分詞處理(Tokenizer + Token Filters),生成詞項(tokens)。對每個詞項建立倒排索引,記錄詞項在哪些文檔中出現,以及出現頻率、位置等信息。文檔數據會被存儲在主分片(Primary Shard)及其副本分片(Replica Shard)中,保證數據高可用。寫操作異步刷新到磁盤,提高寫入性能。
3. 查詢流程:查詢請求發到集群的某個節點(協調節點)。協調節點根據索引的分片信息,將查詢請求廣播到所有相關的主分片和副本分片。對查詢語句進行解析,針對查詢字段使用對應的分詞器分詞(如 match 查詢)。在倒排索引中查找詞項,快速定位匹配文檔 ID。計算文檔相關度得分(基于 TF-IDF 或 BM25 算法等),排序。各分片返回結果給協調節點。協調節點合并各分片結果,進行排序分頁,返回最終結果給客戶端。
2. 倒排索引是什么?為什么適合全文檢索?
在理解倒排索引之前,先看一下正排索引。正排索引是從“文檔到詞”的映射,也就是說:每個文檔記錄了它包含的所有詞。而倒排索引則是相反的:它是從“詞到文檔”的映射,即:每個詞會記錄它出現在哪些文檔中。
當我們搜索一個詞時,只需通過倒排索引快速定位所有包含該詞的文檔,而不需要對所有文檔內容進行全文掃描,大大提升了搜索性能。此外,倒排索引還可以記錄每個詞在各個文檔中出現的頻率、位置等信息,用于相關性打分(如 BM25 算法),從而實現搜索結果的排序和精準匹配。因此,倒排索引非常適合實現高性能的全文搜索,是搜索引擎(如 Elasticsearch)核心的數據結構之一。
3. ES 中的文檔(Document)、索引(Index)、類型(Type)是什么?
在 Elasticsearch 中,最基本的數據單位是 Document(文檔),它就像數據庫中的一行數據,JSON 格式存儲。
文檔是存在哪個 Index(索引) 里的,索引可以類比為數據庫或表,是文檔的邏輯集合。
早期 ES 中還支持 Type(類型),一個 Index 下可以有多個 Type,相當于一個數據庫里有多個表。但因為底層結構沖突,從 6.x 開始被逐步廢棄,7.x 開始每個索引只能有一個 Type,8.x 完全移除。
所以現在實際開發中,一個索引通常只存一種類型的文檔,不再使用 Type。
比如我們項目中有商品搜索功能,就會創建一個 product_index
,每條商品數據就是一個文檔,包含商品名、描述、價格等字段,然后通過這個索引來實現搜索和過濾。
4. 什么是 Mapping?和數據庫中的 schema 有什么區別?
在 Elasticsearch 中,索引(Index)通過 Mapping 來定義文檔結構,包括字段名、字段類型、是否索引、是否分詞等規則,相當于定義表的結構。
PUT /products
{"mappings": {"properties": {"name": { "type": "text", "analyzer": "standard" },"price": { "type": "float" },"in_stock": { "type": "boolean" },"created_at": { "type": "date" }}}
}
文檔(Document)是索引中的一條具體數據記錄,以 JSON 格式存儲,結構要符合 Mapping 的定義。
POST /products/_doc/1
{"name": "Apple iPhone 14","price": 799.99,"in_stock": true,"created_at": "2024-06-01T10:00:00Z"
}
所以可以理解為:Mapping 決定了索引中能存什么樣的數據結構,文檔就是實際存進去的數據。
在 Elasticsearch 中,Mapping 類似于數據庫中的 Schema,它定義了每個文檔字段的數據類型、是否分詞、是否索引、分詞器、是否支持聚合等規則。
不同于數據庫,ES 的 Mapping 更加靈活,比如可以支持嵌套結構、數組、動態字段,還能定義全文檢索相關的分詞方式,是搜索性能調優的重要部分。
5. ES 中 match
和 term
查詢的區別?
在 Elasticsearch 中,match 查詢是 全文檢索 類型的查詢,它會對查詢條件先進行分詞,然后再去倒排索引中查找對應的文檔,常用于搜索 text 類型字段,比如商品描述、文章內容等。
term 查詢則是 精確匹配 查詢,它不會進行分詞,直接使用給定的值去匹配字段,常用于 keyword、數值、布爾值等字段的過濾或精確判斷。
所以兩者的核心區別就是:match 會分詞,適合模糊查詢;term 不分詞,適合精確查詢。
6. ES 是怎么進行分詞的?常用的分詞器有哪些?
Elasticsearch 使用 分詞器(Analyzer) 來對文本字段進行處理,分詞器會將一段文本拆分為一個個詞項(term)并進行標準化,例如大小寫轉換、去除符號、刪除停用詞等。
分詞器一般包含三個組件:
1.字符過濾器(Char Filters):預處理文本,如去除 HTML 標簽。
2.分詞器(Tokenizer):將文本切分成詞(最核心部分)。
3.詞項過濾器(Token Filters):對分詞結果進行加工,比如大小寫統一、去除停用詞、同義詞處理等。
常用分詞器:
1.standard:默認分詞器,按空格、標點分詞,同時做大小寫標準化
輸入: I'm learning Elasticsearch.
輸出:i, m, learning, elasticsearch
2.simple:以非字母字符為分隔符,只保留小寫英文
輸入: Hello, World!
輸出: hello, world
3.whitespace:僅以空格分詞,不做其他處理
輸入: Hello, World!
輸出: hello, world
4.keyword:不分詞,把整個輸入當成一個詞項
輸入: 中華人民共和國
輸出: 中華人民共和國
5.ik_max_word:中文分詞器,細粒度,盡可能多的切詞
輸入: 中國互聯網公司
輸出: 中國, 互聯網, 公司, 中國互聯網, 互聯網公司
6.ik_smart:中文分詞器,粗粒度,分得較少但準確
輸入: 中國互聯網公司
輸出: 中國互聯網, 公司
7. 什么是主分片(Primary Shard)和副本分片(Replica Shard)?
在 Elasticsearch 中,索引的數據是通過主分片和副本分片進行分布式存儲的。
主分片(Primary Shard)負責實際寫入和保存原始數據;副本分片(Replica Shard)是主分片的冗余副本,用于容災備份和查詢負載均衡。
通常每個主分片至少配置一個副本,從而保證當某個節點宕機時數據不會丟失,并且查詢時可以由多個分片并行處理提升性能。
主分片負責寫入,副本分片負責高可用和查詢負載分擔;主分片掛了,副本可以自動轉為主分片,保障數據可靠性。
8. ES 是如何保證高可用的?節點掛掉會怎樣?
Elasticsearch 通過主/副分片機制、Master 選舉機制以及自動分片遷移能力實現高可用。
當某個節點宕機時,集群會自動將其主分片由副本接管,并在其他節點上重新構建副本,從而實現無縫切換,保證查詢和寫入的連續性。同時,Master 節點也有選舉機制,避免單點故障,整個集群能自動感知變化并自我修復。
節點掛掉會發生什么?
Elasticsearch 會立刻識別失聯節點(默認 30 秒內)。
該節點上的主分片如果有副本,副本會自動被提升為主分片。
副本不足的部分,會被自動重新分配到其他節點上重建副本。
查詢和寫入請求會自動路由到新的主分片或其副本,不會影響業務使用。
如果主節點宕機,會觸發主節點重新選舉機制,集群會暫時處于 yellow 狀態,自動恢復后變回 green。
9. 怎么保證 ES 和數據庫之間的數據一致性?
保證 ES 和數據庫之間數據一致,關鍵在于解決異步同步導致的最終一致性問題:
1. 冪等寫入
ES 寫入接口要設計冪等,避免重復寫入產生臟數據。
常用 document id 由業務唯一主鍵生成。
2. 異步消息可靠傳遞
使用消息隊列保障消息不丟失(持久化、確認機制)。
設計消息重試機制,處理寫 ES 失敗。
3. 事務保證與補償機制
有條件的場景使用分布式事務(如基于消息中間件的事務模式)。
定時全量校驗比對,發現不一致后自動修復。
4. 順序消費
保證消息順序消費,避免舊數據覆蓋新數據。
5. 監控和告警
監控同步延遲和失敗率,及時人工干預。
10. 實際項目中一般數據是怎么同步到 ES 的?
1. 應用程序主動寫入(同步寫入)
在業務系統(如數據庫)寫操作后,直接調用 Elasticsearch API 進行索引寫入。
2. 異步同步(消息隊列/日志異步消費)
業務系統將數據變更事件發送到消息隊列(Kafka、RabbitMQ 等)。專門的同步服務監聽消息隊列,異步寫入 Elasticsearch。
3. 定時全量同步 + 增量同步
定時全量同步是指周期性(比如每天凌晨)將數據庫中的所有數據一次性批量導入 Elasticsearch。目的是初始化數據或修復數據不一致問題。
增量同步是指只同步自上次同步后數據庫中新增加或變更的數據。可以通過基于業務表的時間戳字段(如 update_time
)進行差量查詢;使用數據庫變更日志(binlog)捕獲變更事件;監聽消息隊列中實時數據變更事件來實現增量同步。