【redis】redis事物和鎖
阿新 • • 發佈:2022-05-19
1、redis事物
1.1、redis事物的特性
一組命令的集合!一個事物中的所有命令都會被序列化,在事物執行過程中按照順序執行。
具有一致性、隔離性、永續性,但是沒有原子性
redis單調命令保證原子性,但是事物沒有原子性
redis的事物
- 開啟事物(multi)
- 命令入隊(...)
- 執行事物(exec)
1.2、事物實現
127.0.0.1:6379> multi #開啟事物 OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> exec #提交事物 1) OK 2) OK 3) "v1" 4) OK 127.0.0.1:6379> set k1 v2 QUEUED 127.0.0.1:6379> discard #放棄修改 OK 127.0.0.1:6379> get k1 "v1"
當事物出現編譯型異常的時候(程式碼有問題,命令有錯),所有的命令都不會執行
如果是執行時候出現語法錯誤,錯誤命令丟擲異常,但是其他命令正常執行,這就是沒有原子性的表現!
#語法審查不過關 127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> qwe (error) ERR unknown command `qwe`, with args beginning with: 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. #出現邏輯錯誤的時候,丟擲異常 127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 "v1" QUEUED 127.0.0.1:6379> incr k1 QUEUED 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) ERR value is not an integer or out of range 3) "v1"
2、redis實現樂觀鎖、悲觀鎖
2.1、先看看沒有鎖帶來的併發問題:
執行緒1
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
執行緒2
127.0.0.1:6379> decrby money 10
(integer) 90
執行緒1提交之後
127.0.0.1:6379> exec 1) (integer) 80 #被其他執行緒影響 2) (integer) 10
出現了髒資料,其實mysql這樣的關係型資料庫通過隔離級別來解決,而redis沒有隔離級別一說,直接通過底層的鎖來實現:
2.1、樂觀鎖
127.0.0.1:6379> watch money #通過watch實現樂觀鎖
OK
加上樂觀鎖,上面的執行緒1提交之後就會
127.0.0.1:6379> exec
(nil) #提交失敗
提交失敗之後怎麼辦呢?
127.0.0.1:6379> unwatch money #放棄監視
OK
127.0.0.1:6379> watch money #重新監視
OK
(然後再次執行操作)
發現沒有,其實就是自旋,不對不一樣,重新獲取最新值(放棄監視然後再監視)
【小結】
一般秒殺這樣的場景會用到redis裡面的樂觀鎖