- 《Spring Boot 整合Redisson配置篇》
- 《Spring Boot 整合Redisson操作Redis基礎篇》
- 《Redisson批量操作類RBuckets和管道利器RBatch》
摘要:使用Redisson的類RBuckets和RBatch批量操作Redis,減少網路請求次數。
綜述
Redis的部署方式有單節點部署、哨兵方式部署、叢集方式部署3種方式,這3中方式都使用的是原生的redis。本文基於單節點部署,使用的Spring Boot版本為2.5.x。
RBuckets批量操作
在Spring Boot專案中,通過RBuckets介面實現批量操作多個RBucket物件,官方示例如下:
RBuckets buckets = redisson.getBuckets();
Map<String, V> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");
Map<String, Object> map = new HashMap<>();
map.put("myBucket1", new MyObject());
map.put("myBucket2", new MyObject());
// 利用Redis的事務特性,同時儲存所有的通用物件桶,如果任意一個通用物件桶已經存在則放棄儲存其他所有資料。
buckets.trySet(map);
// 同時儲存全部通用物件桶。
buckets.set(map);
方法介紹:
Map<String,V> get(String... keys):返回桶的key-value對。 - boolean trySet(Map<String,?> buckets):利用Redis的事務特性,同時儲存所有的通用物件桶,如果任意一個通用物件桶已經存在則放棄儲存其他所有資料。
- void set(Map<String,?> buckets):同時儲存全部通用物件桶。
RBatch 批量操作
多個連續命令可以通過RBatch物件在一次網路會話請求裡合併傳送,這樣省去了產生多個請求消耗的時間和資源。這在Redis中叫做管道。
RBatch管道功能就是REDIS的批量傳送,實際上是客戶端的功能,與服務端無關。相當於把多個請求的命令放在一個資料包通過TCP傳送到服務端,然後客戶端再一次性讀取所有的命令回應。管道技術最顯著的優勢是提高了 redis 服務的效能。
/**
* 批量操作
*/
private void batchDemo() throws ExecutionException, InterruptedException {
Map<String, String> map = new HashMap<>();
map.put("abc", "testStr");
map.put("abcDemo", "redis");
redisUtils.setMassStrings(map);
log.info("String 測試資料:{}", redisUtils.getStr("abc") + " "
+ redisUtils.getStr("abcDemo"));
RBatch batch = redisUtils.createBatch();
// 模擬購物車場景,真實場景中請替換店鋪ID shopId 和商品ID commodityId
String field = "shopId:commodityId";
// 把即將執⾏的命令放進 RBatch
RMapAsync testMap = batch.getMap("customerId:"+ 32L);
// 更新value,並返回上一次的值
String commodityNum = "mapValue" + String.valueOf((int)(Math.random()*9 + 100));
log.info("當前商品數量commodityNum是:{}", commodityNum);
testMap.putAsync(field, commodityNum);
testMap.putAsync("test2", "mapValue3");
testMap.putAsync("test2", "mapValue5");
testMap.putAsync("test:"+ String.valueOf((int)(Math.random()*900 + 100)), String.valueOf((int)(Math.random()*900 + 100)));
RAtomicLongAsync counter = batch.getAtomicLong("counter");
RFuture<Long> num = counter.incrementAndGetAsync();
// 執行RBatch中的全部命令,並返回執行結果
BatchResult result = batch.execute();
List list = result.getResponses();
log.info("Map Batch 執行結果:{}", list);
log.info("計數器當前值:{}", num.get());
}
執行batchDemo()後,控制檯列印結果如下:
StudyRedissonController - String 測試資料:testStr redis
StudyRedissonController - 當前商品數量commodityNum是:mapValue106
StudyRedissonController - Map Batch 執行結果:[mapValue101, mapValue5, mapValue3, null, 8]
StudyRedissonController - 計數器當前值:8
測試用例主要介紹了Hash,順便介紹一下它的使用場景:
- 儲存結構化的資料,比如 Java 中的物件。其實 Java 中的物件也可以用 string 進行儲存,只需要將物件序列化成 json 字串就可以,但是如果這個物件的某個屬性更新比較頻繁的話,那麼每次就需要重新將整個物件序列化儲存,這樣消耗開銷比較大。可如果用 hash 來儲存物件的每個屬性,那麼每次只需要更新要更新的屬性就可以。
- 購物車場景。以業務線+使用者id作為key,以店鋪編號+商品的id作為儲存的field,以選購商品數量作為鍵值對的value,這樣就構成了購物車的三個要素。
在叢集模式下,所有的命令會按各個槽所在的節點,篩選分配到各個節點並同時傳送。每個節點返回的結果將會彙總到最終的結果列表裡。上述demo中用到的工具類如下:
@Component
public class RedisUtils {
private RedisUtils() {
}
/**
* 預設快取時間
*/
private static final Long DEFAULT_EXPIRED = 32000L;
/**
* 自動裝配redisson client物件
*/
@Resource
private RedissonClient redissonClient;
/**
* 獲取getBuckets 物件
*
* @return RBuckets 物件
*/
public RBuckets getBuckets() {
return redissonClient.getBuckets();
}
/**
* 讀取快取中的字串,永久有效
*
* @param key 快取key
* @return 字串
*/
public String getStr(String key) {
RBucket<String> bucket = redissonClient.getBucket(key);
return bucket.get();
}
// ---------------- 批量操作 ------------------------
/**
* 獲取RBatch
*
* @return RBatch
*/
public RBatch createBatch() {
return redissonClient.createBatch();
}
/**
* 批量移除快取
*
* @param keys key 物件
*/
public void deleteBatch(String... keys) {
if (null == keys) {
return;
}
this.getKeys().delete(keys);
}
/**
* 批量快取字串,缺點:不可以設定過期時間
*
* @param map 快取key-value
*/
public void setMassStrings(Map<String, String> map) {
if (MapUtils.isEmpty(map)) {
return;
}
RBuckets buckets = redissonClient.getBuckets();
// 同時儲存全部通用物件桶。
buckets.set(map);
}
/**
* 批量快取字串,支援過期
*
* @param map 快取key-value
* @param leaseTime 快取有效期,必傳
*/
public void setMassStrings(Map<String, String> map, long leaseTime) {
if (MapUtils.isEmpty(map)) {
return;
}
final long expireTime = leaseTime <= 0L ? DEFAULT_EXPIRED : leaseTime;
RBatch batch = redissonClient.createBatch();
map.forEach(new BiConsumer<String, String>() {
public void accept(String key, String value) {
batch.getBucket(key).setAsync(value, expireTime, TimeUnit.SECONDS);
}
});
batch.execute();
}
}
結束語
關於redisson中如何使用批量操作類RBuckets和管道利器RBatch就分享到這裡,希望本文對大家的學習或者工作具有一定的參考和學習價值;如果有疑問,大家可以在評論區留言交流,也希望大家多多點贊關注。謝謝大家對樓蘭胡楊的支援!