亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為何Redis用樂觀鎖,而MySQL數據庫卻沒有

為何Redis用樂觀鎖,而MySQL數據庫卻沒有

素胚勾勒不出你 2019-04-05 03:01:36
為何Redis用樂觀鎖,而MySQL數據庫卻沒有
查看完整描述

4 回答

?
慕桂英4014372

TA貢獻1871條經驗 獲得超13個贊

簡單來說,Redis使用樂觀鎖,相對于悲觀鎖,在實現中更加簡單,在某些場景中的性能也更好。Redis作為一個輕量級的、快速的緩存引擎,而不是一個全功能的關系型數據庫,既沒有使用悲觀鎖的必要,也難以承受使用悲觀鎖的成本。

詳細來說,要深入到Redis和MySQL的事務處理機制。Redis關于事務的文檔見此:

Transactions(事務)

Redis對于事務只提供了非常有限的支持,其實更多地是試圖繞過問題。

首先,Redis對于同一事務中的一組操作,而不是立即執行,而是放入一個queue中,當執行到EXEC時,再一起執行。事務執行是全局獨占的,也就是同一時間只有一個事務被執行,中途不能被其它事務打斷。Redis用這種最簡單的、也是性能最差的方式避免了race condition。

其次,在Redis的事務中,如果有一個或多個操作失敗,其它操作仍然會成功,也就是說它根本沒有回滾機制。

這種方式會帶來很多嚴重的問題,其中之一是,無法先讀取某個數值后再進行依賴這個值的操作,因為放在一個事務里會被在同一個瞬間執行,不放在同一個事務里又會導致race condition。解決方法是使用WATCH,它會監視一個或多個變量,如果變量的值在調用WATCH以后和事務提交之前被別的事務修改過了,整個事務都會失敗。這類似于操作系統中的CAS(Compare and Set)。我不知道WATCH具體是怎么實現的,但是我推測它監控了指定變量的版本號

即使有了WATCH,Redis的事務也是受到嚴重限制的。第一,它沒有實現讀數據時的一致性,因為WATCH對于讀操作不起作用。第二,它不支持回滾。第三,在對同一變量存在大量并發寫操作時,性能會非常差,因為每次提交事務時,WATCH監控的變量都已經被修改了,導致事務將多次提交失敗。但是,Redis本來就是一個KV類型的緩存引擎,要處理的是大量讀少量寫的場景,對一致性也沒有要求。

MySQL就完全不一樣了,作為一個典型的關系型數據庫,它需要完整地實現ACID,所以Redis的方式是解決不了它的問題的。

MySQL中的MVCC機制(Oracle的也是),通過undo 日志來獲取某個行記錄的歷史快照,從而實現了所謂的讀一致性。它的目的是讀取某個時間點上的歷史數據(而不是可能已經被修改了的數據),而不是避免悲觀鎖的使用。嚴格地說這不能稱之為樂觀鎖,因為它既不Compare當前版本和歷史版本,也不進行Set。事實上,在讀取記錄的歷史快照時,當前記錄有可能(由于并發的寫操作)已經被加上獨占鎖。

進一步的問題是:有沒有可能使用樂觀鎖來實現RDBMS中的寫一致性?有沒有可能使用樂觀鎖實現完整的ACID特性?

回答是可以。例如,MS SQL SERVER的Hekaton引擎通過一套基于時間戳的多版本管理系統,實現了不使用了悲觀鎖的ACID。

但是,這并不意味著樂觀鎖必然優于悲觀鎖。除了維護多版本的開銷以外,樂觀鎖無法避免的一個問題是,當多個寫操作試圖更新同一個對象時,只有第一個操作可以成功,其它的操作都會在Compare時失敗然后回滾,從而造成極大的性能問題。在這種情況下,樂觀鎖的性能會低于悲觀鎖。

目前的趨勢似乎是,大規模的分布式數據庫更傾向于使用樂觀鎖來達到所謂的external consistency,因為基于傳統悲觀鎖的分布式鎖在集群大到一定程度以后(從幾百臺擴展到成千上萬臺時),性能開銷就大得無法接受了。Google的Spanner就是基于樂觀鎖。當然這完全是另外一個問題了。



查看完整回答
反對 回復 2019-04-06
?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

mysql也有樂觀鎖
樂觀鎖假設數據一般情況下不會造成沖突,所以在數據進行提交更新的時候,才會正式對數據的沖突與否進行檢測,如果發現沖突了,則返回錯誤的信息,讓用戶決定如何去做。在對數據庫進行處理的時候,樂觀鎖并不會使用數據庫提供的鎖機制。一般的實現樂觀鎖的方式就是記錄數據版本。數據版本,就是為數據增加的一個版本標識。當讀取數據時,將版本標識的值一同讀出,數據每更新一次,同時對版本標識進行更新。當我們提交更新的時候,判斷數據庫表對應記錄的當前版本信息與第一次取出來的版本標識進行比對,如果數據庫表當前版本號與第一次取出來的版本標識值相等,則予以更新,否則認為是過期數據。實現數據版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。使用版本號時,可以在數據初始化時指定一個版本號,每次對數據的更新操作都對版本號執行+1操作,并判斷當前版本號是不是該數據的最新的版本號。

查看完整回答
反對 回復 2019-04-06
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

Memcached是全內存的數據緩沖系統,Redis雖然支持數據的持久化,但是全內存畢竟才是其高性能的本質。
作為基于內存的存儲系統來說,機器物理內存的大小就是系統能夠容納的最大數據量。
如果需要處理的數據量超過了單臺機器的物理內存大小,就需要構建分布式集群來擴展存儲能力。

查看完整回答
反對 回復 2019-04-06
  • 4 回答
  • 0 關注
  • 1306 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號