ElasticSearch(八)關於document的一些知識點


先查看一條數據:

GET /ecommerce/product/5

{
  "_index" : "ecommerce",
  "_type" : "product",
  "_id" : "5",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "name" : "gaolujie yagao2",
    "desc" : "gaoxiao meibai2",
    "price" : 31,
    "producer" : "gaolujie producer",
    "tags" : [
      "meibai",
      "fangzhu"
    ]
  }
}

1、_index元數據

(1)代表一個document存放在哪個index中

(2)類似的數據放在一個索引,非類似的數據放不同索引:product index(包含了所有的商品),sales index(包含了所有的商品銷售數據),inventory index(包含了所有庫存相關的數據)。如果你把比如product,sales,human resource(employee),全都放在一個大的index里面,比如說company index,不合適的。

2.1)類似的數據放在一個索引,因為這批數據的功能和支持的需求,可能類似,與其他不類似的數據,不在一個shard中,就不會互相影響。

2.2)類似的數據放在一個索引,也會避免了性能問題,假如不同類型的數據放在同一個index中,可能某些數據會有比較復雜的操作,非常耗時,這樣會導致讀取某些數據的時候很難,有可能超時。

(3)index中包含了很多類似的document:類似是什么意思,其實指的就是說,這些document的fields很大一部分是相同的,你說你放了3個document,每個document的fields都完全不一樣,這就不是類似了,就不太適合放到一個index里面去了。

(4)索引名稱必須是小寫的,不能用下划線開頭,不能包含逗號

2、_type元數據

(1)代表document屬於index中的哪個類別(type)
(2)一個索引通常會划分為多個type,邏輯上對index中有些許不同的幾類數據進行分類:因為一批相同的數據,可能有很多相同的fields,但是還是可能會有一些輕微的不同,可能會有少數fields是不一樣的,舉個例子,就比如說,商品,可能划分為電子商品,生鮮商品,日化商品,等等。
(3)type名稱可以是大寫或者小寫,但是同時不能用下划線開頭,不能包含逗號

3、_id元數據

(1)代表document的唯一標識,與index和type一起,可以唯一標識和定位一個document
(2)我們可以手動指定document的id(put /index/type/id),也可以不指定,由es自動為我們創建一個id

4、關於document id

1、手動指定document id

1)根據應用情況來說,是否滿足手動指定document id的前提:

一般來說,是從某些其他的系統中,導入一些數據到es時,會采取這種方式,就是使用系統中已有數據的唯一標識,作為es中document的id。舉個例子,比如說,我們現在在開發一個電商網站,做搜索功能,或者是OA系統,做員工檢索功能。這個時候,數據首先會在網站系統或者IT系統內部的數據庫中,會先有一份,此時就肯定會有一個數據庫的primary key(自增長,UUID,或者是業務編號)。如果將數據導入到es中,此時就比較適合采用數據在數據庫中已有的primary key。

如果說,我們是在做一個系統,這個系統主要的數據存儲就是es一種,也就是說,數據產生出來以后,可能就沒有id,直接就放es一個存儲,那么這個時候,可能就不太適合說手動指定document id的形式了,因為你也不知道id應該是什么,此時可以采取下面要講解的讓es自動生成id的方式。

(2)自動生成的id,長度為20個字符,URL安全(可以直接放在url中),base64編碼,GUID,分布式系統並行生成時不可能會發生沖突

4、_source元數據

_source元數據:就是說,我們在創建一個document的時候,使用的那個放在request body中的json串,默認情況下,在get的時候,會原封不動的給我們返回回來。

5、定制返回結果

定制返回的結果,指定_source中,返回哪些field

 

PUT /test_index/test_type/1
{
  "test_field1": "test field1",
  "test_field2": "test field2"
}
GET /test_index/test_type/1?_source=test_field1

{
  "_index" : "test_index",
  "_type" : "test_type",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "test_field1" : "test field1"
  }
}

 

6、document的全量替換

(1)語法與創建文檔是一樣的,如果document id不存在,那么就是創建;如果document id已經存在,那么就是全量替換操作,替換document的json串內容
(2)document是不可變的,如果要修改document的內容,第一種方式就是全量替換,直接對document重新建立索引,替換里面所有的內容
(3)es會將老的document標記為deleted,然后新增我們給定的一個document,當我們創建越來越多的document的時候,es會在適當的時機在后台自動刪除標記為deleted的document

7、document的強制創建

(1)創建文檔與全量替換的語法是一樣的,有時我們只是想新建文檔,不想替換文檔,如果強制進行創建呢?
(2)PUT /index/type/id?op_type=create,PUT /index/type/id/_create

8、document的刪除 

(1)DELETE /index/type/id
(2)不會理解物理刪除,只會將其標記為deleted,當數據越來越多的時候,在后台自動刪除

9、_version元數據

PUT /test_index/test_type/6
{
  "test_field": "test test"
}
{
  "_index" : "test_index",
  "_type" : "test_type",
  "_id" : "6",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 4
}

第一次創建一個document的時候,它的_version內部版本號就是1;以后,每次對這個document執行修改或者刪除操作,都會對這個_version版本號自動加1;哪怕是刪除,也會對這條數據的版本號加1

接下來刪除該數據

DELETE /test_index/test_type/6

{
  "_index" : "test_index",
  "_type" : "test_type",
  "_id" : "6",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 4
}

然后在創建該數據

PUT /test_index/test_type/6
{
  "test_field": "test test"
}

{
  "_index" : "test_index",
  "_type" : "test_type",
  "_id" : "6",
  "_version" : 3,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 4
}

我們會發現,在刪除一個document之后,可以從一個側面證明,它不是立即物理刪除掉的,因為它的一些版本號等信息還是保留着的。先刪除一條document,再重新創建這條document,其實會在delete version基礎之上,再把version號加1

 關於es后台,多線程異步replica同步並發請求的分析:

10、document的數據路由

(1)什么是document路由到shard上

1.一個index的數據會被分為多片,每片都在一個shard中,所以說,一個document,只能存在於一個shard中
2.當客戶端創建document的時候,es此時就需要決定,這個document是放在這個index的哪個shard上的,這個過程,就稱為document routing,數據路由

(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。

(3)自定義routing value

默認的routing就是_id
也可以在發送請求的時候,手動指定一個routing value,比如說put /index/type/id?routing=user_id

手動指定routing value是很有用的,可以保證說,某一類document一定被路由到一個shard上去,那么在后續進行應用級別的負載均衡,以及提升批量讀取的性能的時候,是很有幫助的

(4)為什么primary shard數量不可變

1.primary shard一旦index建立,是不允許修改的。但是replica shard可以隨時修改
2.假設有3個primary shard,我們在某個index下創建一個document,id=1
,hash=21,此時計算出的shard=21%3=0
3.如果修改為4個primary shard,則此時計算出的shard=21%4=1,結果發現沒有找到,就會間接導致數據丟失。

 

11、關於document的增刪改根據coordinating node(協調節點)實現路由原理

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

 

11、關於document的寫一致性和quorum機制

寫一致性分析:

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都是活躍的,可用的,才可以執行這個寫操作

 

quorum機制:

(2)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狀態的,才可以執行這個寫操作
(3)如果節點數少於quorum數量,可能導致quorum不齊全,進而導致無法執行任何寫操作

3個primary shard,replica=1,要求至少3個shard是active,3個shard按照之前學習的shard&replica機制,必須在不同的節點上,如果說只有2台機器的話,是不是有可能出現說,3個shard都沒法分配齊全,此時就可能會出現寫操作無法執行的情況

es提供了一種特殊的處理場景,就是說當number_of_replicas>1時才生效,因為假如說,你就一個primary shard,replica=1,此時就2個shard

(1 + 1 / 2) + 1 = 2,要求必須有2個shard是活躍的,但是可能就1個node,此時就1個shard是活躍的,如果你不特殊處理的話,導致我們的單節點集群就無法工作

 

12、關於document的查詢根據coordinating node(協調節點)實現路由原理

1、客戶端發送請求到任意一個node,成為coordinate node(協調節點)
2、coordinate node對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪詢算法,在primary shard以及其所有replica中隨機選擇一個,讓讀請求負載均衡
3、接收請求的node返回document給coordinate node
4、coordinate node返回document給客戶端
5、特殊情況:document如果還在建立索引過程中,可能只有primary shard有,任何一個replica shard都沒有,此時可能會導致無法讀取到document,但是document完成索引建立之后,primary shard和replica shard就都有了

分析:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM