maven依赖

			<dependency>
				<groupId>org.redisson</groupId>
				<artifactId>redisson</artifactId>
				<version>3.9.1</version>
			</dependency>

基本配置

/**
 * @author ZhuRuiLin
 * @description TODO
 * @date 2022/9/25 16:40
 **/
@Configuration
@Slf4j
public class GetConfigFromYaml {

    @Bean
    public RedissonClient config() {
        try {
            Config config = Config.fromYAML(GetConfigFromYaml.class.getClassLoader().getResource("redisson-config.yaml"));
            return Redisson.create(config);
        } catch (IOException e) {
            log.error("从application.yaml获取Redisson配置出错");
        }
        return null;
    }

}

放在resource文件夹下的redisson-config.yaml文件:

---
singleServerConfig:
  idleConnectionTimeout: 10000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500
  password: xxxx
  subscriptionsPerConnection: 5
  clientName: springcloud-learn
  address: "redis://xxxx:6379"
  subscriptionConnectionMinimumIdleSize: 1
  subscriptionConnectionPoolSize: 50
  connectionMinimumIdleSize: 32
  connectionPoolSize: 64
  database: 0
  dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> { }
"transportMode": "NIO"

代码demo

RedissonClient.getKeys()方法可以得到当前指定的database的所有key,不指定database默认为db0,并不会跨库查询:

    /**
     * 得到某个database下的所有key
     *
     * @return
     */
    public RKeys getAllKeys() {
        return client.getKeys();
    }

getKeysByPattern(String pattern)方法可以模糊查询多个key

   public Iterable<String> getKeysByPattern() {
        return getAllKeys().getKeysByPattern("string*");// 也会查询到key=string
    }

删除多个key的方法:

    public long deleteByPattern() {
        long rows0 = getAllKeys().deleteByPattern("two*");
        long rows1 = getAllKeys().deleteByPattern("three?");// 这个pattern我本地没有删除成功,但是在git的wiki上是这么写的
        long rows2 = getAllKeys().delete("string0", "string1");
        log.info("rows0={}", rows0);
        log.info("rows1={}", rows1);
        log.info("rows2={}", rows2);
        return rows2;
    }

Redisson的分布式RBucketJava对象是一种通用对象桶可以用来存放任类型的对象

    public void setValue() {
        RBucket<String> strBucket = client.getBucket("strBucket");
        strBucket.set("这是一个字符串");
        strBucket.set("更新一个字符串", 5, TimeUnit.SECONDS);
        strBucket.set("再次更新一个字符串");

        List<String> strList = new ArrayList<>();
        strList.add("周一");
        strList.add("周二");
        strList.add("周三");
        RList<String> listBucket = client.getList("listBucket");
        boolean saveListResult = listBucket.addAll(strList);
        log.info("listBucket存储成功={}", saveListResult);
        if (saveListResult) {
            RList<Object> dataList = client.getList("listBucket");
            List<String> newList = dataList.stream().map(data -> (String) data).collect(Collectors.toList());
            newList.stream().forEach(System.out::println);
        }

        Map<String, String> map = new HashMap<>();
        map.put("monday", "周一");
        map.put("friday", "周五");
        RMap<String, String> mapBucket = client.getMap("mapBucket");
        mapBucket.putAll(map);
        Map<String, String> dataMap = new HashMap<>(client.getMap("mapBucket"));
        for (Map.Entry<String, String> entry : dataMap.entrySet()) {
            log.info("key={},value={}", entry.getKey(), entry.getValue());
        }
    }

还可以通过RBuckets接口实现批量操作多个RBucket对象:

        RBuckets buckets = client.getBuckets();
        Map<String, String> map = buckets.get("string1", "string2");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            entry.setValue(entry.getValue() + "再次更新");
        }
        buckets.set(map);

Redisson的分布式话题:

        RTopic topic = client.getTopic("testTopic0926");
        topic.addListener(TestTopicBean.class, new MessageListener() {
            @Override
            public void onMessage(CharSequence charSequence, Object o) {
                log.info("charSequence={},o={}", charSequence.toString(), o.toString());
            }
        });
        TimeUnit.SECONDS.sleep(5);
        RTopic setTopic = client.getTopic("testTopic0926");
        TestTopicBean ttb = new TestTopicBean();
        ttb.setName("测试");
        long result = setTopic.publish(ttb);
        log.info("public方法的返回值是={}", result);

判断是否存在和设置过期时间

        RBucket<String> week = client.getBucket("week");
//        判断是否存在
        if (week.isExists()) {
            log.info("week对应的key已经存在");
        } else {
            log.info("week对应的key不存在");
        }
//      设置时间自动过期
        week.set("临时存储", 10, TimeUnit.SECONDS);
        TimeUnit.SECONDS.sleep(5);
        RBucket<String> after5 = client.getBucket("week");
        log.info("after5={}", after5);
        TimeUnit.SECONDS.sleep(7);
        RBucket<String> after12 = client.getBucket("week");
        if (after12.isExists()) {
            log.info("after12对应的key仍然存在");
        } else {
            log.info("after12对应的key不存在");
        }

基于Redis的Redisson分布式整长型累加器(LongAdder)采用了与java.util.concurrent.atomic.LongAdder类似的接口。通过利用客户端内置的LongAdder对象,为分布式环境下递增和递减操作提供了很高得性能。据统计其性能最高比分布式AtomicLong对象快 12000 倍。完美适用于分布式统计计量场景。

//        sum()方法就是返回当前值
        log.info("初始化的值是{}", rla.sum());
        rla.add(10);
        log.info("add(10)之后的值{}", rla.sum());
        rla.reset();
        log.info("调用reset()方法之后的值是{}", rla.sum());// 调用reset()方法之后的值是0
        rla.increment();
        rla.increment();
        rla.decrement();
        log.info("自增两次,减少一次之后的值是{}", rla.sum());
        rla.reset();
        rla.add(10);
        log.info("sum()方法的返回值是{}", rla.sum());
        rla.sumAsync(1, TimeUnit.SECONDS);
        TimeUnit.SECONDS.sleep(2);
        log.info("调用sum(long,TimeUnit)之后的值是{}", rla.sum()); //调用sum(long,TimeUnit)之后的值是10
        rla.reset();
        rla.add(100);
        rla.delete();
        log.info("调用delete()方法之后的值{}", rla.sum()); //调用delete()方法之后的值100
//        当不再使用整长型累加器对象的时候应该自行手动销毁,如果Redisson对象被关闭(shutdown)了,则不用手动销毁。
        rla.destroy();
        log.info("调用destroy之后的值是{}", rla == null ? "null" : rla.sum()); // 调用destroy之后的值是0

如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

// 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);

// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       lock.unlock();
   }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐