1. document資料路由原理
1.1 document路由到shard上是什麼意思?
一個index的資料會被分為多片,每片都在一個shard中。所以說,一個document,只能存在於一個shard中。
當客戶端建立document的時候,es此時就需要決定說,這個document是放在這個index的哪個shard上。
這個過程,就稱之為document routing, 資料路由。
複製程式碼
1.2. 路由演算法
shard = hash(routing) % number_of_primary_shards
舉例說明:
- 一個index有3個primary shard,P0,P1,P2
- 每次增刪改查一個document的時候,都會帶過來一個routing number,預設就是這個document的_id(可能是手動指定,也可能是自動生成)
複製程式碼
routing = _id,假設_id=1 - 會將這個routing值,傳入一個hash函式中,產出一個routing值的hash值,假設hash(routing) = 21 然後將hash函式產出的值對這個index的primary shard的數量求餘數,21 % 3 = 0 就決定了,這個document就放在P0上。 - 決定一個document在哪個shard上,最重要的一個值就是routing值,預設是_id,也可以手動指定,相同的routing值,每次過來,從hash函式中,產出的hash值一定是相同的
無論hash值是幾,無論是什麼數字,對number_of_primary_shards求餘數,結果一定是在0~number_of_primary_shards-1之間這個範圍內的。0,1,2。
複製程式碼
1.3 手動指定 routing id
- 預設的routing就是_id,也可以在傳送請求的時候,手動指定一個routing value,比如說
put /index/type/id?routing=user_id
- 手動指定routing value是很有用的,可以保證說,某一類document一定被路由到一個shard上去,那麼在後續進行應用級別的負載均衡,以及提升批量讀取的效能的時候,是很有幫助的
1.4 primary shard 數量不可變的原理
-
根據路由演算法中的例子,當document的_id為1時,計算出的結果為0,就是在P0 shard 上。
-
如果增加一個primary shard,變為4個,_id=1, 則計算出來的結果為 21 % 4 = 1,就去P1 shard 上找這條資料,結果就會找不到,間接導致資料丟失。
2. document增刪改內部實現原理
首先,增刪改操作只能有 primary shard 處理,不能由 replica sahrd處理。
具體步驟:
-
客戶端選擇一個node傳送請求過去,這個node就是coordinating node(協調節點)
-
coordinating node,對document進行路由,將請求轉發給對應的node(有primary shard)
-
實際的node上的primary shard處理請求,然後將資料同步到replica node
-
coordinating node,如果發現primary node和所有replica node都搞定之後,就返回響應結果給客戶端
3. document寫一致性原理及quorum機制
3.1 consistency,one(primary shard),all(all shard),quorum(default)
我們在傳送任何一個增刪改操作的時候,比如說put /index/type/id,都可以帶上一個consistency引數,指明我們想要的寫一致性是什麼? put /index/type/id?consistency=quorum
- one:要求我們這個寫操作,只要有一個primary shard是active活躍可用的,就可以執行
- all:要求我們這個寫操作,必須所有的primary shard和replica shard都是活躍的,才可以執行這個寫操作
- quorum:預設的值,要求所有的shard中,必須是大部分的shard都是活躍的,可用的,才可以執行這個寫操作
3.2 quorum機制
-
quorum機制,寫之前必須確保大多數shard都可用,int( (primary + number_of_replicas) / 2 ) + 1,當number_of_replicas>1時才生效
quroum = int( (primary + number_of_replicas) / 2 ) + 1 複製程式碼
舉個例子,3個primary shard,number_of_replicas=1,總共有3 + 3 * 1 = 6個shard, quorum = int( (3 + 1) / 2 ) + 1 = 3 所以,要求6個shard中至少有3個shard是active狀態的,才可以執行這個寫操作
-
如果節點數少於quorum數量,可能導致quorum不齊全,進而導致無法執行任何寫操作
此處有一個問題:
es提供了一種特殊的處理場景,就是說當number_of_replicas>1時才生效,因為假如說,你就一個primary shard,replica=1,此時就2個shard (1 + 1)/2 + 1 = 2,要求必須有2個shard是活躍的,但是可能就1個node,此時就1個shard是活躍的,如果你不特殊處理的話,導致我們的單節點叢集就無法工作
我在自己的機器上啟動了一個節點,新建索引如下:
PUT /quorum_test { "settings": { "number_of_shards": 1, "number_of_replicas": 1 } } 複製程式碼
增加一條資料,成功了:
PUT /quorum_test/type/1 { "field1": "test" } 返回: { "_index": "quorum_test", "_type": "type", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true } 複製程式碼
按照上面說的應該失敗才對,不知道為什麼?
-
quorum不齊全時,wait,預設1分鐘,timeout,100,30s
等待期間,期望活躍的shard數量可以增加,最後實在不行,就會timeout 我們其實可以在寫操作的時候,加一個timeout引數,比如說
put /index/type/id?timeout=30
,這個就是說自己去設定quorum不齊全的時候,es的timeout時長,可以縮短,也可以增長
4. document 查詢原理
對於讀請求,不一定將請求轉發到primary shard上,也可以轉發到replica shard上去。
具體步驟:
-
客戶端傳送請求到任意一個node,成為coordinate node
-
coordinate node對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪詢演算法,在primary shard以及其所有replica中隨機選擇一個,讓讀請求負載均衡
-
接收請求的node返回document給coordinate node
-
coordinate node返回document給客戶端
-
特殊情況:document如果還在建立索引過程中,可能只有primary shard有,任何一個replica shard都沒有,此時可能會導致無法讀取到document,但是document完成索引建立之後,primary shard和replica shard就都有了.