redis專項練習三redis的事務和樂觀鎖

2021-09-03 03:13:09 字數 3177 閱讀 9593

redis目前對事務的支援相對簡單。redis只能保證乙個client發起的事務中的命令可以連續的執行,而中間不會插入其他的client命令。當乙個client在乙個鏈結中發出multi命令時,這個鏈結會進入乙個事務上下文,該連線後續的命令不會立即執行,而是先放到乙個佇列中,當執行exec命令時,redis會順序的執行佇列中的所有命令。注意redis的事務和樂觀鎖只針對於redis單機例項,redis的集群沒有事務相關的概念。

redis事務設定的命令有 multi (multi)(開啟事務), exec(執行佇列中的redis命令),discard(取消)redis支援簡單的事務

mysql

redis

開啟start transaction

muitl

語句普通sql

普通命令

失敗rollback 回滾

discard 取消

成功commit

exec

注: rollback與discard 的區別

如果已經成功執行了2條語句, 第3條語句出錯.

rollback後,前2條的語句影響消失.

discard只是結束本次事務,前2條語句(在exec命令之前已經成功的命令)造成的影響仍然還在

#先設定金額為10000

127.0.0.1:6379> set money 10000

ok#獲取金額

127.0.0.1:6379> get money

"10000"

#執行事務操作

127.0.0.1:6379> multi

ok#將所有的redis命令都存在到佇列中,在執行discard(取消執行佇列中的命令)

#或者exec操作(執行存放在佇列中的redis命令)

127.0.0.1:6379> set money 9000

queued

127.0.0.1:6379> get money

queued

#執行操作

127.0.0.1:6379> exec

/**

* redis的事務操作

*/@test

public void testtransaction(),李四的資金:{}",zhangsanmoney,lisimoney);

}

在mutil後面的語句中, 語句出錯可能有2種情況

1: 語法就有問題,

這種,exec時,報錯, 所有語句得不到執行

2: 語法本身沒錯,但適用物件有問題. 比如 zadd 操作list物件

exec之後,會執行正確的語句,並跳過有不適當的語句.

(如果zadd操作list這種事怎麼避免? 這一點,由程式設計師負責)

樂觀鎖:redis大多數是基於資料版本(version)的記錄機制實現的。即為資料增加乙個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表新增乙個version欄位來實現。在讀取資料時,將此版本號一同讀出,之後更新時對此版本號加1。此時,將提交資料的版本號與資料庫表對應記錄的當前版本號進行對比,如果提交的資料版本號大於資料庫當前版本號,則予以更新,否則認為是過期資料。

watch監控:watch命令會監控給定的key,當exec時如果監視的key從呼叫watch後發生過變化,則整個事務會失敗。也可以呼叫watch多次監視多個key,這樣就對指定事務key加樂觀鎖了。注意watch的key是對整個鏈結有效的,事務也一樣。如果鏈結斷開,監視和事務都會被自動清除。當然exex、discard、unwatch命令都會自動清除鏈結中的所有監視。

2.1 只事務實現兩個人搶一張票

client 1

#開啟事務

127.0.0.1:6379> multi

ok#票數自減

127.0.0.1:6379> decr ticket

queued

#等待客戶端2操作 在執行該操作

#客戶端2操作完成後,再執行則票數在0的基礎上-1 則票數為-1 不合理

127.0.0.1:6379> exec

1) (integer) -1

127.0.0.1:6379> get ticket

"-1"

client 2

#客戶端2操作

127.0.0.1:6379> multi

ok#票數自減

127.0.0.1:6379> decr ticket

queued

執行 票數為0

127.0.0.1:6379> exec

1) (integer) 0

出現 票數為負數的情況,則無法確保業務正確性。

client 1

#使用watch命令來監聽ticket  如果在針對該key操作的時候 發現key已經被操作過

#則這次事務所涉及的redis操作都被取消

127.0.0.1:6379> watch ticket

ok127.0.0.1:6379> multi

ok#在票數自減之前,client2已經對ticket進行了操作,則該次事務取消

127.0.0.1:6379> decr ticket

queued

#操作為 nil 說明別的客戶端已經操作過,無法進行相關的操作

127.0.0.1:6379> exec

(nil)

127.0.0.1:6379> get ticket

"0"

client 2

#客戶端2操作

127.0.0.1:6379> multi

ok#票數自減

127.0.0.1:6379> decr ticket

queued

執行 票數為0

127.0.0.1:6379> exec

1) (integer) 0

則不會出現業務超售情況,確保了事務,watch命令在一次key的修改事務完成後失效,如果需要繼續監聽,則重新執行watch命令。

有關redis的事務和樂觀鎖的知識先寫到這裡,以後有什麼新的理解,在重新補充,第一次學習redis,如果有什麼錯誤的地方,希望大家指出,手打不易,看完請點讚,您的點讚是我繼續更新的動力。

redis 練習筆記(四) redis 管理

rename oldkey newkey 鍵的重新命名 renamenx oldkey newkey 重新命名,要求newkey不存在 dbsize 檢視庫 randomkey 返回隨機鍵 expire name second 設定name在second秒後過期 對於字串二次設值後,expire無效...

Redis(三) redis持久化

redis是支援資料持久化的,雖然在生產中經常被當做快取伺服器使用。redis持久化機制分為兩種 第一種是快照第二種是aof日誌。快照原理 前面redis基礎篇中提到,redis是單執行緒的,這個執行緒需要同時處理客戶端的請求和記憶體資料結構的邏輯讀寫,顯然難以在保持高效能的前提下完成這些工作。所以...

redis練習手冊《六》Redis安全

redis資料庫可以設定安全,所以做出相關的任何客戶端都需要在執行命令之前進行身份驗證。為了確保redis需要設定在配置檔案中的密碼驗證一致。例子 下面給出的例子顯示的步驟,以確保redis例項。127.0.0.1 6379 config get requirepass 1 requirepass ...