詳解Redis的LUA腳本、管道 (Pipelining)、事務事務 (Transactions)

1. 管道 (Pipelining)

  • 網絡延遲 (Round-Trip Time - RTT) 瓶頸。

    • 在傳統模式下,客戶端發送一個命令 -> 等待 Redis 服務器處理并返回結果 -> 再發送下一個命令。如果客戶端需要執行大量命令(例如設置或獲取多個鍵),每個命令之間的網絡往返時間(RTT)會成為主要的性能瓶頸,即使每個命令本身執行很快。

  • 原理:

    • 客戶端一次性打包多個命令發送給 Redis 服務器。

    • Redis 服務器按順序連續執行收到的所有命令。

    • 服務器執行完所有命令后,一次性將所有結果打包返回給客戶端。

  • 關鍵特性:

    • 性能優化:?核心目標是極大減少網絡 RTT 次數。將 N 次 RTT 減少為 1 次 RTT(發送請求包 + 接收響應包),顯著提升吞吐量,尤其適合批量寫入或讀取。

    • 非原子性:?管道中的命令雖然是一起發送和返回的,但在執行過程中,命令之間并不是原子的。Redis 會按順序依次執行每個命令。其他客戶端的命令可能穿插在管道中某個命令執行的前后。

    • 無回滾:?如果管道中某個命令執行出錯(例如語法錯誤、對錯誤類型操作),它不會影響其他命令的執行,也不會導致整個管道回滾。客戶端在收到所有結果后需要自行檢查每個命令的返回結果。

  • 使用方式:

    • 客戶端庫通常提供管道支持(如 Python 的?redis-py?使用?pipeline()?方法)。

    • 在 Redis CLI 中,可以手動將多個命令寫在一行(用分號?;?分隔)或使用?echo?和?nc?組合。

  • 適用場景:

    • 需要執行大量獨立、無依賴關系的命令,且對原子性沒有要求。

    • 批量設置(MSET)、批量獲取(MGET?雖然原生支持,但復雜鍵名時仍需管道)、批量刪除(DEL key1 key2 ...)。

    • 數據導入/導出。

    • 需要最大化吞吐量的場景(如實時計數器批量更新)。

  • 優點:

    • 大幅提升吞吐量,減少網絡延遲影響。

    • 使用相對簡單。

  • 缺點:

    • 不保證原子性:?命令可能被其他客戶端插入。

    • 不提供隔離性:?管道執行過程中,其他客戶端可以修改數據。

    • 錯誤處理:?需要客戶端在收到響應后逐一檢查每個命令的結果。

2. 事務 (Transactions)

  • 簡單命令序列的原子性執行需求。

    • 確保一組命令在?EXEC?時作為一個整體連續執行(執行原子性),但運行時錯誤不會回滾已執行的命令。

  • 核心命令:

    • MULTI: 標記事務開始。之后的命令不會立即執行,而是被放入一個隊列

    • EXEC: 執行事務隊列中的所有命令。Redis 會按順序、連續地、原子地執行隊列中的所有命令。在執行?EXEC?期間,服務器不會被其他客戶端的命令打斷。

    • DISCARD: 放棄事務,清空隊列。

    • WATCH key [key ...]:?關鍵機制!?在?MULTI?之前執行。監視一個或多個鍵。如果在?WATCH?之后、EXEC?之前,有任何被監視的鍵被其他客戶端修改,那么當該客戶端執行?EXEC?時,整個事務將被取消(返回?nil)。這是 Redis 實現 CAS(Compare-and-Set)樂觀鎖的基礎。

  • 關鍵特性:

    • 原子性:?EXEC?命令觸發時,隊列中的所有命令作為一個整體執行,不會被其他命令打斷。

    • 隔離性:?通過?WATCH?實現樂觀鎖,可檢測并發修改,但事務本身無隔離性保證。

    • 無回滾:?這是 Redis 事務的一個重要特點!?如果在事務執行過程中(EXEC?之后)某個命令運行時出錯(例如對字符串執行?HINCRBY),只有出錯的命令不會生效,而隊列中其他命令依然會被執行!?Redis 不會回滾已經執行成功的命令。事務的錯誤通常發生在入隊時(命令語法錯誤,Redis 會拒絕入隊)或運行時(數據類型錯誤)。

  • 執行流程:

    • WATCH key?(可選,用于樂觀鎖)

    • MULTI

    • 發送要執行的命令 (這些命令被放入隊列,返回?QUEUED)

    • EXEC?或?DISCARD

      • 如果執行?EXEC

        • 檢查?WATCH?的鍵是否被修改過?是 -> 放棄執行,返回?(nil)

        • 否 -> 按順序原子執行所有隊列命令,返回所有命令的結果數組。

  • 適用場景:

    • 需要保證一組命令原子執行的簡單場景(例如:轉賬?A-100; B+100)。

    • 結合?WATCH?實現樂觀鎖,處理簡單的并發競爭(例如:庫存扣減、搶票)。

  • 優點:

    • 提供命令序列的原子性保證。

    • WATCH?提供了基本的并發控制手段。

  • 缺點:

    • 運行時錯誤不回滾:?事務執行中部分命令失敗,其他命令仍然生效。需要客戶端精心設計命令或依賴?WATCH?重試。

    • 無法獲取中間結果:?在事務中(MULTI?之后),無法直接獲取之前命令的執行結果來決定后續操作(所有命令在?EXEC?時一次性執行)。命令是靜態入隊的。

    • 性能:?雖然?MULTI/EXEC?本身開銷不大,但?WATCH?失敗重試可能導致性能下降。EXEC?執行期間會阻塞其他命令。

    • 復雜性:?需要理解?WATCH?的機制和錯誤處理邏輯。

3. Lua 腳本 (Lua Scripting)

  • ?復雜原子操作、需要中間邏輯判斷、事務的局限性。

    • 事務無法在命令執行過程中根據中間結果做動態決策。

    • 事務的錯誤回滾行為不符合某些預期。

    • 需要執行更復雜的邏輯,這些邏輯無法簡單地拆分成一組 Redis 命令序列。

  • 原理:

    • Redis 內嵌了?Lua 5.1?解釋器。

    • 客戶端將一段?Lua 腳本發送給 Redis 服務器(使用?EVAL?或?EVALSHA)。

    • Redis 服務器在單個線程中原子性地執行整個 Lua 腳本

    • 腳本執行期間,服務器不會執行任何其他命令或腳本(完全隔離)。

    • 腳本可以訪問和操作 Redis 數據,可以包含復雜的邏輯(條件判斷、循環、計算等)。

    • 腳本最后返回一個結果給客戶端。

  • 關鍵特性:

    • 原子性:?核心優勢!?整個腳本的執行是原子的、隔離的。腳本執行過程中不會有其他命令或腳本執行,腳本看到的數據視圖在執行開始時是確定的。

    • 靈活性:?可以使用 Lua 語言的全部特性(變量、條件、循環、函數、表等)實現復雜的業務邏輯。

    • 可獲取中間結果:?腳本內部可以執行多個 Redis 命令(通過?redis.call()?或?redis.pcall()),并能立即獲取這些命令的返回值,用于后續的邏輯判斷和計算。這是超越事務的關鍵點。

    • redis.call(): 執行 Redis 命令,如果命令出錯會拋出 Lua 錯誤,導致整個腳本停止執行(類似事務中的運行時錯誤)。

    • redis.pcall(): 執行 Redis 命令,如果命令出錯會捕獲錯誤并以 Lua 表的形式返回錯誤信息,不會中斷腳本執行,腳本可以處理這個錯誤。

    • 復用性:?腳本可以被緩存(使用?SCRIPT LOAD?返回 SHA1 摘要),后續通過?EVALSHA?用摘要執行,減少網絡傳輸。

  • 使用方式:

    • EVAL "lua_script" numkeys key [key ...] arg [arg ...]

      • lua_script: Lua 腳本字符串。

      • numkeys: 后面跟著的鍵名的個數。

      • key [key ...]: 腳本中用到的 Redis 鍵名,通過?KEYS[1],?KEYS[2]?訪問。

      • arg [arg ...]: 傳遞給腳本的附加參數,通過?ARGV[1],?ARGV[2]?訪問。

    • SCRIPT LOAD "lua_script": 加載腳本并返回 SHA1 摘要。

    • EVALSHA sha1 numkeys key [key ...] arg [arg ...]: 使用 SHA1 摘要執行緩存的腳本。

    • SCRIPT EXISTS sha1 [sha1 ...]: 檢查腳本是否已緩存。

    • SCRIPT FLUSH: 清空腳本緩存。

    • SCRIPT KILL: 終止當前正在執行的腳本(僅當腳本未執行任何寫操作時有效)。

  • 適用場景:

    • 需要真正原子性的復雜操作:?例如:檢查庫存、扣減庫存、記錄訂單;實現分布式鎖(Redlock 或更復雜的鎖);實現自定義的原子計數器/限流器。

    • 需要基于中間結果做決策:?例如:如果?HGET?的值大于 X,則執行?ZADD?和?PUBLISH

    • 封裝復雜操作:?將多個 Redis 命令和業務邏輯封裝成一個原子操作,簡化客戶端代碼。

    • 保證計算與操作原子性:?在腳本中進行計算并基于計算結果更新 Redis。

  • 優點:

    • 真正的原子性和隔離性:?腳本是執行 Redis 命令的最小單元。

    • 強大的靈活性:?幾乎可以實現任何復雜的原子邏輯。

    • 可獲取中間結果:?腳本內部可基于之前命令的返回值進行決策。

    • 復用性:?EVALSHA?減少網絡開銷。

    • 性能:?腳本在服務器端執行,避免了多次網絡 RTT(雖然單次?EVAL?請求可能比單個命令大,但比多次 RTT 好)。腳本執行很快(Redis 單線程高效)。

  • 缺點/注意事項:

    • 腳本編寫:?需要學習 Lua 語法和 Redis Lua API (redis.call,?redis.pcall)。

    • 調試:?Redis Lua 腳本調試相對困難。

    • 阻塞風險:?非常重要!?一個運行緩慢的 Lua 腳本會阻塞整個 Redis 服務器,導致所有其他客戶端請求超時。必須確保腳本是高效的、執行時間可預測的。避免長循環、避免執行大量耗時的命令、避免使用?KEYS?命令。

    • 可復制性:?Lua 腳本在復制和持久化時有一些特殊規則(通常腳本本身和效果都會被復制)。

    • 資源管理:?腳本緩存需要管理(雖然 Redis 會管理,但?SCRIPT FLUSH?需謹慎)。

    • 錯誤處理:?需要理解?redis.call?和?redis.pcall?的錯誤處理差異。腳本中的邏輯錯誤可能導致整個操作失敗(原子性保證)。

總結對比表

特性管道 (Pipeline)事務 (Transaction)Lua 腳本 (Lua Scripting)
核心目標優化性能 (減少 RTT)保證隔離性 (命令連續執行)原子性執行復雜邏輯
發送方式? 批量發送? 逐條發送(MULTI+命令)? 一次性發送(EVAL/EVALSHA
原子性? 不保證。命令逐個執行,可能被穿插。???隔離性而非嚴格原子性。?EXEC?期間連續執行,但運行時錯誤不回滾。??強原子性。?整個腳本執行不可中斷,腳本內錯誤會中止執行(已執行效果保留)。
性能優化??顯著減少 RTT?(主要優勢)?? 批量執行減少部分 RTT,但?WATCH?失敗重試會降低效率。? 減少復雜邏輯的 RTT,但腳本執行本身可能阻塞服務器。
復雜邏輯? 只能執行簡單命令序列。? 只能執行簡單命令序列。? 支持條件、循環、變量、函數等復雜 Lua 邏輯。
錯誤處理每個命令獨立成功/失敗。?? 入隊錯誤導致事務放棄;運行時錯誤僅失敗命令,其他執行。?? 腳本或命令錯誤導致腳本中止,已執行命令效果保留。
阻塞性低。服務器按序執行,但命令間可穿插其他客戶端命令。EXEC?執行期間阻塞其他命令。整個腳本執行期間完全阻塞服務器!
關鍵命令客戶端實現(一次性發送/接收)。MULTI,?EXEC,?DISCARD,?WATCHEVAL,?EVALSHA,?SCRIPT LOAD,?SCRIPT FLUSH
典型場景大批量獨立命令操作(無原子性要求)。需要連續執行且不被干擾的命令組 + 樂觀鎖 (WATCH)。需要原子性執行的復雜業務邏輯(如分布式鎖、限流)。

如何選擇?

  1. 需要高性能批量讀寫,且命令獨立、無原子性要求??->?管道

  2. 需要保證幾個簡單命令要么都成功要么都不成功,并且并發競爭不激烈或可以通過?WATCH?重試解決??->?事務

  3. 需要實現復雜的業務邏輯、需要基于中間結果做決策、需要真正的原子性保證(即使包含邏輯判斷和循環)、或者事務的運行時錯誤不回滾特性不符合需求??->?Lua 腳本?(務必保證腳本高效!)。

  4. 需要結合使用??很常見!例如,使用管道發送多個?EVAL?或?EVALSHA?命令來批量執行多個(獨立的)原子操作。

重要補充:Redis 7 函數 (Functions)

????????Redis 7 引入了?Redis Functions,這是對 Lua 腳本的進一步封裝和增強。它允許你將 Lua 腳本注冊為命名的函數(FUNCTION LOAD),然后像調用內置命令一樣調用它們(FCALL,?FCALL_RO)。這提供了更好的代碼組織、復用性、訪問控制和調試支持(通過?FUNCTION?命令族管理)。函數在底層仍然是 Lua 腳本執行,繼承了其原子性、隔離性、阻塞風險等核心特性,但提供了更優雅和安全的使用方式。對于新項目,特別是需要復用復雜邏輯的場景,推薦優先考慮 Redis Functions。

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

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

相關文章

SIP 協議中的定時器

SIP(Session Initiation Protocol) 是一種信令協議,廣泛用于建立、維持和終止多媒體會話(如VoIP通話)。作為基于UDP等不可靠傳輸的協議,SIP 通過多個定時器機制來確保消息的可靠傳輸和狀態機的正常運行。 …

【機器學習深度學習】偏置項(Bias)概念

目錄 前言 一、先說結論:偏置項是“默認起點” 二、類比理解 類比 1:老師給學生的“基礎分” 類比 2:預測房價時的“固定成本” 三、沒有偏置項的模型,會有什么問題? 四、在神經網絡中,偏置項是神經…

使用數組 海選女主角

問題描述 面試那天,剛好來了m * n個MM,站成一個m * n的隊列,副導演Fe(OH)2為每個MM打了分數,分數都是32位有符號整數。 一開始我很納悶:分數怎么還有負的?Fe(OH)2解釋說,根據選拔規則&#xff…

從0開始學習R語言--Day29--社交網絡分析

在探尋數據之間的關系時,由于數據類型的限制,很多時候我們可以從數據的現實角度出發去選擇方法,而不是一昧地從頭嘗試不同方法去分類。假如我們用的是傳染病在市面上的傳播路徑數據,亦或是病毒對于基因的感染模塊,就可…

一款基于 React 的開源酷炫動畫庫

React Bits 是一個開源的交互式 React 組件庫,包含一系列動畫化、交互式且完全可定制的 React 組件,用于構建令人驚艷且難忘的用戶界面,可幫助開發者在 React 應用中輕松實現各種動畫效果。它提供了超過70種動畫組件,分為文本動畫…

深入理解前端理念bundleless

Bundleless 是一種新興的前端開發趨勢,它的核心思想是減少或完全去除傳統的打包步驟,直接利用瀏覽器對現代 JavaScript 特性(尤其是 ES 模塊)的原生支持。這一趨勢背后的推動力包括現代瀏覽器的進步、開發者對更快開發反饋的需求以及更簡單的開發流程。以下是對 bundleless…

馬斯克YC技術核彈全拆解:Neuralink信號編譯器架構·星艦著陸AI代碼·AGI防御協議(附可復現算法核心/開源替代方案/中國技術對標路徑)

一、Neuralink技術棧深度剖析 ? 神經信號編譯架構(基于已公開專利US20220369936) 關鍵算法實現: # 運動意圖解碼核心(簡化版) import numpy as np from sklearn.ensemble import RandomForestClassifierclass Neura…

【RK3568 嵌入式linux QT開發筆記】 二維碼開源庫 libqrencode 交叉靜態編譯和使用

本文參考文章:https://blog.csdn.net/qq_41630102/article/details/108306720 參考文章有些地方描述的有疏漏,導致筆者學習過程中,編譯的.a文件無法在RK3568平臺運行,故寫本文做了修正,以下僅是自我學習的筆記&#xf…

git本地裸倉庫的“激活”:在同一臺 Linux 服務器上創建工作區

大家好!在之前的文章中,我們探討了 Git 裸倉庫(Bare Repository)的概念,它是沒有工作目錄,只包含 .git 目錄內容的特殊倉庫格式,非常適合作為中心化的代碼集散地或備份。我們也了解了 git clone…

如何排查在docker中運行軟件的故障:Docker故障排查可視化指南,三招鎖定問題根源

很多剛接觸Docker的朋友常覺得故障排查很神秘。其實只需關注CPU、內存、磁盤這三大資源指標!Linux終端雖強大但不夠直觀,下面教你用可視化工具輕松監控: 一、宿主機全局監控:FinalShell 掌控全局 連接宿主機 打開FinalShell&…

【論文筆記】【強化微調】T-GRPO:對視頻數據進行強化微調

tulerfeng/Video-R1: Video-R1: Reinforcing Video Reasoning in MLLMs [🔥the first paper to explore R1 for video] 1. 引述 在強化微調中,像 GRPO、DAPO 這樣的方法都是對文本或者圖片進行微調思考,所以這類微調方法不對時序信息做處理&…

【Unity】動畫系統

0 前言 早些時間學動畫系統時的筆記,實際還沒學完,后續計劃會慢慢補全吧。 1 動畫 通常來說動畫都是動畫師來做的,不過Unity也能實現簡單的動畫效果。PS:官方文檔中,將動畫稱之為動畫剪輯。 1.1 創建動畫 首先在Unit…

C++二級指針的用法指向指針的指針(多級間接尋址)

指向指針的指針是一種多級間接尋址的形式,或者說是一個指針鏈。 指針的指針就是將指針的地址存放在另一個指針里面。 通常,一個指針包含一個變量的地址。當我們定義一個指向指針的指針時,第一個指針包含了第二個指針的地址,第二個…

【格與代數系統】示例

【格與代數系統】格與代數系統匯總 例1 設是由誘導的代數系統,則其上的二元運算滿足(ABCD) A. B. C. D. 代數系統滿足交換律、冪等律、吸收律、結合律 例2 是(ABCD) A.有界格 有界格:有最大、最小元…

Stable Diffusion 項目實戰落地:手機壁紙制作-第一篇 從零基礎到生成藝術品的第一步!

大家好!歡迎來到《StableDiffusion實戰-手機壁紙制作》系列的第一篇! 在這一篇文章里,我們將一起探索如何用StableDiffusion(SD)這款強大的工具,快速制作出炫酷的手機壁紙。 如果你對生成藝術、AI繪圖感興趣,那你一定不能錯過! 你能做什么?你將做什么! 在之前的系…

WEB3開啟 Hardhat 自動驗證有什么意義

這是個非常好的問題,尤其是你在學習 Web3 后端開發時,理解為什么要啟用 Hardhat 自動驗證合約源碼,會讓你開發流程更完整、更專業。 ? 一句話總結: 開啟 Hardhat 自動驗證的意義是:讓你的合約在區塊鏈瀏覽器&#xff…

Qt窗?的學習(一)

Qt窗?是通過QMainWindow類來實現的。 QMainWindow是?個為??提供主窗?程序的類,繼承?QWidget類,并且提供了?個預定義的 布局。QMainWindow包含?個菜單欄(menubar)、多個?具欄(toolbars)、多個浮動窗?(鉚 接部…

C++ 面試題常用總結 詳解(滿足c++ 崗位必備,不定時更新)

📚 本文主要總結了一些常見的C面試題,主要涉及到語法基礎、STL標準庫、內存相關、類相關和其他輔助技能,掌握這些內容,基本上就滿足C的崗位技能(紅色標記為重點內容),歡迎大家前來學習指正&…

git提交的腳本無執行權限怎么辦

問題描述 自己寫的小項目,沒有在服務器安裝 Jenkins 進行項目部署,為了圖方便,在項目中編寫了一個 deploy.sh 腳本文件用來執行項目部署。但是在服務器上 pull 下來之后發現腳本文件沒有執行權限,通過 chmod 命令進行賦權&#x…

004.chromium編譯進階-啟動時傳入cookies

一、目標: 實現傳入參數--set-cookies[{"domain":"https://baidu.com","name":"AAAA","value":"111"},{"domain":"https://baidu.com","name":"BBB","…