elsticsearch基礎(二) 工作機制

1、候選主節點(Master-eligible node)

一個節點啓動後,就會使用Zen Discovery機制去尋找集羣中的其他節點,並與之建立連接。集羣中會從候選主節點中選舉出一個主節點,主節點負責創建索引、刪除索引、分配分片、追蹤集羣中的節點狀態等工作。Elasticsearch中的主節點的工作量相對較輕,用戶的請求可以發往任何一個節點,由該節點負責分發和返回結果,而不需要經過主節點轉發。
  正常情況下,集羣中的所有節點,應該對主節點的選擇是一致的,即一個集羣中只有一個選舉出來的主節點。然而,在某些情況下,比如網絡通信出現問題、主節點因爲負載過大停止響應等等,就會導致重新選舉主節點,此時可能會出現集羣中有多個主節點的現象,即節點對集羣狀態的認知不一致,稱之爲腦裂現象。爲了儘量避免此種情況的出現,可以通過discovery.zen.minimum_master_nodes來設置最少可工作的候選主節點個數,建議設置爲(候選主節點數 / 2) + 1, 比如,當有三個候選主節點時,該配置項的值爲(3/2)+1=2,也就是保證集羣中有半數以上的候選主節點。
  候選主節點的設置方法是設置node.mater爲true,默認情況下,node.mater和node.data的值都爲true,即該節點既可以做候選主節點也可以做數據節點。由於數據節點承載了數據的操作,負載通常都很高,所以隨着集羣的擴大,建議將二者分離,設置專用的候選主節點。當我們設置node.data爲false,就將節點設置爲專用的候選主節點了。

node.master = true
node.data = false

2、數據節點(Data node)

數據節點負責數據的存儲和相關具體操作,比如CRUD、搜索、聚合。所以,數據節點對機器配置要求比較高,首先需要有足夠的磁盤空間來存儲數據,其次數據操作對系統CPU、Memory和IO的性能消耗都很大。通常隨着集羣的擴大,需要增加更多的數據節點來提高可用性。
  前面提到默認情況下節點既可以做候選主節點也可以做數據節點,但是數據節點的負載較重,所以需要考慮將二者分離開,設置專用的數據節點,避免因數據節點負載重導致主節點不響應。

node.master = false
node.data = true

3、客戶端節點(Client node)

按照官方的介紹,客戶端節點就是既不做候選主節點也不做數據節點的節點,只負責請求的分發、彙總等等,也就是下面要說到的協調節點的角色。這樣的工作,其實任何一個節點都可以完成,單獨增加這樣的節點更多是爲了負載均衡。

node.master = false
node.data = false

4、協調節點(Coordinating node)

協調節點,是一種角色,而不是真實的Elasticsearch的節點,你沒有辦法通過配置項來配置哪個節點爲協調節點。集羣中的任何節點,都可以充當協調節點的角色。當一個節點A收到用戶的查詢請求後,會把查詢子句分發到其它的節點,然後合併各個節點返回的查詢結果,最後返回一個完整的數據集給用戶。在這個過程中,節點A扮演的就是協調節點的角色。毫無疑問,協調節點會對CPU、Memory要求比較高。

5、分片 副本查看

“settings”: { #配置信息
“number_of_shards”: 5, #5片
“number_of_replicas”: 1 # 備份數量 1
}

6、索引狀態

Red,表示有主分片沒有分配,某些數據不可用。
Yellow,表示主分片都已分配,數據都可用,但是有複製分片沒有分配。
Green,表示主分片和複製分片都已分配,一切正常。

6、es 寫數據過程

客戶端選擇一個 node 發送請求過去,這個 node 就是 coordinating node(協調節點)。
coordinating node 對 document 進行路由,將請求轉發給對應的 node(有 primary shard)。
實際的 node 上的 primary shard 處理請求,然後將數據同步到 replica node。
coordinating node 如果發現 primary node 和所有 replica node 都搞定之後,就返回響應結果給客戶端。
盜圖

7、寫數據底層原理

先寫入內存 buffer,在 buffer 裏的時候數據是搜索不到的;同時將數據寫入 translog 日誌文件。

如果 buffer 快滿了,或者到一定時間,就會將內存 buffer 數據 refresh 到一個新的 segment file 中,但是此時數據不是直接進入 segment file 磁盤文件,而是先進入 os cache 。這個過程就是 refresh。

每隔 1 秒鐘,es 將 buffer 中的數據寫入一個新的 segment file,每秒鐘會產生一個新的磁盤文件 segment file,這個 segment file 中就存儲最近 1 秒內 buffer 中寫入的數據。

但是如果 buffer 裏面此時沒有數據,那當然不會執行 refresh 操作,如果buffer裏面有數據,默認 1 秒鐘執行一次 refresh 操作,刷入一個新的 segment file 中。

操作系統裏面,磁盤文件其實都有一個東西,叫做 os cache,即操作系統緩存,就是說數據寫入磁盤文件之前,會先進入 os cache,先進入操作系統級別的一個內存緩存中去。只要 buffer 中的數據被 refresh 操作刷入 os cache中,這個數據就可以被搜索到了。

爲什麼叫 es 是準實時的? NRT,全稱 near real-time。默認是每隔 1 秒 refresh 一次的,所以 es 是準實時的,因爲寫入的數據 1 秒之後才能被看到。可以通過 es 的 restful api 或者 java api,手動執行一次 refresh 操作,就是手動將 buffer 中的數據刷入 os cache中,讓數據立馬就可以被搜索到。只要數據被輸入 os cache 中,buffer 就會被清空了,因爲不需要保留 buffer 了,數據在 translog 裏面已經持久化到磁盤去一份了。

重複上面的步驟,新的數據不斷進入 buffer 和 translog,不斷將 buffer 數據寫入一個又一個新的 segment file 中去,每次 refresh 完 buffer 清空,translog保留。隨着這個過程推進,translog 會變得越來越大。當 translog 達到一定長度的時候,就會觸發 commit 操作。

commit 操作發生第一步,就是將 buffer 中現有數據 refresh 到 os cache 中去,清空 buffer。然後,將一個 commit point 寫入磁盤文件,裏面標識着這個 commit point 對應的所有 segment file,同時強行將 os cache 中目前所有的數據都 fsync 到磁盤文件中去。最後清空 現有 translog 日誌文件,重啓一個 translog,此時 commit 操作完成。

這個 commit 操作叫做 flush。默認 30 分鐘自動執行一次 flush,但如果 translog 過大,也會觸發 flush。flush 操作就對應着 commit 的全過程,我們可以通過 es api,手動執行 flush 操作,手動將 os cache 中的數據 fsync 強刷到磁盤上去。

translog 日誌文件的作用是什麼?你執行 commit 操作之前,數據要麼是停留在 buffer 中,要麼是停留在 os cache 中,無論是 buffer 還是 os cache 都是內存,一旦這臺機器死了,內存中的數據就全丟了。所以需要將數據對應的操作寫入一個專門的日誌文件 translog 中,一旦此時機器宕機,再次重啓的時候,es 會自動讀取 translog 日誌文件中的數據,恢復到內存 buffer 和 os cache 中去。

translog 其實也是先寫入 os cache 的,默認每隔 5 秒刷一次到磁盤中去,所以默認情況下,可能有 5 秒的數據會僅僅停留在 buffer 或者 translog 文件的 os cache 中,如果此時機器掛了,會丟失 5 秒鐘的數據。但是這樣性能比較好,最多丟 5 秒的數據。也可以將 translog 設置成每次寫操作必須是直接 fsync 到磁盤,但是性能會差很多。

實際上你在這裏,如果面試官沒有問你 es 丟數據的問題,你可以在這裏給面試官炫一把,你說,其實 es 第一是準實時的,數據寫入 1 秒後可以搜索到;可能會丟失數據的。有 5 秒的數據,停留在 buffer、translog os cache、segment file os cache 中,而不在磁盤上,此時如果宕機,會導致 5 秒的數據丟失。

7.1、Translog作用

那麼假如由於某種原因,ES的進程突然掛了,那些在內存中的數據就會丟失。而實際上,用戶調用api, 返回結果確認用戶數據已經添加到索引中。這種數據丟失是無法被接受的。怎麼解決這個問題呢?

通過ES的源碼,瞭解一下實現的細節。 首先關注Translog類。

Translog類是一個索引分片層級的組件,即每個index shard一個Translog類。它的作用是: 將沒有提交的索引操作以持久化的方式記錄起來(其實就是寫到文件中)。

InternalEngine 在commit metadata中記錄了當前最新的translog generation。 通過這個 generation,可以關聯到所有沒有commit的操作記錄。

每個Translog實例在任何時候都只會有一個處於open狀態的translog file. 這個translog file跟translog generation ID是一一映射的關係。

出於性能的考慮,災後重建並不是回放所有的translog, 而是最新沒有提交索引的那一部分。所以必須有一個checkpoint, 即translog.ckp文件。

8、刪除/更新數據底層原理

如果是刪除操作,commit 的時候會生成一個 .del 文件,裏面將某個 doc 標識爲 deleted 狀態,那麼搜索的時候根據 .del 文件就知道這個 doc 是否被刪除了。

如果是更新操作,就是將原來的 doc 標識爲 deleted 狀態,然後新寫入一條數據。

buffer 每次 refresh 一次,就會產生一個 segment file,所以默認情況下是 1 秒鐘一個 segment file,這樣下來 segment file 會越來越多,此時會定期執行 merge。每次 merge 的時候,會將多個 segment file 合併成一個,同時這裏會將標識爲 deleted 的 doc 給物理刪除掉,然後將新的 segment file 寫入磁盤,這裏會寫一個 commit point,標識所有新的 segment file,然後打開 segment file 供搜索使用,同時刪除舊的 segment file。

mysql
https://www.cnblogs.com/myseries/p/10734780.html
https://www.jianshu.com/p/fa510352ce1a
https://www.jianshu.com/p/d6fd7e8cf220
https://blog.csdn.net/weixin_34343308/article/details/91838956
https://www.cnblogs.com/glzgc/p/10831877.html
https://www.baidu.com/s?wd=log(n)&rsv_spt=1&rsv_iqid=0xb505f45600070e89&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=78040160_26_pg&ch=8&rsv_enter=1&rsv_dl=tb&rsv_sug3=6&rsv_sug1=5&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&inputT=3165&rsv_sug4=3862
mysql寫入是順序存儲麼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章