Redis中的事務和原子性

在 Redis 中,事務原子性 是兩個關鍵概念,用于保證多個操作的一致性和可靠性。以下是 RedissonSpring Data Redis 在處理原子性操作時的區別與對比:


1. Redis 的原子性機制

Redis 本身通過以下方式保證原子性:

  • 單線程模型:所有命令按順序執行,單個命令默認是原子的。
  • 事務(MULTI/EXEC:將多個命令打包為一個事務,按順序執行,但不支持回滾。
  • Lua 腳本:通過 EVAL 執行的 Lua 腳本在 Redis 中是原子執行的,適合復雜邏輯。

2. Redisson 的分布式集合操作(如 putIfAbsent

Redisson 封裝了 Redis 的分布式數據結構(如 RMapRLock 等),其操作默認是線程安全的,并且內部通過 Lua 腳本Redis 事務 保證原子性。

示例:Redisson 的 putIfAbsent
RMap<String, String> map = redisson.getMap("myMap");
String value = map.putIfAbsent("key", "value");
  • 實現原理
    Redisson 內部通過 Lua 腳本實現 putIfAbsent,邏輯類似:
    if redis.call("EXISTS", KEYS[1]) == 0 thenreturn redis.call("SET", KEYS[1], ARGV[1])
    elsereturn nil
    end
    
  • 原子性保障
    由于 Lua 腳本在 Redis 單線程中執行,整個操作是原子的,無需開發者手動處理事務。
優點
  • 簡化開發:開發者無需關注底層的 Lua 腳本或事務。
  • 開箱即用:適合分布式鎖、隊列、集合等常見場景。
適用場景
  • 快速實現分布式集合操作(如 putIfAbsentfastPut)。
  • 需要線程安全的分布式數據結構(如 RMapRSet)。

3. Spring Data Redis 的原子性保障

Spring Data Redis 提供了對 Redis 的原生操作支持,但需要開發者通過 Lua 腳本事務 顯式保證原子性。

示例:通過 Lua 腳本實現 putIfAbsent
DefaultRedisScript<String> script = new DefaultRedisScript<>();
script.setScriptText("if redis.call('EXISTS', KEYS[1]) == 0 then return redis.call('SET', KEYS[1], ARGV[1]) else return nil end");
script.setResultType(String.class);String result = redisTemplate.execute(script, Collections.singletonList("key"), "value");
示例:通過事務實現原子性
redisTemplate.setEnableTransactionSupport(true);
TransactionStatus status = redisTemplate.getTransactionManager().beginTransaction();
try {redisTemplate.opsForValue().set("key", "value");redisTemplate.boundValueOps("key").get();redisTemplate.getTransactionManager().commit(status);
} catch (Exception e) {redisTemplate.getTransactionManager().rollback(status);
}
原子性保障
  • Lua 腳本:通過 EVAL 執行的腳本在 Redis 中是原子的。
  • 事務MULTI/EXEC 保證命令按順序執行,但不支持回滾。
優點
  • 靈活性:可直接使用 Redis 的原生命令和高級特性。
  • 性能優化:通過管道(Pipeline)減少網絡往返。
適用場景
  • 高頻讀寫緩存(如熱點數據)。
  • 復雜業務邏輯(如排行榜、分布式計數器)。
  • 需要直接調用 Redis 的 SCANBITFIELD 等高級命令。

4. 對比總結

維度RedissonSpring Data Redis
原子性保障方式內部封裝 Lua 腳本或 Redis 事務,開發者無需手動處理。需要顯式使用 Lua 腳本或事務。
開發復雜度簡單,直接調用 Java 集合接口(如 putIfAbsent)。復雜,需自行編寫 Lua 腳本或事務邏輯。
性能封裝可能引入額外開銷(如序列化),適合中低并發場景。原生 Redis 命令調用,性能更高,適合高并發場景。
適用場景分布式鎖、隊列、集合操作等常見場景。緩存、排行榜、復雜數據結構操作等高性能場景。
線程安全所有 API 默認線程安全。Lettuce 連接線程安全,但需注意多線程操作 Redis 命令的原子性。

5. 選擇建議

  • 優先使用 Redisson
    如果需要快速實現 分布式集合操作(如 putIfAbsentremoveIfPresent)或 分布式鎖(如 RLock),優先選擇 Redisson。其封裝的 Lua 腳本和事務邏輯隱藏了復雜性,適合快速開發。

  • 優先使用 Spring Data Redis + Lua
    如果需要 高性能緩存復雜業務邏輯(如排行榜、分布式計數器),使用 Spring Data Redis 并結合 Lua 腳本。通過精細控制 Redis 命令,可以優化性能并充分利用 Redis 的原生特性。

  • 混合使用注意事項

    • 連接池分離:Redisson 和 Spring Data Redis 使用不同的連接池,避免資源競爭。
    • 鍵名命名規范:避免鍵名沖突(如 Redisson 使用前綴 redisson:,Spring Data Redis 使用前綴 spring:)。
    • 集群模式下的原子性:確保 Lua 腳本操作的 key 在同一個 slot,否則原子性無法保證。

6. 實際案例

案例 1:分布式計數器
  • Redisson

    RAtomicLong counter = redisson.getAtomicLong("counter");
    counter.incrementAndGet(); // 原子操作
    
  • Spring Data Redis

    DefaultRedisScript<Long> script = new DefaultRedisScript<>();
    script.setScriptText("return redis.call('INCR', KEYS[1])");
    script.setResultType(Long.class);
    Long count = redisTemplate.execute(script, Collections.singletonList("counter"));
    
案例 2:分布式鎖
  • Redisson

    RLock lock = redisson.getLock("lock");
    lock.lock();
    try {// 臨界區操作
    } finally {lock.unlock();
    }
    
  • Spring Data Redis

    String lockKey = "lock";
    Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
    if (Boolean.TRUE.equals(isLocked)) {try {// 臨界區操作} finally {redisTemplate.delete(lockKey);}
    }
    

通過合理選擇工具和實現方式,可以充分發揮 Redis 的原子性保障能力,構建高效、可靠的分布式系統。

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

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

相關文章

Apollo10.0學習——planning模塊(8)之scenario、Stage插件詳解二

scenario插件 插件總覽插件ValetParkingScenario階段一&#xff1a;StageApproachingParkingSpotprocess()方法 階段二&#xff1a;StageParkingprocess()方法FinishStage方法 插件PullOverScenarioIsTransferable: 場景切入條件 代碼邏輯階段一&#xff1a;PullOverStageAppro…

JVM的面試相關問題

面試中的相關問題主要是三塊 1.JVM 內存區域劃分 2.JVM 的類加載機制 3.JVM 的垃圾回收機制 JVM Java虛擬機 VM Virtual Machine 虛擬機,用 軟件 來 模擬 硬件 傳統意義上的"虛擬機" 更多指的是 VMWare, Virtual Box, Hyper-V, KVM(構造出虛擬的電腦,甚至可以…

win10使用nginx做簡單負載均衡測試

一、首先安裝Nginx&#xff1a; 官網鏈接&#xff1a;https://nginx.org/en/download.html 下載完成后&#xff0c;在本地文件中解壓。 解壓完成之后&#xff0c;打開conf --> nginx.config 文件 1、在 http 里面加入以下代碼 upstream GY{#Nginx是如何實現負載均衡的&a…

[特殊字符]車牌識別相機,到底用在哪?

停車場管理&#xff0c;快速通行不是夢 停車場大概是車牌識別相機最常見的 “工作崗位” 啦&#xff01;以前進出停車場&#xff0c;取卡、刷卡、人工收費&#xff0c;一系列操作下來&#xff0c;高峰期的時候真的能把人等得不耐煩&#x1f62b; 現在有了車牌識別相機&#xff…

nosqlbooster pojie NoSQLBooster for MongoDB

測過可用&#xff0c;注意 asar的安裝使用報錯改用 npx asar extract app.asar app 路徑 C:\Users{computerName}\AppData\Local\Programs\nosqlbooster4mongo\resources npm install asar -g asar extract app.asar app 打開shared\lmCore.js 修改MAX_TRIAL_DAYS3000 修改…

組態王通過開疆智能profinet轉ModbusTCP網關連接西門子PLC配置案例

本案例是組態王通過使用開疆智能研發的Profinet轉ModbusTCP網關采集西門子1200PLC中數據的案例。 網關配置 首先來配置網關的參數&#xff0c;打開網關配置軟件“Gateway Configuration Studio” 由于組態王那側設定為ModbusTCP客戶端所以網關作為ModbusTCP服務器。新建項目…

大模型服務如何實現高并發與低延遲

寫在前面 大型語言模型(LLM)正以前所未有的速度滲透到各行各業,從智能客服、內容創作到代碼生成、企業知識庫,其應用場景日益豐富。然而,將這些強大的 AI 能力轉化為穩定、高效、可大規模應用的服務,卻面臨著巨大的挑戰,其中高并發處理能力和低響應延遲是衡量服務質量的…

k8s監控方案實踐補充(二):使用kube-state-metrics獲取資源狀態指標

k8s監控方案實踐補充&#xff08;二&#xff09;&#xff1a;使用kube-state-metrics獲取資源狀態指標 文章目錄 k8s監控方案實踐補充&#xff08;二&#xff09;&#xff1a;使用kube-state-metrics獲取資源狀態指標一、Metrics Server簡介二、kube-state-metrics實戰部署1. 創…

Manus 全面開放注冊,OpenAI 發布 Codex,ChatGPT 上線 GPT-4.1!| AI Weekly 5.12-18

&#x1f4e2;本周 AI 快訊 | 1 分鐘速覽&#x1f680; 1?? &#x1f4dd; Manus 全面開放注冊 &#xff1a;無需邀請碼即可注冊&#xff0c;新用戶免費獲得 1000 積分&#xff0c;每日 300 積分免費任務。 2?? &#x1f50d; 阿里 Qwen 推出「深入研究」 &#xff1a;Qw…

代理(主要是動態)和SpringAOP

代理 靜態代理基于繼承實現動態代理是基于接口實現 業務層每次實現轉賬都需要執行&#xff0c;可以把他們拿出來當成一個切面&#xff0c;自己寫出一個代理類&#xff0c;讓業務層只執行業務的邏輯&#xff0c;重復的代碼代理類來完成&#xff0c;然后調用代理類來執行。 代理類…

uniapp打包H5,輸入網址空白情況

由于客戶預算有限&#xff0c;最近寫了兩個uniapp打包成H5的案例&#xff0c;總結下面注意事項 1. 發行–網站-PCWeb或手機H5按鈕&#xff0c;輸入名稱&#xff0c;網址 點擊【發行】&#xff0c;生成文件 把這個給后端&#xff0c;就可以了 為什么空白呢 最重要一點&#xf…

uniapp-商城-63-后臺 商品列表(分類展示商品的刪除)

商品列表中的數據需要進行狀態管理&#xff0c;如上架、下架、刪除和修改等操作。對于存在錯誤或后期需要重新上傳的商品&#xff0c;可以通過刪除操作進行處理。 具體到商品刪除功能的實現&#xff0c;其基本流程如下&#xff1a;用戶在前端頁面點擊刪除按鈕后&#xff0c;系統…

學習設計模式《十》——代理模式

一、基礎概念 代理模式的本質【控制對象訪問】&#xff1b; 代理模式的定義&#xff1a;為其他對象提供一種代理以控制對這個對象的訪問&#xff1b; 代理模式的功能&#xff1a;代理模式是通過創建一個代理對象&#xff0c;用這個代理對象去代表真實的對象&#xff1b;客戶端得…

阿里云web端直播(前端部分)

阿里云&#xff1a;Web播放器快速接入_視頻點播(VOD)-阿里云幫助中心 import Aliplayer from aliyun-aliplayerimport aliyun-aliplayer/build/skins/default/aliplayer-min.css<div id"J_prismPlayer" style"width: 300px; height: 300px;" />var …

深入解析OrientDB:多模型數據庫的技術優勢與實際應用

OrientDB 是一款開源的多模型 NoSQL 數據庫&#xff0c;融合了文檔數據庫、圖數據庫和對象數據庫的特性。它不僅支持靈活的數據建模&#xff0c;還提供了高性能的查詢能力&#xff0c;適用于社交網絡、物聯網、內容管理等場景。本文詳細探討 OrientDB 的核心特性、應用場景&…

STM32控制電機

初始化時鐘&#xff1a;在 STM32 的程序中&#xff0c;初始化系統時鐘&#xff0c;一般會使用 RCC&#xff08;Reset and Clock Control&#xff09;相關函數來配置時鐘。例如&#xff0c;對于 STM32F103 系列&#xff0c;可能會使用 RCC_APB2PeriphClockCmd 函數來使能 GPIO 和…

(05)數字化轉型之生產制造:從通常的離散制造到柔性化生產的全景指南

當今制造業正經歷著前所未有的數字化變革&#xff0c;從傳統的離散制造到流程制造&#xff0c;再到新興的項目制造和柔性制造&#xff0c;各種生產模式都在加速向智能化方向演進。本文將系統性地介紹制造業生產管理的完整體系&#xff0c;為企業數字化轉型提供全面的方法論和實…

龍虎榜——20250520

上證指數今天縮量向上&#xff0c;個股漲多跌少&#xff0c;大盤股和小盤股總體表現都還可以。 深證同樣縮量上漲&#xff0c;向上補缺口的概率增大。 2025年5月20日龍虎榜行業方向分析 寵物經濟&#xff08;消費升級政策催化&#xff09; ? 代表標的&#xff1a;天元寵物、…

CVE-2022-22978源碼分析與漏洞復現

漏洞概述 CVE-2022-22978 是 Spring Security 框架中的一個高危認證繞過漏洞&#xff0c;影響版本包括 Spring Security 5.5.x < 5.5.7、5.6.x < 5.6.4 及更早的不受支持版本。攻擊者可通過構造包含換行符&#xff08;如 %0a&#xff09;的 URL 路徑&#xff0c;繞過正則…

PostGIS實現柵格數據入庫【raster2pgsql】

raster2pgsql使用與最佳實踐 一、工具概述 raster2pgsql是PostGIS提供的命令行工具,用于將GDAL支持的柵格格式(如GeoTIFF、JPEG、PNG等)導入PostgreSQL數據庫,支持批量加載、分塊切片、創建空間索引及金字塔概覽,是柵格數據入庫的核心工具。 二、核心功能與典型用法 1…