• Spring Boot 整合Redisson配置篇
  • Spring Boot 整合Redisson操作Redis基础篇
  • Redisson批量操作类RBuckets和管道利器RBatch
  • 摘要 :介绍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

  • https://wenku.baidu.com/view/7999dc79322b3169a45177232f60ddccda38e627.html
  • https://www.bookstack.cn/read/redisson-wiki-zh/spilt.4.2.-配置方法.md
  •