1. 程式人生 > 其它 >【redis】redis事物和鎖

【redis】redis事物和鎖

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裡面的樂觀鎖