Redis 之四:Redis 事務和樂觀鎖

事務特點

Redis 事務可以一次執行多個命令, 并且帶有以下三個重要的保證:

  • 批量操作在發送 EXEC 命令前被放入隊列緩存。

  • 收到 EXEC 命令后進入事務執行,事務中任意命令執行失敗,其余的命令依然被執行。不具備原子性。

  • 在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中。

Redis 事務的缺點
  1. 不支持回滾: Redis事務在執行EXEC命令之前,如果通過WATCH檢測到監視的鍵發生了變化,則會拒絕執行整個事務并返回空結果。但請注意,這并不是傳統數據庫中的“回滾”操作,因為Redis不會自動撤銷已經執行過的命令,它僅僅是在事務中止時阻止后續未執行的命令。
  2. 命令排隊一次性執行: 在Redis事務中,所有命令會被放入一個隊列,在EXEC命令被執行時按照先進先出的順序執行,期間不能中斷或插入新的命令。這意味著事務開始后無法根據中間結果動態調整事務內的操作,降低了靈活性。
  3. 無隔離級別: Redis的事務沒有提供如SQL數據庫那樣的多種事務隔離級別(如讀已提交、可重復讀等)。所有事務都是在單線程環境下的串行化執行,因此避免了臟讀、不可重復讀等問題,但這也意味著在高并發場景下可能會有性能瓶頸。
  4. Watch-Multi-Exec模式的問題: 使用WATCH進行樂觀鎖控制時,一旦網絡延遲或者客戶端異常導致事務未能及時執行,監視的數據可能已經被其他客戶端修改,此時即便事務最終執行,也無法保證數據一致性。
  5. 批量操作不具備完全的原子性: 雖然Redis的所有命令在服務器內部是原子執行的,但在一個事務中多個命令的組合并不能視為一個原子操作。例如,事務中包含對多個key的操作,即使其中一個操作失敗,事務內其它命令也會被執行完畢,而不是整體取消。
三個階段

一個事務從開始到執行會經歷以下三個階段:

  • 開始事務。
  • 命令入隊。
  • 執行事務。
案例步驟

從multi 開始,一系列操作,最后執行 exec ,批量執行處理

127.0.0.1:6379> multi
OK
127.0.0.1:6379> keys *
QUEUED
127.0.0.1:6379> hset person name zhang age 34
QUEUED
127.0.0.1:6379> hdel person age
QUEUED
127.0.0.1:6379> hset person email zhang@sina.com
QUEUED
127.0.0.1:6379> exec
1)  1) "listz"2) "book"3) "word"4) "myset"5) "mydest"6) "student"
2) (integer) 2
3) (integer) 1
4) (integer) 1
127.0.0.1:6379> hgetall person
1) "name"
2) "zhang"

下表列出了 redis 事務的相關命令:

序號命令及描述
1[DISCARD] 取消事務,放棄執行事務塊內的所有命令。
2[EXEC] 執行所有事務塊內的命令。
3[MULTI] 標記一個事務塊的開始。
4[UNWATCH] 取消 WATCH 命令對所有 key 的監視。
5[WATCH key [key ...]] 監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷。
樂觀鎖

樂觀鎖(Optimistic Locking)是一種在數據庫并發控制中的策略,它假設多用戶同時訪問同一數據時發生沖突的概率較低,并且在更新數據之前并不立即進行加鎖操作。與悲觀鎖不同的是,悲觀鎖在讀取數據時就直接獲取并持有鎖,直到事務結束才釋放;而樂觀鎖則是:

  1. 讀取階段:當一個事務想要修改數據時,它不會立即鎖定該數據行。每個事務在讀取數據時都會記錄下當時的數據版本號或時間戳等信息。
  2. 驗證階段:在事務提交更新操作前,會再次檢查當前要更新的數據是否自上次讀取以來沒有被其他事務修改過。這通常通過比較數據的版本號來實現,如果版本號未變,則認為可以安全地執行更新。
  3. 更新階段:如果數據版本驗證通過(即版本號仍為事務開始讀取時的版本),則執行更新操作,并將數據版本號遞增,確保后續的并發事務能夠識別出這次更新。如果發現版本號已被改變,說明存在并發修改,此時樂觀鎖機制會讓當前事務回滾,并提示并發錯誤,通常需要重新讀取數據并嘗試更新。
Redis 樂觀鎖

Redis 樂觀鎖是一種在分布式系統中實現并發控制的機制,它借鑒了數據庫領域的樂觀并發控制思想,并通過Redis提供的命令來實現。在樂觀鎖策略下,假定多個客戶端同時訪問同一數據時,通常不會發生沖突或至少沖突的概率較低。因此,在讀取數據時不立即加鎖,而是在更新數據前才去檢查在此期間是否有其他客戶端修改過該數據。

在Redis中,樂觀鎖主要通過WATCH命令和事務(multi/exec)來實現:

  1. WATCH命令:客戶端使用WATCH命令監視一個或多個鍵,這些鍵的數據狀態將被記錄下來。當執行WATCH后,如果任何被監視的鍵在事務提交前發生了變化,則整個事務將會被打斷,即不會執行EXEC命令內的操作。
  2. 事務處理:客戶端可以將一系列命令放入事務中,使用MULTI開始一個事務塊,然后執行一系列的操作指令。最后,用EXEC命令嘗試提交事務。只有在所有被WATCH的鍵自WATCH以來未被其他客戶端改變的情況下,事務中的命令才會被執行。

舉例來說:

  • 客戶端A對一個鍵進行WATCH
  • 然后客戶端A開始一個事務,并準備修改這個鍵的值。
  • 在事務提交(EXEC)之前,如果其他客戶端改變了該鍵的值,那么客戶端A的事務在執行EXEC時會發現數據已經被修改,從而導致事務回滾,不執行任何操作。

下面具體來舉例:

主要是 watch 和 multi 兩個命令配合使用,實現樂觀鎖

watch 監視某一個可能變化的 key。然后開啟事務,一系列操作放入隊列等待執行,如果在exec 執行事務之前,其他的客戶端對監視的key 做了修改,則exec 執行結果為nil 。什么都不執行。

127.0.0.1:6379> watch mm         #### 開始監視 mm 變量
OK
127.0.0.1:6379> multi            #### 開啟事務
OK
127.0.0.1:6379> incrby mm 500    #### 第一次 給 mm 加500 操作放入隊列
QUEUED
127.0.0.1:6379> incrby mm 500    #### 第二次 給 mm 加500 操作放入隊列 
QUEUED
### 此時去另一個客戶端執行修改操作

另一個客戶端的修改操作

127.0.0.1:6379> decrby mm 500    #### 給 mm 減去500
(integer) -500                   #### 立即起效,結果為 -500

然后再回原來執行事務的客戶端執行下面操作:

127.0.0.1:6379> exec             #### 開始執行事務
(nil)                            #### 沒有任何執行結果  因為樂觀鎖起作用了
127.0.0.1:6379> get mm           #### 再次查看結果
"-500"                           #### 是另一個客戶端的執行結果。剛才加的兩次500 無效。
127.0.0.1:6379> watch mm         #### 再次監控
OK
127.0.0.1:6379> multi            #### 開啟事務
OK
127.0.0.1:6379> incrby mm 500    #### 加500
QUEUED
127.0.0.1:6379> incrby mm 500    #### 加500
QUEUED
127.0.0.1:6379> exec             #### 執行事務
1) (integer) 0
2) (integer) 500                 #### 執行成功,因為其他客戶端沒有修改被監視的變量 mm .
127.0.0.1:6379> 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/710704.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/710704.shtml
英文地址,請注明出處:http://en.pswp.cn/news/710704.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

通訊錄——C語言實現

頭文件Contact.h #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib.h> #pragma once #define MAX 100 #define MAX_NAME 20 #define MAX_SEX 5 #define MAX_TELE 12 #define MAX_ADDR 30//表示一個人的信息 //struct…

npm使用國內淘寶鏡像的方法整理

命令配置安裝&#xff1a; 淘寶鏡像&#xff1a; npm config set registry https://registry.npm.taobao.org/ 官方鏡像&#xff1a; npm config set registry https://registry.npmjs.org 通過cnpm安裝&#xff1a; npm install -g cnpm --registryhttps://registry.npm.…

PTA L2-003 月餅 (附坑點說明)

月餅是中國人在中秋佳節時吃的一種傳統食品&#xff0c;不同地區有許多不同風味的月餅。現給定所有種類月餅的庫存量、總售價、以及市場的最大需求量&#xff0c;請你計算可以獲得的最大收益是多少。 注意&#xff1a;銷售時允許取出一部分庫存。樣例給出的情形是這樣的&#…

如何在Java中反轉字符串?

目錄 1. 使用StringBuilder的reverse方法&#xff1a; 2. 使用for循環和字符數組&#xff1a; 3. 使用遞歸&#xff1a; 4. 使用Java 8的Stream API&#xff1a; More Java中&#xff0c;反轉字符串可以通過多種方式實現。以下是一些常見的方法&#xff1a; 1. Java中使用…

【Python】PyGameUI控件

哈里前段時間寫了一個windows平板上自娛自樂&#xff08;春節和家人一起玩&#xff09;基于pygame的大富翁游戲。 pygame沒有按鈕之類的UI控件&#xff0c;寫起來不怎么順手。就自己寫一個簡單的框架。 倉庫地址 哈里PygameUi: pygame ui封裝自用 (gitee.com) 使用示例 示…

上海亞商投顧:滬指終結月線6連陰 北向資金凈買入超160億

上海亞商投顧前言&#xff1a;無懼大盤漲跌&#xff0c;解密龍虎榜資金&#xff0c;跟蹤一線游資和機構資金動向&#xff0c;識別短期熱點和強勢個股。 一.市場情緒 三大指數昨日低開高走&#xff0c;滬指重新站上3000點&#xff0c;深成指、創業板指大漲超3%。半導體產業鏈全…

實時聊天系統PHP

實時聊天系統可以讓用戶在網站上實時交流&#xff0c;這對社交平臺、在線客服等網站非常有幫助。以下是一個簡單的基于 PHP 和 WebSocket 的實時聊天系統示例&#xff1a; 1. 首先創建一個 HTML 文件 index.html 來顯示聊天界面和發送消息的表單&#xff1a; html <!DOCTYP…

【C#】 List.Sort 方法

【C#】 List.Sort 方法 在C#中&#xff0c;List.Sort()不僅為系統自帶的變量(int, float, double …)類型的集合提供默認排序&#xff0c;還提供了自定義的排序方法。 List自帶排序 List<int> list new List<int>(); list.Add(5); list.Add(3); list.Add(4); l…

探索那些能喚起情感共鳴的壁紙

1、方小童在線工具集 網址&#xff1a; 方小童 該網站是一款在線工具集合的網站&#xff0c;目前包含PDF文件在線轉換、隨機生成美女圖片、精美壁紙、電子書搜索等功能&#xff0c;喜歡的可以趕緊去試試&#xff01;

Python:關于數據服務中的Web API的設計

搭建類似joinquant、tushare類似的私有數據服務應用&#xff0c;有以下一些點需要注意&#xff1a; 需要說明的是&#xff0c;這里討論的是web api前后端&#xff0c;當然還有其它方案&#xff0c;thrift&#xff0c;grpc等。因為要考慮到一魚兩吃&#xff0c;本文只探討web ap…

高項軟考電子版論文答題紙(附下載)

24年軟考又要來了&#xff0c;作為高項軟考的攔路虎&#xff0c;論文你準備好了嗎&#xff1f;&#xff01;記住在開始考試之前一定要用論文答題紙上把準備好的論文&#xff0c;在規定的時間內寫上幾遍&#xff0c;一是現在很少動筆寫字了。二是、熟悉一下論文考試的感覺。 準備…

UniApp Vue 3 中的網絡請求封裝詳解及用法

在UniApp中&#xff0c;結合Vue 3的強大特性&#xff0c;進行網絡請求的封裝是項目中常見的需求。這樣的封裝不僅提高了代碼的可維護性&#xff0c;還使得在組件中使用網絡請求更加簡潔。本文將詳細介紹UniApp Vue 3中的網絡請求封裝&#xff0c;并提供一個簡單的用法示例。 1…

索引使用規則4——覆蓋索引回表查詢

覆蓋索引&#xff1a;查詢使用了索引&#xff0c;并且需要返回的列&#xff0c;在索引里面都可以找到&#xff0c;減少select*的使用 1、using index condition Extra 為using index condition 表明查找使用了索引&#xff0c;但是需要回表查詢&#xff08;也就是先二級索引&…

第十八屆全國大學生智能汽車競賽——攝像頭算法(附帶個人經驗)

文章目錄 前言一、攝像頭圖像處理1、攝像頭圖像采集2、圖像二值化與大津算法 二、左右邊界&#xff0c;中線掃描 前言 參加了第十六&#xff0c;十七和第十八屆全國大學生智能車競賽&#xff0c;對攝像頭的學習有部分心得&#xff0c;分享給大家&#xff0c;三屆車賽&#xff…

【C語言基礎】:深入理解指針(一)

文章目錄 一、內存和地址1. 內存2. 如何理解編址 二、指針變量和地址2.1 取地址操作符(&)2.2 指針變量和解引用操作符(*)2.2.1 指針變量2.2.2 如何拆解指針變量2.2.3 解引用操作符 2.3 指針變量的大小 三、指針變量類型的意義3.1 指針的解引用3.2 指針 - 整數3.3 void*指針…

HCIA-HarmonyOS設備開發認證V2.0-習題

目錄 習題一習題二&#xff08;待續...&#xff09;堅持就有收獲 習題一 # HarmonyOS簡介 1. 以下哪幾項屬于OpenHarmony的技術特性&#xff1f;&#xff08;&#xff09;A. 統一OS&#xff0c;彈性部署B. 一次開發&#xff0c;多端部署C. 硬件互助&#xff0c;資源共享2. Ope…

從零開始的Java知識(下)

從零開始的Java知識 雙列數據集合&#xff08;Day1&#xff09;Map 雙列數據集合&#xff08;Day1&#xff09; Map 注意點&#xff1a; Map一次加入一個key-value一個key對應一個valuekey與key之間是不重復的key-value被稱為鍵值對&#xff0c;鍵值對對象或者是entry對象 …

離散數學

(理解大于識記, 這么多公式我是記不住) 命題邏輯 P P P Q Q Q P \neg P P 否定/非 P ∧ Q P \wedge Q P∧Q 合取/與 P ∨ Q P \vee Q P∨Q 析取/或 P → Q P \to Q P→Q 蘊含 P ? Q P \leftrightarrow Q P?Q 等價0010011011011010001001101111 P → Q P\to Q P→Q 的自然語…

openssl 加密文件(支持大文件,對稱、非對稱)

一、非對稱加密&#xff08;小文件&#xff09; 生成 2048 位密鑰 openssl genrsa -out rsa2048.key 2048從 rsa2048.key 密鑰文件中提取出公鑰 pub2048.key openssl rsa -in rsa2048.key -pubout -out pub2048.key使用 pub2048.key 公鑰加密一個文件 (data.zip 為原始文件&…

C# WPF編程-創建項目

1.創建新項目 選擇“WPF應用程序”》“下一步” 2. 設置項目 設置項目名稱&#xff0c;保存位置等參數>下一步 3.選擇框架 4.項目創建成功 5.運行項目