Elasticsearch總結

1 基本概念

  • cluster 類比成數據庫
  • index 類比成表
  • document 類比成表中一行數據
  • field 類比成表中字段,字段是包含數據的鍵值對

2 ES 是如何實現分布式的?

image.png
  • 一個索引其實會被分片成多個shard放在不同機器上,每個shard只有索引的部分數據。
  • 每個shard可有多個replica shard 放在其他機器。primary shard負責讀寫,寫完后會同步到replica shard上。replica shard負責分擔讀請求,并防止其primary shard節點故障導致數據丟失。索引創建完成后,primary shard的數量就確定了不可更改,但replica shard的數量可以隨時調整。
  • cluster中有多個node, 會自動選舉出一個node為master節點,負責維護索引元數據,負責集群中primary shard和replica shard的身份切換。

比如上圖,index分成p0 p1 兩個primary shard, 分別存儲在node3 和 node 1上,他們的replica shard各自都有兩份,比如p0的replica shard是r0, 在node1 和 node2 上。
cluster選舉了node1作為master節點。

primary shard的默認數量是5,replica默認是1,也就是說默認5個primary shard,5個replica shard

3 ES寫入數據的工作原理是什么?

image.png

插入、刪除和索引都是寫入操作。寫入操作的主要過程如下:

  1. 客戶端請求到任意節點,比如node1
  2. node1根據文檔_id參數,hash計算出分片位置在node3節點的p0上,于是轉發請求到p0
  3. node3的p0分片執行寫請求,完畢后轉發給自己的兩個分片r0。
  4. 等待兩個復制分片寫入成功,node3報告寫入成功給node1節點,node1節點再告訴客戶端寫入成功。

其中“執行寫請求”的底層原理如下。

image.png

3.1 refresh

在ES中,buffer每隔1秒(或者滿了),打開一個新segemnt并寫入的過程,叫做refresh。

默認情況下,每個分片每秒自動刷新一次。這就是為什么說Elasticsearch是近實時的搜索了:
文檔的改動在refresh之前,是搜索不出來的。

3.2 flush

在ES中,進行一次提交并刪除事務日志的操作叫做 flush 。分片每30分鐘,或事務日志過大,都會進行一次flush操作。

3.3 translog

為了數據安全es默認每隔5秒鐘會把translog刷新(fsync)到磁盤中,也就是說最多會丟失5秒鐘的數據,如果你對數據安全比較敏感,可以把這個間隔減小,但是會占用更多資源

flush和fsync的區別:

  • flush是把內存中的數據(包括translog和segments)都刷到磁盤
  • fsync只是把translog刷新到磁盤(確保數據不丟失)。

3.4 merge

通過每隔1秒自動刷新創建新的段,用不了多久段的數量就爆炸了。

每個段文件都會消費句柄、內存、cpu資源。更重要的是,每次搜索請求都需要依次檢查每個段。段越多,查詢越慢。

ES通過后臺merge段解決這個問題。小段被合并成大段,再合并成更大的段。

image.png
image.png

3.5 刪除數據

如果刪除,其實是把數據寫到磁盤上的.del文件,然后在segemnt搜索到數據后,會在.del文件看是否有刪除標記。

在merge后會物理刪除。

4 ES搜索數據的工作原理是什么?

4.1 根據doc id 進行GET

  • 協調節點根據id進行hash計算確認在哪個分片上
  • 采用負載均衡的方式在primary shard和replica shard里查找數據

4.2 全文檢索

image.png
  1. 客戶端發送請求到協調節點node3
  2. node3向每個分片廣播,比如圖中廣播給了r0和p1
  3. 每個分片在本地執行搜索并且建立了匹配document的優先隊列(priority queue),返回document的ID和它優先隊列里的所有document的排序值給協調節點 Node 3 。
  4. Node3 把這些值合并到自己的優先隊列里產生全局排序結果。

5 在幾十億數據量級的場景下如何優化查詢性能?

5.1 filesystem cache

es的數據是存在磁盤上,第1次讀的時候如果沒在操作系統的filesystem cache上找到,就會先去磁盤把數據放到filesystem cache里再返回給node。所以filesystem cache要足夠大容納盡可能多的index和segment file數據,這樣就請求直接走內存,速度就快了。

另外,不必要的數據就別存在es里了,只把搜索用的字段數據放es。其他不用于檢索的數據,可以放在hbase或者mysql數據庫里。

走磁盤速度基本上都要上秒級,走內存基本上就是毫秒級了。

5.2 緩存預熱

對于熱點數據,每隔一段時間提前預熱到filesystem cache里。

5.3 冷熱分離

大量訪問很少,頻率很低的數據,單獨寫一個索引,熱數據在另一個索引中。確保filesystem cache里的熱數據不被頻繁刷掉。

5.4 document 模型設計

es里復雜的關聯語法join/nested等盡量別用,性能很低。寫入es系統之前就完成關聯,然后設計好document,添加一些field。

5.5 分頁性能優化

es的分頁性能比較差。es是分布式的,比如每頁10條數據,你要查第100頁的數據,實際上每個shard都會把自己的幾千條數據發給協調節點,然后匯總,再從匯總結果查詢到第100頁的數據。

也就是說,翻頁越深,各個shard拿到的數據越多,匯總的數據量也越多,性能越差。

1)不允許深度分頁
2)使用es的scroll api , 游標查詢會取某個時間點的快照數據。 查詢初始化之后索引上的任何變化會被它忽略。 但是沒法隨意跳到任何一頁

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。