日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis的基础事务

發布時間:2025/3/12 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis的基础事务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Redis 存在事務,盡管它沒有數據庫那么強大,但是它還是很有用的,尤其是在那些需要高并發的網站當中。

使用 Redis 讀/寫數據要比數據庫快得多,如果使用 Redis 事務在某種場合下去替代數據庫事務,則可以在保證數據一致性的同時,大幅度提高數據讀/寫的響應速度。

互聯網和傳統企業管理系統不一樣,互聯網系統面向的是公眾,很多用戶同時訪問服務器的可能性很大,尤其在一些商品搶購、搶紅包等場合,對性能和數據的一致性有著很高的要求,而存儲系統的讀/寫響應速度對于這類場景的性能的提高是十分重要的。

在 Redis 中,也存在多個客戶端同時向 Redis 系統發送命令的并發可能性,因此同一個數據,可能在不同的時刻被不同的線程所操縱,這樣就出現了并發下的數據一致的問題。為了保證異性數據的安全性,Redis 為提供了事務方案。而 Redis 的事務是使用 MULTI-EXEC 的命令組合,使用它可以提供兩個重要的保證:

事務是一個被隔離的操作,事務中的方法都會被 Redis 進行序列化并按順序執行,事務在執行的過程中不會被其他客戶端發生的命令所打斷。事務是一個原子性的操作,它要么全部執行,要么就什么都不執行。

在一個 Redis 的連接中,請注意要求是一個連接,所以更多的時候在使用 Spring 中會使用 SessionCallback 接口進行處理,在 Redis 中使用事務會經過 3 個過程:

開啟事務。命令進入隊列。執行事務。

Redis事務命令

在 Redis 中開啟事務是 multi 命令,而執行事務是 exec 命令。multi 到 exec 命令之間的 Redis 命令將采取進入隊列的形式,直至 exec 命令的出現,才會一次性發送隊列里的命令去執行,而在執行這些命令的時候其他客戶端就不能再插入任何命令了,這就是 Redis 的事務機制。

Redis 命令執行事務的過程。

從圖中可以看到,先使用 multi 啟動了 Redis 的事務,因此進入了 set 和 get 命令,我們可以發現它并未馬上執行,而是返回了一個“QUEUED”的結果。

這說明 Redis 將其放入隊列中,并不會馬上執行,當命令執行到 exec 的時候它就會把隊列中的命令發送給 Redis 服務器,這樣存儲在隊列中的命令就會被執行了,所以才會有“OK”和“value1”的輸出返回。

如果回滾事務,則可以使用 discard 命令,它就會進入在事務隊列中的命令,這樣事務中的方法就不會被執行了,使用 discard 命令取消事務如圖所示。

當我們使用了 discard 命令后,再使用 exec 命令時就會報錯,因為 discard 命令已經取消了事務中的命令,而到了 exec 命令時,隊列里面已經沒有命令可以執行了,所以就出現了報錯的情況。

在 Spring 中要使用同一個連接操作 Redis 命令的場景,這個時候我們借助的是 Spring 提供的 SessionCallback 接口,采用 Spring 去實現上述命令,代碼如下所示。

ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); SessionCallback callBack = (SessionCallback) (RedisOperations ops)-> {ops.multi();ops.boundValueOps("key1").set("value1");//注意由于命令只是進入隊列,而沒有被執行,所以此處采用get命令,而value卻返回為nullString value = (String) ops.boundValueOps("key1").get();System.out.println ("事務執行過程中,命令入隊列,而沒有被執行,所以value為空: value="+value);//此時list會保存之前進入隊列的所有命令的結果List list = ops.exec(); //執行事務//事務結束后,獲取value1value = (String) redisTemplate.opsForValue().get("key1");return value; }; //執行Redis的命令 String value = (String)redisTemplate.execute(callBack); System.out.println(value);

這里采用了 Lambda 表達式(注意,Java 8 以后才引入 Lambda 表達式)來為 SessionCallBack 接口實現了業務邏輯。從代碼看,使用了 SessionCallBack 接口,從而保證所有的命令都是通過同一個 Redis 的連接進行操作的。

在使用 multi 命令后,要特別注意的是,使用 get 等返回值的方法一律返回為空,因為在 Redis 中它只是把命令緩存到隊列中,而沒有去執行。使用 exec 后就會執行事務,執行完了事務后,執行 get 命令就能正常返回結果了。

最后使用 redisTemplate.execute(callBack); 就能執行我們在 SessionCallBack 接口定義的 Lambda 表達式的業務邏輯,并將獲得其返回值。執行代碼后可以看到這樣的結果,如圖所示:

這里打印出來的 value=null,是因為在事務中,所有的方法都只會被緩存到 Redis 事務隊列中,而沒有立即執行,所以返回為 null。如果我們希望得到 Redis 執行事務各個命令的結果,可以用這行代碼:

List list = ops.exec(); //執行事務

這段代碼將返回之前在事務隊列中所有命令的執行結果,并保存在一個 List 中,我們只要在 SessionCallback 接口的 execute 方法中將 list 返回,就可以在程序中獲得各個命令執行的結果了。

總結

以上是生活随笔為你收集整理的Redis的基础事务的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。