來源:https://mp.weixin.qq.com/s/7F497t66OJfN1qAvaN1yuA
ID生成介紹
? ? 映射也就是mapping站辉,用來定義一個文檔以及其所包含的字段如何被存儲和索引呢撞,可以在映射中事先定義字段的數(shù)據(jù)類型损姜、分詞等屬性。自動生成id殊霞,和手動生成id的適應場景:
手動指定ID
? ? 從某些其他的系統(tǒng)中摧阅,導入一些數(shù)據(jù)到es時,會采取這種方式绷蹲,就是使用系統(tǒng)中已有數(shù)據(jù)的唯一標識棒卷,作為es中document的id。比如說祝钢,我們現(xiàn)在在開發(fā)一個電商網(wǎng)站比规,做搜索功能。這個時候拦英,數(shù)據(jù)首先會在網(wǎng)站系統(tǒng)或者IT系統(tǒng)內(nèi)部的數(shù)據(jù)庫中蜒什,會先有一份數(shù)據(jù),此時需要把數(shù)據(jù)導入es這時比較適合用庫里的id疤估。
POST user_info/_doc/1
{
???"name":"張三",
???"birthdate":"1988-09-01"
}
可以看到右側(cè)id為1灾常。
自動生成ID
? ? 如果數(shù)據(jù)直接存入es,那么這個時候铃拇,可能就不太適合說手動指定document id的形式了钞瀑,因為你也不知道id應該是什么,此時可以采取下面要講解的讓es自動生成id的方式慷荔。
POST user_info/_doc
{
???"name":"張三",
???"birthdate":"1988-09-01"
}
可以看到右側(cè)id為 JWCVJXkB-WsrqdxVu0fQ
VERSION介紹
? ? ??es在創(chuàng)建索引的過程中會為每個文檔創(chuàng)建一個version變量雕什,這個變量是用于解決沖突用的。es在更新文檔時是一次讀取原生文檔显晶,做修改然后重新索引整個文檔监徘,最先請求將成功,此時文檔的versinon會加1吧碾,如果在同一時刻其他人也修改了該文檔,他們的修改將丟失墓卦。在數(shù)據(jù)庫領域中倦春,有兩種方法通常備用來確保并發(fā)更新時變更不會丟失:
????1、悲觀并發(fā)控制
????????這種方法被關系型數(shù)據(jù)庫廣泛使用落剪,它假定有變更沖突可能發(fā)生睁本,因此阻塞訪問資源以防止沖突。一個典型的例子是讀取一行數(shù)據(jù)之前先將其鎖住忠怖,確保只有放置鎖的線程能夠?qū)@行數(shù)據(jù)進行修改呢堰。
????2、樂觀并發(fā)控制
????????Elasticsearch?中使用的這種方法凡泣,它假定沖突是不可能發(fā)生的枉疼,所以不會阻塞正在嘗試的操作皮假。然而,如果源數(shù)據(jù)在讀寫當中被修改version與原來的值不一致骂维,更新將會失敗惹资。應用程序接下來將決定該如何解決沖突『焦耄可以設置重試更新次數(shù)褪测、或者將相關情況報告給用戶即拋出異常。
內(nèi)部版本號
? ? ? 使用內(nèi)部版本號是要求指定的version字段和當前的version號相同潦刃,侮措,當文檔被修改時版本號遞增。ElasticSearch使用這個_version確保變更以正確的順序得到執(zhí)行乖杠。如果舊版本的文檔在新版本之后到達分扎,它可以被簡單的忽略。我們可以用_version來確保應用中相互沖突的變更不會導致數(shù)據(jù)的丟失滑黔。我們通過指定想要修改文檔的_version來達到這個目的笆包。如果該版本不是當前版本號,我們請求將失敗
POST /user_info/user_info?version=1
version可以不用寫略荡,默認從1開始庵佣,每修改一次version將遞增。
可以到右側(cè)_version的值為1
外部版本號
? ? ?version_type:外部版本號校驗類型,有兩種:external(默認,外部版本號必須要大于內(nèi)部版本號),external_gte(外部版本號大于等于內(nèi)部版本號),如果請求成功汛兜,外部版本號作為文檔新的version號進行存儲巴粪。
POST /user_info/user_info?version=5&version_type=external
op_type?
es默認添加數(shù)據(jù)時es的ID相同會更新,不同會創(chuàng)建粥谬。op_type 參數(shù)可以指定為create來強制執(zhí)行創(chuàng)建操作肛根,此操作是不存在則創(chuàng)建,如果指定id的文檔已經(jīng)存在漏策,則此操作失斉烧堋;也可以通過_create指定此值掺喻。
op_type=create 或_create
文檔路由原理
? ? ? Elasticsearch中每個index由多個shard組成芭届,7.0之后,默認主分片是1個可修改感耙。shard分為主分片和副本分片褂乍,在文檔寫入時,會根據(jù)_routing來計算(OperationRouting類)得出文檔要寫入哪個分片即硼。這里的寫入請求只會寫主分片逃片,當主分片寫入成功后,會同時把寫入請求發(fā)送給所有的副本分片只酥,當副本分片寫入成功后褥实,會傳回返回信息給主分片呀狼,主分片得到所有副本分片的返回信息后,再返回給客戶端性锭。
默認路由機制
保存文檔時赠潦,文檔會通過一個公式路由到一個索引中的一個分片上。默認的公式如下:shard_num = hash(_routing) % num_primary_shards
默認情況下時通過_routing字段進行路由的草冈,這個字段的值默認時等于文檔_id字段的她奥。
routing?通過?hash?函數(shù)生成一個數(shù)字,然后這個數(shù)字再除以?number_of_primary_shards?(主分片的數(shù)量)后得到 余數(shù) 怎棱。這個分布在?0?到?number_of_primary_shards-1?之間的余數(shù)哩俭,就是我們所尋求的文檔所在分片的位置。這就解釋了為什么我們要在創(chuàng)建索引的時候就確定好主分片的數(shù)量?并且永遠不會改變這個數(shù)量:因為如果數(shù)量變化了拳恋,那么所有之前路由的值都會無效凡资,文檔也再也找不到了
自定義路由
???自定義路由比較簡單,如下谬运,一旦設置routing參數(shù)將替換_id字段路由文檔隙赁。
POST?my_index/my_type/1?routing=user1&refresh=true
{
??"title": "This is a document"
}
GET my_index/my_type/1?routing=user1
如果不設置路由,每個一個查詢都會去搜索索引中的全部分片梆暖,所以自定義路由可以提高搜索性能(只搜索路由指定的分片)伞访。在索引的時候只能指定一個路由,但搜索的時候可以指定一個或多個路由轰驳,這樣可以大大提高搜索的靈魂性厚掷,如下:
POST my_index/_search?routing=user1,user2
{
??"query": {
????"match": {
??????"title": "document"
????}
??}
}
文檔寫一致性
? ? ??es的一個操作請求比如:增刪改操作時put /index/type/id,都可以帶上一個consistency參數(shù)级解,指明我們想要的寫一致性是什么冒黑。
POST??/index/_doc/id?consistency=quorum
????one:要求我們這個寫操作,只要有一個primary shard是active活躍可用的勤哗,就可以執(zhí)行
????all:要求我們這個寫操作抡爹,必須所有的primary shard和replica shard都是活躍的,才可以執(zhí)行這個寫操作
????quorum:默認的值芒划,要求所有的shard中豁延,必須是大部分的shard都是活躍的,可用的腊状,才可以執(zhí)行這個寫操作
quorum
? ? ?在寫之前必須確保大多數(shù)shard都可用,int(primary + number_of_replicas)/2)+1,當number_of_replicas>1時才生效quorum = 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狀態(tài)的苟鸯,才可以執(zhí)行這個寫操作,如果節(jié)點數(shù)少于quorum數(shù)量棚点,可能導致quorum不齊全早处,進而導致無法執(zhí)行任何寫操作。3個primary shard瘫析,replica=1砌梆,要求至少3個shard是active,3個shard按照之前學習的shard&replica機制贬循,必須在不同的節(jié)點上咸包,如果說只有2臺機器的話,是不是有可能出現(xiàn)說杖虾,3個shard都沒法分配齊全烂瘫,此時就可能會出現(xiàn)寫操作無法執(zhí)行的情況。
????es提供了一種特殊的處理場景奇适,就是說當number_of_replicas>1時才生效坟比,因為假如說,你就一個primary shard嚷往,replica=1葛账,此時就2個shard((1 + 1) / 2) + 1 = 2,要求必須有2個shard是活躍的间影,但是可能就1個node注竿,此時就1個shard是活躍的,如果你不特殊處理的話魂贬,導致我們的單節(jié)點集群就無法工作巩割,quorum不齊全時,wait付燥,默認1分鐘宣谈,timeout,100键科,30s闻丑,?等待期間扩劝,期望活躍的shard數(shù)量可以增加炕檩,最后實在不行们拙,就會timeout我們其實可以在寫操作的時候编饺,加一個timeout參數(shù)扛禽,比如說put /index/type/id?timeout=30捉片,這個就是說自己去設定quorum不齊全的時候秩霍,es的timeout時長齐婴,可以縮短,也可以增長矮冬。
one
要求我們這個寫操作谈宛,只要有一個primary shard是active活躍可用的,就可以執(zhí)行胎署。
all
? ?要求我們這個寫操作吆录,必須所有的primary shard和replica shard都是活躍的,才可以執(zhí)行這個寫操作琼牧,主分片和副本都是可用的恢筝。
掃碼留言獲取相關資料