Spring Boot 整合Redisson操作Redis基礎篇
摘要:介紹Redisson中分布式對象和集合的基礎操作,包括對象桶、集合、列表和散列。
綜述
??測試環境為:Spring Boot版本 2.5.x 和 Redisson 單機。關于如何中Spring Boot項目集成Redisson,請戳《Spring Boot 整合Redisson配置篇》。
??RedissonClient是線程安全的,由于其內部是通過Netty通信,所以除了同步執行方式,也支持異步執行。
Redisson 工具類
??首先提供一個Redisson 工具類,方便下文用于演示。
import org.redisson.api.*;
import org.redisson.client.codec.StringCodec;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
@Component
public class RedisUtils {
private RedisUtils() {
}
/**
* 默認緩存時間
*/
private static final Long DEFAULT_EXPIRED = 32000L;
/**
* 自動裝配redisson client對象
*/
@Resource
private RedissonClient redissonClient;
/**
* 用于操作key
* @return RKeys 對象
*/
public RKeys getKeys() {
return redissonClient.getKeys();
}
/**
* 移除緩存
*
* @param key
*/
public void delete(String key) {
redissonClient.getBucket(key).delete();
}
/**
* 獲取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();
}
/**
* 緩存字符串
*
* @param key
* @param value
*/
public void setStr(String key, String value) {
RBucket<String> bucket = redissonClient.getBucket(key);
bucket.set(value);
}
/**
* 緩存帶過期時間的字符串
*
* @param key 緩存key
* @param value 緩存值
* @param expired 緩存過期時間,long類型,必須傳值
*/
public void setStr(String key, String value, long expired) {
RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE);
bucket.set(value, expired <= 0L ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
}
/**
* string 操作,如果不存在則寫入緩存(string方式,不帶有redisson的格式信息)
*
* @param key 緩存key
* @param value 緩存值
* @param expired 緩存過期時間
*/
public Boolean setIfAbsent(String key, String value, long expired) {
RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE);
return bucket.trySet(value, expired <= 0L ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
}
/**
* 如果不存在則寫入緩存(string方式,不帶有redisson的格式信息),永久保存
*
* @param key 緩存key
* @param value 緩存值
*/
public Boolean setIfAbsent(String key, String value) {
RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE);
return bucket.trySet(value);
}
/**
* 判斷緩存是否存在
*
* @param key
* @return true 存在
*/
public Boolean isExists(String key) {
return redissonClient.getBucket(key).isExists();
}
/**
* 獲取RList對象
*
* @param key RList的key
* @return RList對象
*/
public <T> RList<T> getList(String key) {
return redissonClient.getList(key);
}
/**
* 獲取RMapCache對象
*
* @param key
* @return RMapCache對象
*/
public <K, V> RMapCache<K, V> getMap(String key) {
return redissonClient.getMapCache(key);
}
/**
* 獲取RSET對象
*
* @param key
* @return RSET對象
*/
public <T> RSet<T> getSet(String key) {
return redissonClient.getSet(key);
}
/**
* 獲取RScoredSortedSet對象
*
* @param key
* @param <T>
* @return RScoredSortedSet對象
*/
public <T> RScoredSortedSet<T> getScoredSortedSet(String key) {
return redissonClient.getScoredSortedSet(key);
}
}
常用RKeys的API操作
??每個Redisson對象實例都會有一個與之對應的Redis數據實例,可以通過調用getName方法來取得Redis數據實例的名稱(key)。所有與Redis key相關的操作都歸納在RKeys這個接口里:
RKeys keys = client.getKeys();
//獲取所有key值
Iterable<String> allKeys = keys.getKeys();
//模糊查詢所有包含關鍵字key的值
Iterable<String> foundedKeys = keys.getKeysByPattern("key");
//刪除多個key值
long numOfDeletedKeys = keys.delete("obj1", "obj2", "obj3");
//模糊刪除key值
long deletedKeysAmount = keys.deleteByPattern("test?");
//隨機獲取key
String randomKey = keys.randomKey();
//查詢當前有多少個key
long keysAmount = keys.count();
??具體demo如下:
private void getKeys() {
RKeys keys = redisUtils.getRedisKeys();
Iterable<String> allKeys = keys.getKeys();
StringBuilder sb = new StringBuilder();
for (String key : allKeys) {
sb = sb.append(key).append(",");
}
log.info("所有的key:{}", sb.substring(0, sb.length() - 1));
// 模糊查詢以 map 打頭的所有 key
allKeys = keys.getKeysByPattern("map*");
sb = new StringBuilder();
for (String key : allKeys) {
sb = sb.append(key).append(",");
}
log.info("模糊匹配到的key:{}", sb.substring(0, sb.length() - 1));
}
??其中,getKeysByPattern是基于redis 的 scan 命令實現的,匹配規則示例如下:
- h?llo subscribes to hello, hallo and hxllo
- h*llo subscribes to hllo and heeeello
- h[ae]llo subscribes to hello and hallo, but not hillo
通用對象桶(Object Bucket)
??Redisson的分布式RBucket Java對象是一種通用對象桶,可以用來存放任意類型的對象。除了同步接口外,還提供了異步(Async)、反射式(Reactive)和RxJava2標準的接口。還可以通過RBuckets接口實現批量操作多個RBucket對象:
/**
* String 數據類型
*/
private void strDemo() {
redisUtils.setStr(DEMO_STR, "Hello, String.");
log.info("String 測試數據:{}", redisUtils.getStr(DEMO_STR));
redisUtils.setStr("myBucket", "myBucketIsXxx");
RBuckets buckets = redisUtils.getBuckets();
Map<String, String> foundBuckets = buckets.get("myBucket*");
Map<String, Object> map = new HashMap<>();
map.put("myBucket1", "value1");
map.put("myBucket2", 30L);
// 同時保存全部通用對象桶。
buckets.set(map);
Map<String, String> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");
log.info("跨桶String 測試數據:{}", loadedBuckets);
map.put("myBucket3", 320L);
}
散列(Hash)
??基于Redisson的分布式映射結構的RMap Java對象實現了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。與HashMap不同的是,RMap保持了元素的插入順序。該對象的最大容量受Redis限制,最大元素數量是4 294 967 295個。
/**
* Hash類型
*/
private void hashDemo() {
RMap<Object, Object> map = redisUtils.getMap("mapDemo");
map.put("demoId1", "123");
map.put("demoId100", "13000");
Object demoId1Obj = map.get("demoId1");
log.info("Hash 測試數據:{}", demoId1Obj);
}
集合(Set)
??基于Redisson的分布式Set結構的RSet Java對象實現了java.util.Set接口。通過元素的相互狀態比較保證了每個元素的唯一性。該對象的最大容量受Redis限制,最大元素數量是4 294 967 295個。
/**
* Set 測試
*/
private void setDemo() {
RSet<String> set = redisUtils.getSet("setKey");
set.add("value777");
log.info("Set 測試數據");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
log.info(next);
}
}
列表(List)
??基于Redisson分布式列表(List)結構的RList Java對象在實現了java.util.List接口的同時,確保了元素插入時的順序。該對象的最大容量受Redis限制,最大元素數量是4 294 967 295個。
/**
* List數據類型
*/
private void listDemo() {
RList<String> list = redisUtils.getList("listDemo");
list.add("listValue1");
list.add("listValue2");
log.info("List 測試數據:{}", list.get(1));
}
綜合示例
??將上述各個demo放入一個API中,以便快速測試:
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping(value = "/redisson", method = RequestMethod.POST)
public class StudyRedissonController {
@Resource
private RedisUtils redisUtils;
private static String DEMO_STR = "demoStr";
@PostMapping("/learnRedisson")
public void learnRedisson() {
//三種數據結構使用示例
strDemo();
hashDemo();
listDemo();
setDemo();
getKeys();
}
private void getKeys() {
RKeys keys = redisUtils.getKeys();
Iterable<String> allKeys = keys.getKeys();
StringBuilder sb = new StringBuilder();
for (String key : allKeys) {
sb = sb.append(key).append(",");
}
log.info("所有的key:{}", sb.substring(0, sb.length() - 1));
// 模糊查詢以 map 打頭的所有 key
allKeys = keys.getKeysByPattern("map*");
sb = new StringBuilder();
for (String key : allKeys) {
sb = sb.append(key).append(",");
}
log.info("模糊匹配到的key:{}", sb.substring(0, sb.length() - 1));
}
/**
* Hash類型
*/
private void hashDemo() {
RMap<Object, Object> map = redisUtils.getMap("mapDemo");
map.put("demoId1", "123");
map.put("demoId100", "13000");
Object demoId1Obj = map.get("demoId1");
log.info("Hash 測試數據:{}", demoId1Obj);
}
/**
* String 數據類型
*/
private void strDemo() {
redisUtils.setStr(DEMO_STR, "Hello, String.");
log.info("String 測試數據:{}", redisUtils.getStr(DEMO_STR));
redisUtils.setStr("myBucket", "myBucketIsXxx");
RBuckets buckets = redisUtils.getBuckets();
Map<String, String> foundBuckets = buckets.get("myBucket*");
Map<String, Object> map = new HashMap<>();
map.put("myBucket1", "value1");
map.put("myBucket2", 30L);
// 同時保存全部通用對象桶。
buckets.set(map);
Map<String, String> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");
log.info("跨桶String 測試數據:{}", loadedBuckets);
map.put("myBucket3", 320L);
}
/**
* List數據類型
*/
private void listDemo() {
RList<String> list = redisUtils.getList("listDemo");
list.add("listValue1");
list.add("listValue2");
log.info("List 測試數據:{}", list.get(1));
}
/**
* Set 測試
*/
private void setDemo() {
RSet<String> set = redisUtils.getSet("setKey");
set.add("value777");
log.info("Set 測試數據");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
log.info(next);
}
}
}
??啟動服務,調用如上API,則控制臺打印的執行結果如下:
結束語
??本文中,Wiener介紹了基于Redisson的redis基礎操作,包括對象桶、集合、列表和哈希表。大家對于這件事都是怎么看的呢?歡迎在文章下方留言討論,三人行必有我師焉!小編會仔仔細細地看每條留言。
Reference
Buy me a coffee. ?Get red packets.
浙公網安備 33010602011771號