天天看點

樂觀鎖和悲觀鎖 你更鐘情于哪一個?

摘要:對資料庫的并發通路一直是應用程式開發者需要面對的問題之一,一個好的解決方案不僅可以提供高的可靠性還能給應用程式的性能帶來提升。下面我們來看一下Couchbase産品市場經理Don Pinto結合Couchbase Server為我們帶來的悲觀鎖和樂觀鎖的解析。

故事背景:Alice和Joe将共同讀取Couchbase Server中的同一個資料,然後都将對資料做出修改;接着将新的版本寫入資料庫。那麼誰的修改将被儲存?Alice還是Jone?又或是都不?還是結合了兩者的。

開發者對有連續通路的共享資料使用鎖。那麼究竟該選擇什麼樣的鎖方案 —— 樂觀或者悲觀?

在看Don Pinto帶來的樂觀鎖與悲觀鎖的差別以及選用建議之前,先簡單介紹一下他的履曆:Don Pinto,現任Couchbase産品市場經理;曾擔任微軟SQL Server和SQL Azure項目經理;更早階段還曾任職于IBM(DB2 LUW軟體工程師)、Honeywell(軟體開發者)等公司。下面先看看樂觀鎖與悲觀鎖的差別:

樂觀鎖

如果我們需要建立一個線上的百科 —— 使用Couchbase Server的應用程式:使用者可以修改和添加文章。假設一下Alice正在使用應用程式對“bicycles”上的一篇文章進行編輯(修改一些資訊),但是在儲存前Alice忽然想起一些其它的事情并離開了電腦;就在這個時候Joe也注意到了“bicycles”文章上的相同錯誤并且準備糾正。

如果應用程式中使用的是樂觀鎖,Joe就可以編輯文章并儲存修改。當Alice傳回并準備儲存修改的時候,那麼不管是Alice或者是應用程式都希望知道文檔的最新狀态 —— 在Alice修改文檔的行動得到允許前。樂觀鎖的出發點在于該資料很少會因為并發修改而産生沖突,是以并發修改顯得更重要一點。

悲觀鎖

這裡不防設想一下你的業務流程需要互斥存取一個或多個文檔(又或是一個graph中的文檔)。參照上面的例子:當Alice正在編輯文檔的時,她不想其他的使用者對相同的文檔進行編輯。如果這時Joe再去做同樣的事情,那麼他必須等待直到Alice釋放鎖。

通過使用悲觀鎖,應用程式可以實作對文檔的單獨占有。當使用者完成文檔的通路後,可以手動或者設定逾時來釋放鎖。

那麼究竟該選用什麼類型的鎖?這裡是沒有确切的答案的,因為使用什麼樣的鎖該由具體情況決定。你需要根據你應用程式的需求選擇相應類型的鎖。

除非你認為一個文檔會存在重度的競争,樂觀鎖的開銷要遠低于悲觀鎖—— 奪取你需要的,迅速做出修改并儲存。如果被系統中其他人搶奪,你隻能繼續嘗試直到成功。

使用了悲觀鎖,你可以對一個指定的項目進行互斥存取 —— 當它被鎖定時,其它的線程都不可以通路。這裡的關鍵在于悲觀鎖在操作失敗後必須得到釋放。想象一下:你已經獲得了對象A,但獲得對象B之前你不想放棄對象A;但是另一個已經獲得了對象B的使用者,在獲得對象A之前也不想放棄對象B。那麼這時候就需要用到逾時設定,它可以打破死鎖和處理釋放鎖失敗的情況。

簡而起見,使用者通常會在整個應用程式中使用相同的鎖政策。如果在整個應用程式中都有着同樣的需求,這麼做也無可非議。事實上,情況不是這樣的 —— 不同的應用程式對象有着不同的通路需求。下面看一下社交遊戲中的兩個例子:

  • 角色和玩家的資訊在遊戲期間被頻繁的通路,這就需要快速的讀寫通路。第一選擇 —— 使用樂觀鎖。第二選擇 —— 悲觀鎖。
  • 使用者的賬号和參數隻在使用者登入或者是遊戲開始的時候才會被讀入,并且不會被頻繁的修改。那麼樂觀鎖在這裡同樣會有很好的表現。

在Couchbase Server中獲得悲觀鎖

  • 使用get-and-lock API獲得檢索給定鍵的值,并進行鎖定
  • 應用現在已經擁有了對該文檔的互斥控制

在Couchbase Server中獲得樂觀鎖

這裡需要使用check-and-set(CAS)API獲得CAS的版本号。

釋放Couchbase Server中的鎖

這裡需要使用CAS來修改并釋放鎖

解讀CAS

CAS操作是一個很簡單的理念用以建立更卓越的并發性控制機構。CAS會在對一個對象進行讀入和嘗試儲存時确認這個對象是否被其他的使用者更改 —— 如果對象被另一個使用者更改,那麼錯誤将會産生而應用程式必須重新讀取對象的值并重試操作。如果對象不存在高度争奪,那麼資料的轉換将是幂等的;而重試操作也會在不浪費太多的工作下完成,一般情況下樂觀鎖會是一個擁有高性能的解決方案。

與CAS的互動涉及到一個GAS回路,點選檢視詳情。

舉個例子:下面互動圖中存在的3個使用者。他們3個都在使用CAS嘗試去更改X對象 —— 每個用戶端都成功,但是一次隻有一個。

你并不需要釋放鎖,吩咐Couchbase就好了

當你做一個get-and-lock的操作時,你提供一個值作為鎖的參數。一個鍵預設會被鎖定15秒。15秒過後,如果你還沒有手動的釋放鎖,那麼Couchbase會自動的為你釋放。

最終的見解

繼續閱讀