一個index的數據會被分爲多片,每片都在一個shard中。因此說,一個document,只能存在於一個shard中。
當客戶端建立document的時候,es此時就須要決定說,這個document是放在這個index的哪一個shard上。
這個過程,就稱之爲document routing, 數據路由。
複製代碼
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值必定是相同的node
不管hash值是幾,不管是什麼數字,對number_of_primary_shards求餘數,結果必定是在0~number_of_primary_shards-1之間這個範圍內的。0,1,2。
複製代碼
put /index/type/id?routing=user_id
根據路由算法中的例子,當document的_id爲1時,計算出的結果爲0,就是在P0 shard 上。算法
若是增長一個primary shard,變爲4個,_id=1, 則計算出來的結果爲 21 % 4 = 1,就去P1 shard 上找這條數據,結果就會找不到,間接致使數據丟失。負載均衡
首先,增刪改操做只能有 primary shard 處理,不能由 replica sahrd處理。函數
具體步驟:性能
客戶端選擇一個node發送請求過去,這個node就是coordinating node(協調節點)spa
coordinating node,對document進行路由,將請求轉發給對應的node(有primary shard)3d
實際的node上的primary shard處理請求,而後將數據同步到replica nodecode
coordinating node,若是發現primary node和全部replica node都搞定以後,就返回響應結果給客戶端cdn
咱們在發送任何一個增刪改操做的時候,好比說put /index/type/id,均可以帶上一個consistency參數,指明咱們想要的寫一致性是什麼? put /index/type/id?consistency=quorumblog
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時長,能夠縮短,也能夠增加
對於讀請求,不必定將請求轉發到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就都有了.