1. 程式人生 > 其它 >鎖與全域性ID

鎖與全域性ID

技術標籤:javamysqlredis

樂觀鎖:

樂觀鎖不需要加鎖,通過一個欄位對資料行的版本進行記錄,更新資料前先讀取資料行的版本。
例子:
MySQL實現:
先讀到version為9
然後執行UPDATE goods SET num=num-1,version=version+1 WHERE version=9
如果有十個執行緒讀到版本為 9 後同時請求update,將只有一個請求是成功的,其他的因為Version資料為10,不符合version=9的條件而返回失敗。
Redis實現:
watch關鍵字配合redis事務可以觀測num的值,在事務執行過程中,如果watch的變數變了則回滾事務。

watch num
multi
decr num
exec

悲觀鎖:

悲觀鎖的方案採用的是排他讀,也就是同時只能有一個程序讀取到num的值。事務在提交或回滾之後,鎖會釋放,其他的程序才能讀取。
例子:
Redis使用命令 setnx 鎖名 1234
獲取到一把悲觀鎖,其他人無法再次成功執行這個命令。
加鎖成功的使用者可以繼續執行對持久層的操作,加鎖失敗的使用者則不能對持久層進行操作。
鎖名可以是資料庫一條資料的id+資料庫表名,這樣就可以鎖住這條資料了。
但是如果加鎖者不放開鎖的話,其他人將永遠無法修改資料了,所以必須增加超時時間。
解決方案:set 鎖名 1234 NX PX 5000如果沒有鎖則設定鎖,5000ms後失效


鎖時間設定推薦:最大耗時120%+平均網路延遲110%

解鎖del 鎖名

分散式鎖:

Memcached 的 add 命令
Redis的setnx命令

類鎖

鎖class的靜態方法

物件鎖

鎖object的例項方法

全域性ID

snowflake演算法:

可靠的分散式全域性唯一ID生成演算法
1bit - 首位無效符
41bit - 時間戳(毫秒級)
41位可以表示241 -1個數字;
241 -1毫秒,換算成年就是表示 69 年的時間
10bit - 工作機器id
5bit - datacenterId機房id
5bit - workerId機器 id
12bit - 序列號
序列號,用來記錄同一個datacenterId中某一個機器上同毫秒內產生的不同id。

java的UUID.random()方法:

UUID 含義是通用唯一識別碼 (Universally Unique Identifier),這是一個軟體建構的標準。
也是被開源軟體基金會 (Open Software Foundation, OSF) 的組織應用在分散式計算環境 (Distributed Computing Environment, DCE) 領域的一部分。
UUID 的目的,是讓分散式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人衝突的 UUID。在這樣的情況下,就不需考慮資料庫建立時的名稱重複問題。