ES并發(fā)沖突問題與悲觀鎖與樂觀鎖并發(fā)控制

1先蒋、ES并發(fā)沖突問題

圖解ES并發(fā)沖突問題

2职恳、悲觀鎖與樂觀鎖兩種并發(fā)控制解決方案

悲觀鎖與樂觀鎖并發(fā)控制方案
  • 悲觀鎖的優(yōu)點是:方便,直接加鎖蛹屿,對應(yīng)用程序來說屁奏,透明,不需要做額外的操作错负;缺點坟瓢,并發(fā)能力很低,同一時間只能一條線程操作數(shù)據(jù)
  • 樂觀鎖的優(yōu)點是:并發(fā)能力很高湿颅,不給數(shù)據(jù)加鎖载绿,大量線程并發(fā)操作粥诫;缺點油航,麻煩,每次更新的時候怀浆,都要先對比版本號谊囚,然后可能需要重新加載數(shù)據(jù),再次修改执赡,再寫镰踏;這個過程,可能要重復(fù)好幾次沙合。

3奠伪、Elasticsearch內(nèi)部如何基于_version進(jìn)行樂觀鎖并發(fā)控制

(1)_version元數(shù)據(jù)

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
  },
  "created": true
}

第一次創(chuàng)建一個document的時候,它的_version內(nèi)部版本號就是1;以后绊率,每次對這個document執(zhí)行修改或者刪除操作谨敛,都會對這個_version版本號自動加1;哪怕是刪除滤否,也會對這條數(shù)據(jù)的版本號加1

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

我們會發(fā)現(xiàn)脸狸,在刪除一個document之后,可以從一個側(cè)面證明藐俺,它不是立即物理刪除掉的炊甲,因為它的一些版本號等信息還是保留著的。先刪除一條document欲芹,再重新創(chuàng)建這條document卿啡,其實會在delete version基礎(chǔ)之上,再把version號加1

PUT /test_index/test_type/7
{
  "test_field": "test test"
}
#返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "6",
  "_version": 1,  //這里是1
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

#刪除
DELETE  /test_insex/test_type/7

PUT /test_index/test_type/7
{
  "test_field": "test test"
}
#返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "6",
  "_version": 2,  //變成了2
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": false
}

(2)圖解內(nèi)部如何基于_version進(jìn)行樂觀鎖并發(fā)控制


_version進(jìn)行樂觀鎖并發(fā)控制

4耀石、實戰(zhàn)演練基于_version進(jìn)行樂觀鎖并發(fā)控制

  1. 先構(gòu)造一條數(shù)據(jù)出來
#添加
PUT /test_index/test_type/7
{
  "test_field":"test test"
}
  1. 模擬兩個客戶端牵囤,都獲取到了同一條數(shù)據(jù)
#查詢
GET /test_index/test_type/7
#返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "7",
  "_version": 1,
  "found": true,
  "_source": {
    "test_field": "test test"
  }
}
  1. 其中一個客戶端,先更新了一下這個數(shù)據(jù)滞伟,同時帶上數(shù)據(jù)的版本號揭鳞,確保說,es中的數(shù)據(jù)的版本號梆奈,跟客戶端中的數(shù)據(jù)的版本號是相同的野崇,才能修改
#修改
PUT /test_index/test_type/7?version=1
{
  "test_field":"test client1"
}
#返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "7",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": false
}
  1. 另外一個客戶端,嘗試基于version=1的數(shù)據(jù)去進(jìn)行修改亩钟,同樣帶上version版本號乓梨,進(jìn)行樂觀鎖的并發(fā)控制
#再次修改
PUT /test_index/test_type/7?version=1 
{
  "test_field": "test client 2"
}
#返回報錯
{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[test_type][7]: version conflict, current version [2] is different than the one provided [1]",
        "index_uuid": "EbphihYrQMWacVrHu8eWAw",
        "shard": "3",
        "index": "test_index"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[test_type][7]: version conflict, current version [2] is different than the one provided [1]",
    "index_uuid": "EbphihYrQMWacVrHu8eWAw",
    "shard": "3",
    "index": "test_index"
  },
  "status": 409
}
  1. 在樂觀鎖成功阻止并發(fā)問題之后,嘗試正確的完成更新清酥。帶上當(dāng)前正確的版本號扶镀,在進(jìn)行修改。
#查詢獲取版本號
GET /test_index/test_type/7
#返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "7",
  "_version": 2,
  "found": true,
  "_source": {
    "test_field": "test client 1"
  }
}

#帶上當(dāng)前版本號進(jìn)行修改
PUT /test_index/test_type/7?version=2
{
  "test_field":"test client2"
}
#返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "7",
  "_version": 3,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": false
}

基于最新的數(shù)據(jù)和版本號焰轻,去進(jìn)行修改臭觉,修改后,帶上最新的版本號辱志,可能這個步驟會需要反復(fù)執(zhí)行好幾次蝠筑,才能成功,特別是在多線程并發(fā)更新同一條數(shù)據(jù)很頻繁的情況下

5. 實戰(zhàn)演練基于external version進(jìn)行樂觀鎖并發(fā)控制

es提供了一個feature揩懒,就是說什乙,你可以不用它提供的內(nèi)部_version版本號來進(jìn)行并發(fā)控制,可以基于你自己維護(hù)的一個版本號來進(jìn)行并發(fā)控制已球。舉個列子臣镣,加入你的數(shù)據(jù)在mysql里也有一份辅愿,然后你的應(yīng)用系統(tǒng)本身就維護(hù)了一個版本號,無論是什么自己生成的忆某,程序控制的渠缕。這個時候,你進(jìn)行樂觀鎖并發(fā)控制的時候褒繁,可能并不是想要用es內(nèi)部的_version來進(jìn)行控制亦鳞,而是用你自己維護(hù)的那個version來進(jìn)行控制。

#語法:
?version=1&version_type=external

version_type=external棒坏,唯一的區(qū)別在于燕差。
_version,只有當(dāng)你提供的version與es中的_version一模一樣的時候坝冕,才可以進(jìn)行修改徒探,只要不一樣,就報錯喂窟;
version_type=external测暗,只有當(dāng)你提供的version比es中的_version大的時候,才能完成修改

# 1. 先添加一條數(shù)據(jù)
PUT /test_index/test_type/8
{
  "test_field":"test"
}

# 2. 模擬兩個客戶端同時查詢到這條數(shù)據(jù)
GET /test_index/test_type/8

# 3. 第一個客戶端先進(jìn)行修改磨澡,此時客戶端程序是在自己的數(shù)據(jù)庫中獲取到了這條數(shù)據(jù)的最新版本號碗啄,比如說版本號是2
PUT /test_index/test_type/8?version=2&version_type=external
{
  "test_field":"test2"
}
#成功返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "8",
  "_version": 2,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

# 4. 模擬第二個客戶端,同時拿到了自己數(shù)據(jù)庫中維護(hù)的那個版本號稳摄,也是2稚字,同時基于version=2發(fā)起了修改
PUT /test_index/test_type/8?version=2&version_type=external
{
  "test_field":"test3"
}
#錯誤返回
{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[test_type][8]: version conflict, current version [2] is higher or equal to the one provided [2]",
        "index_uuid": "BTr18MteTx6HxbRogSjrpw",
        "shard": "1",
        "index": "test_index"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[test_type][8]: version conflict, current version [2] is higher or equal to the one provided [2]",
    "index_uuid": "BTr18MteTx6HxbRogSjrpw",
    "shard": "1",
    "index": "test_index"
  },
  "status": 409
}

# 5. 在并發(fā)控制成功后,重新基于最新的版本號發(fā)起更新
#先獲取最新的版本號
GET /test_index/test_type/8
#version=2
#再使用大于最新的版本號的號碼進(jìn)行修改
PUT /test_index/test_type/8?version=3&version_type=external
{
  "test_field":"test3"
}
#成功返回
{
  "_index": "test_index",
  "_type": "test_type",
  "_id": "8",
  "_version": 3,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": false
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厦酬,一起剝皮案震驚了整個濱河市胆描,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仗阅,老刑警劉巖昌讲,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異减噪,居然都是意外死亡短绸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門旋廷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸠按,“玉大人礼搁,你說我怎么就攤上這事饶碘。” “怎么了馒吴?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵扎运,是天一觀的道長瑟曲。 經(jīng)常有香客問我,道長豪治,這世上最難降的妖魔是什么洞拨? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮负拟,結(jié)果婚禮上烦衣,老公的妹妹穿的比我還像新娘。我一直安慰自己掩浙,他們只是感情好花吟,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著厨姚,像睡著了一般衅澈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谬墙,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天今布,我揣著相機與錄音,去河邊找鬼拭抬。 笑死部默,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的造虎。 我是一名探鬼主播甩牺,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼累奈!你這毒婦竟也來了贬派?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤澎媒,失蹤者是張志新(化名)和其女友劉穎搞乏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戒努,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡请敦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了储玫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侍筛。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撒穷,靈堂內(nèi)的尸體忽然破棺而出匣椰,到底是詐尸還是另有隱情,我是刑警寧澤端礼,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布禽笑,位于F島的核電站入录,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏佳镜。R本人自食惡果不足惜僚稿,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蟀伸。 院中可真熱鬧蚀同,春花似錦、人聲如沸啊掏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脖律。三九已至谢肾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間小泉,已是汗流浹背芦疏。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留微姊,地道東北人酸茴。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像兢交,于是被迫代替她去往敵國和親薪捍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容