文檔由索引(_index),類型(_type),惟一標識(_id) 組成,咱們爲 _index(索引) 分配相關邏輯地址分片,該索引下的數據會根據索引以及類型計算哈希來分配數據存儲的分片,文檔內容爲Json格式的文檔體,注意文檔中的字段名稱不能包含英文的句號,實際處理過程當中這裏最好不要包含符號,索引名稱要用小寫網絡
規則:分佈式
值得注意的是:
咱們要在建立索引的時候就肯定好主分片的數量 而且永遠不會改變這個數量:由於若是數量變化了,那麼全部以前路由的值都會無效,文檔也再也找不到了大數據
以下 定義三個節點,咱們有2個主分片,每一個分片有2個副分片,爲了保證數據完整性,ES會進行以下分佈,這裏咱們用綠色標識主分片,矩形標識副分片,那麼會出現以下分佈,保證每一個節點上都有完成的分片(主1 和主2 )數據.spa
一、Client 發送寫操做到Node13d
問題:爲何要發到Node1,好比新加入了一個節點,這節點間的有編排編號嗎?,若是是訪問帶有主節點的,也能夠訪問Node2也能夠,這之間有什麼關聯嗎?code
答:每一個節點都有能力處理任意請求。 每一個節點都知道集羣中任一文檔位置,因此能夠直接將請求轉發到須要的節點上,一開始進來都是任意一個節點,這個節點知道位置後,會做爲協調節點轉發請求到對應的節點上。這裏請求Node1是隨機節點,知道文檔存儲在主分片2上轉發到Node2,若是一開始就是Node2節點就不需轉發了,而後協調數據同步後,返回Node1再返回客戶端,寫操做都會直接找主分區所在的節點,我有點懷疑直接進入Node3呢?blog
二、根據_id發現數據應該存在存在主分片2上,因而轉到Node2,寫入數據索引
問題:新建、索引和刪除 請求都是 寫 操做, 必須在主分片上面完成以後才能被複制到相關的副本分片,ES應該每一個節點上有應該有一個記錄主分片分佈的節點記錄,若是設置的自動生成_id的狀況,那麼怎麼去判斷位置?路由
三、數據同步,寫入Node2中的主分片2成功後,並行寫入2個副分片,等待兩個副分片都應答成功後,而後通知客戶端,防止網絡或者其餘問題帶來的數據不一致文檔
ES會要求有必定的副分片數量纔會執行寫操做,結合上面的 同步副分區,能夠設置
int( (primary + number_of_replicas) / 2 ) + 1 ,consistency 參數也能夠設置 one(主分區ok便可寫入) 、all(全部主、副分區所有ok才執行寫入)、quorum 默認(大多數的主、副分區沒問題便可寫入,及上面的公式)
出現分佈式就須要注意大數據一致性的問題以及,多修改數據丟失的問題?雖然上面的同步能處理數據最終一致性的問題,可是若是出現多我的修改,會致使數據掉丟失的狀況。在實際過程咱們又怎麼來避免這種狀況呢?如又這麼一組數據
數據data 在 update data1 update data2 2個同時操做的時候會致使數據丟失,加入先get到數據 都是data 可是在update1 update2不管哪一個先那個後實際上都會存在數據丟失 若是update1先,update2後,最後數據是 update2的 /myindex/mytable/123 { "myname":"liyouming「, "myage":25 } 若是update2先,update1後,最後數據是 update1的 /myindex/mytable/123 { "myname":"zhangsan「, "myage":22 } 可是實際上咱們須要的數據應該是這樣 /myindex/mytable/123 { "myname":"zhangsan「, "myage":25 } 其實仔細想一想在咱們的實際業務管理系統中也會有這樣的問題,若是兩我的同時打開一個編輯界面同時修改,操做1 在不知道 操做2 修改內容的狀況下直接修改,其中會覆蓋一部分的數據丟失掉了
每一個文檔都有一個 _version (版本)號,當文檔被修改時版本號遞增。 Elasticsearch 使用這個 _version 號來確保變動以正確順序獲得執行。若是舊版本的文檔在新版本以後到達,它能夠被簡單的忽略,咱們能夠利用 _version 號來確保 應用中相互衝突的變動不會致使數據丟失。
那麼咱們在來看下上面的demo
在咱們查詢出來的時候獲取到版本號 _version 爲1,在進行update1 或update2的時候帶上咱們的版本號,那麼其中後面執行的那個會出現修改失敗,這麼就能保證數據丟失的狀況了,假定數據update2修改爲功了,那麼咱們獲得的數據會是這樣 data2 ,upate1失敗後再次獲取信息 獲得版本爲2 再次修改爲功獲得data1最終修改