SpringBoot Redisson 集成的實(shí)現(xiàn)示例
一、引入依賴
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.23.5</version> </dependency>
redison-spring-boot-starter依賴于與最新版本的spring-boot兼容的redison-spring數(shù)據(jù)模塊。降級(jí)redison彈簧數(shù)據(jù)模塊(如有必要),以支持以前的spring Boot版本:
redisson-spring-data module name | Spring Boot version |
---|---|
redisson-spring-data-16 | 1.3.y |
redisson-spring-data-17 | 1.4.y |
redisson-spring-data-18 | 1.5.y |
redisson-spring-data-2x | 2.x.y |
redisson-spring-data-3x | 3.x.y |
二、添加配置文件
使用 common Spring Boot 3.x+ settings:
spring: data: redis: database: host: port: password: ssl: timeout: connectTimeout: clientName: cluster: nodes: sentinel: master: nodes:
使用common Spring Boot up to 2.7.x settings:
spring: redis: database: host: port: password: ssl: timeout: connectTimeout: clientName: cluster: nodes: sentinel: master: nodes:
配置redision屬性(application.yaml):
spring: redis: redisson: config: | clusterServersConfig: idleConnectionTimeout: 10000 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 failedSlaveReconnectionInterval: 3000 failedSlaveCheckInterval: 60000 password: null subscriptionsPerConnection: 5 clientName: null loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {} subscriptionConnectionMinimumIdleSize: 1 subscriptionConnectionPoolSize: 50 slaveConnectionMinimumIdleSize: 24 slaveConnectionPoolSize: 64 masterConnectionMinimumIdleSize: 24 masterConnectionPoolSize: 64 readMode: "SLAVE" subscriptionMode: "SLAVE" nodeAddresses: - "redis://127.0.0.1:7004" - "redis://127.0.0.1:7001" - "redis://127.0.0.1:7000" scanInterval: 1000 pingConnectionInterval: 0 keepAlive: false tcpNoDelay: false threads: 16 nettyThreads: 32 codec: !<org.redisson.codec.Kryo5Codec> {} transportMode: "NIO"
三、使用 RedissonClient
除了常用的 StringRedisTemplate
外,我們還可以注入如下由 Redisson 提供的 Bean:
RedissonClient
RedissonRxClient
(響應(yīng)式)RedissonReactiveClient
(響應(yīng)式)RedisTemplate
ReactiveRedisTemplate
(響應(yīng)式)
四、接下來(lái),我們使用 RedissonClient 來(lái)實(shí)現(xiàn)一個(gè)分布式鎖,以進(jìn)行測(cè)試:
import org.junit.jupiter.api.Test; import org.redisson.api.RedissonClient; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.Lock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class Application { static final Logger logger = LoggerFactory.getLogger(DemoApplicationTests.class); // 注入 RedissonClient @Autowired RedissonClient redissonClient; // 計(jì)數(shù)器 private int count; @Test public void LockOp throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(1000); for (int i = 0; i < 1000; i++) { new Thread(() -> { // 每個(gè)線程都創(chuàng)建自己的鎖對(duì)象 // 這是基于 Redis 實(shí)現(xiàn)的分布式鎖 Lock lock = this.redissonClient.getLock("counterLock"); try { // 上鎖 lock.lock(); // 計(jì)數(shù)器自增 1 this.count = this.count + 1; } finally { // 釋放鎖 lock.unlock(); } countDownLatch.countDown(); }).start(); } countDownLatch.await(); logger.info("count = {}", this.count); }
如上。我們?cè)跍y(cè)試類中注入了 RedissonClient
Bean,并且定義了一個(gè) count
屬性。在測(cè)試方法中,啟動(dòng) 1000 個(gè)線程對(duì) count
屬性進(jìn)行 +1
操作。其中,每個(gè)線程都通過(guò) RedissonClient
獲取分布式鎖來(lái)控制對(duì)變量的并發(fā)修改。
運(yùn)行測(cè)試,輸出的日志如下:
INFO 4840 --- [ main] c.s.demo.test.DemoApplicationTests : count = 1000
最后的結(jié)果是 1000,分布式鎖生效。
五、 復(fù)雜多維對(duì)象結(jié)構(gòu)和對(duì)象引用的支持
Redisson突破了Redis數(shù)據(jù)結(jié)構(gòu)維度的限制,通過(guò)一個(gè)特殊引用對(duì)象的幫助,Redisson允許以任意的組合方式構(gòu)建多維度的復(fù)雜對(duì)象結(jié)構(gòu),實(shí)現(xiàn)了對(duì)象之間的類似傳統(tǒng)數(shù)據(jù)庫(kù)里的關(guān)聯(lián)關(guān)系。使用范例如下:
RMap<RSet<RList>, RList<RMap>> map = redisson.getMap("myMap"); RSet<RList> set = redisson.getSet("mySet"); RList<RMap> list = redisson.getList("myList"); map.put(set, list); // 在特殊引用對(duì)象的幫助下,我們甚至可以構(gòu)建一個(gè)循環(huán)引用,這是通過(guò)普通序列化方式實(shí)現(xiàn)不了的。 set.add(list); list.add(map);
可能您已經(jīng)注意到了,在map包含的元素發(fā)生改變以后,我們無(wú)需再次“保存/持久”這些對(duì)象。因?yàn)閙ap對(duì)象所記錄的并不是序列化以后的值,而是元素對(duì)象的引用。這讓Redisson提供的對(duì)象在使用方法上,與普通Java對(duì)象的使用方法一致。從而讓Redis成為內(nèi)存的一部分,而不僅僅是一個(gè)儲(chǔ)存空間。
以上范例中,一共創(chuàng)建了三個(gè)Redis數(shù)據(jù)結(jié)構(gòu):一個(gè)Redis HASH,一個(gè)Redis SET和一個(gè)Redis LIST。
六、 命令的批量執(zhí)行
多個(gè)連續(xù)命令可以通過(guò)RBatch對(duì)象在一次網(wǎng)絡(luò)會(huì)話請(qǐng)求里合并發(fā)送,這樣省去了產(chǎn)生多個(gè)請(qǐng)求消耗的時(shí)間和資源。這在Redis中叫做管道。
用戶可以通過(guò)以下方式調(diào)整通過(guò)管道方式發(fā)送命令的方式:
BatchOptions options = BatchOptions.defaults() // 指定執(zhí)行模式 // // ExecutionMode.REDIS_READ_ATOMIC - 所有命令緩存在Redis節(jié)點(diǎn)中,以原子性事務(wù)的方式執(zhí)行。 // // ExecutionMode.REDIS_WRITE_ATOMIC - 所有命令緩存在Redis節(jié)點(diǎn)中,以原子性事務(wù)的方式執(zhí)行。 // // ExecutionMode.IN_MEMORY - 所有命令緩存在Redisson本機(jī)內(nèi)存中統(tǒng)一發(fā)送,但逐一執(zhí)行(非事務(wù))。默認(rèn)模式。 // // ExecutionMode.IN_MEMORY_ATOMIC - 所有命令緩存在Redisson本機(jī)內(nèi)存中統(tǒng)一發(fā)送,并以原子性事務(wù)的方式執(zhí)行。 // .executionMode(ExecutionMode.IN_MEMORY) // 告知Redis不用返回結(jié)果(可以減少網(wǎng)絡(luò)用量) .skipResult() // 將寫(xiě)入操作同步到從節(jié)點(diǎn) // 同步到2個(gè)從節(jié)點(diǎn),等待時(shí)間為1秒鐘 .syncSlaves(2, 1, TimeUnit.SECONDS) // 處理結(jié)果超時(shí)為2秒鐘 .responseTimeout(2, TimeUnit.SECONDS) // 命令重試等待間隔時(shí)間為2秒鐘 .retryInterval(2, TimeUnit.SECONDS); // 命令重試次數(shù)。僅適用于未發(fā)送成功的命令 .retryAttempts(4);
使用方式如下:
RBatch batch = redisson.createBatch(); batch.getMap("test").fastPutAsync("1", "2"); batch.getMap("test").fastPutAsync("2", "3"); batch.getMap("test").putAsync("2", "5"); batch.getAtomicLongAsync("counter").incrementAndGetAsync(); batch.getAtomicLongAsync("counter").incrementAndGetAsync(); BatchResult res = batch.execute(); // 或者 Future<BatchResult> asyncRes = batch.executeAsync(); List<?> response = res.getResponses(); res.getSyncedSlaves();
在集群模式下,所有的命令會(huì)按各個(gè)槽所在的節(jié)點(diǎn),篩選分配到各個(gè)節(jié)點(diǎn)并同時(shí)發(fā)送。每個(gè)節(jié)點(diǎn)返回的結(jié)果將會(huì)匯總到最終的結(jié)果列表里。
七、Redisson事務(wù)
Redisson為RMap、RMapCache、RLocalCachedMap、RSet、RSetCache和RBucket這樣的對(duì)象提供了具有ACID屬性的事務(wù)功能。Redisson事務(wù)通過(guò)分布式鎖保證了連續(xù)寫(xiě)入的原子性,同時(shí)在內(nèi)部通過(guò)操作指令隊(duì)列實(shí)現(xiàn)了Redis原本沒(méi)有的提交與滾回功能。當(dāng)提交與滾回遇到問(wèn)題的時(shí)候,將通過(guò)org.redisson.transaction.TransactionException告知用戶。
目前支持的環(huán)境如下: SINGLE, MASTER/SLAVE, SENTINEL, ELASTICACHE REPLICATED, AZURE CACHE, RLEC。
Redisson事務(wù)支持的事務(wù)隔離等級(jí)為: READ_COMMITTED,即僅讀取提交后的結(jié)果。
另見(jiàn) Spring事務(wù)管理器 和本章 XA事務(wù)(XA Transactions)。
以下選項(xiàng)可以用來(lái)配置事務(wù)屬性:
TransactionOptions options = TransactionOptions.defaults() // 設(shè)置參與本次事務(wù)的主節(jié)點(diǎn)與其從節(jié)點(diǎn)同步的超時(shí)時(shí)間。 // 默認(rèn)值是5秒。 .syncSlavesTimeout(5, TimeUnit.SECONDS) // 處理結(jié)果超時(shí)。 // 默認(rèn)值是3秒。 .responseTimeout(3, TimeUnit.SECONDS) // 命令重試等待間隔時(shí)間。僅適用于未發(fā)送成功的命令。 // 默認(rèn)值是1.5秒。 .retryInterval(2, TimeUnit.SECONDS) // 命令重試次數(shù)。僅適用于未發(fā)送成功的命令。 // 默認(rèn)值是3次。 .retryAttempts(3) // 事務(wù)超時(shí)時(shí)間。如果規(guī)定時(shí)間內(nèi)沒(méi)有提交該事務(wù)則自動(dòng)滾回。 // 默認(rèn)值是5秒。 .timeout(5, TimeUnit.SECONDS);
代碼范例:
RTransaction transaction = redisson.createTransaction(TransactionOptions.defaults()); RMap<String, String> map = transaction.getMap("myMap"); map.put("1", "2"); String value = map.get("3"); RSet<String> set = transaction.getSet("mySet") set.add(value); try { transaction.commit(); } catch(TransactionException e) { transaction.rollback(); }
八、XA事務(wù)(XA Transactions)
Redisson提供了XAResource標(biāo)準(zhǔn)的實(shí)現(xiàn)。該實(shí)現(xiàn)可用于JTA事務(wù)中。
另見(jiàn)本章Redisson事務(wù)和Spring事務(wù)管理器。
該功能僅適用于Redisson PRO版本
代碼范例:
// Transaction對(duì)象可以從所有兼容JTA接口的事務(wù)管理器中獲取。 Transaction globalTransaction = transactionManager.getTransaction(); RXAResource xaResource = redisson.getXAResource(); globalTransaction.enlistResource(xaResource); RTransaction transaction = xaResource.getTransaction(); RBucket<String> bucket = transaction.getBucket("myBucket"); bucket.set("simple"); RMap<String, String> map = transaction.getMap("myMap"); map.put("myKey", "myValue"); transactionManager.commit();
到此這篇關(guān)于SpringBoot Redisson 集成的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot Redisson 集成內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot接收前端參數(shù)的四種方式圖文詳解
Spring Boot可以通過(guò)多種方式接收前端傳遞的數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于springboot接收前端參數(shù)的四種方式,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11SpringMVC框架使用jackson封裝數(shù)據(jù)過(guò)程中遇到的問(wèn)題及解決
這篇文章主要介紹了SpringMVC框架使用jackson封裝數(shù)據(jù)過(guò)程中遇到的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07Java使用easyExcel批量導(dǎo)入數(shù)據(jù)詳解
這篇文章主要介紹了Java使用easyExcel批量導(dǎo)入數(shù)據(jù)詳解,通常我們會(huì)提供一個(gè)模板,此模塊我們可以使用easyExcel導(dǎo)出數(shù)據(jù)生成的一個(gè)Excel文件當(dāng)作模板,提供下載鏈接,用戶在該文件內(nèi)填入規(guī)定的數(shù)據(jù)格式以后可以批量導(dǎo)入數(shù)據(jù)到數(shù)據(jù)庫(kù)中,需要的朋友可以參考下2023-08-08maven的升級(jí)版maven-mvnd的使用小結(jié)
maven-mvnd是Maven的升級(jí)版,通過(guò)將構(gòu)建過(guò)程放在守護(hù)進(jìn)程中,實(shí)現(xiàn)了更快的編譯速度和更低的內(nèi)存占用,下面就來(lái)介紹一下如何使用,感興趣的可以了解一下2025-01-01mybatis攔截器實(shí)現(xiàn)通用權(quán)限字段添加的方法
這篇文章主要給大家介紹了關(guān)于mybatis攔截器實(shí)現(xiàn)通用權(quán)限字段添加的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09SpringBoot接入deepseek深度求索示例代碼(jdk1.8)
這篇文章主要介紹了SpringBoot接入deepseek深度求索的相關(guān)資料,包括建API?key、封裝詢問(wèn)Deepseek的工具方法(在配置文件中添加key值)、調(diào)用測(cè)試并確保端口一致例如8091,最后運(yùn)行結(jié)果,需要的朋友可以參考下2025-02-02