官方描述:Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。
它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。
Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redisson底层采用的是Netty 框架。支持Redis 2.8以上版本,支持Java1.6+以上版本。
Redisson程序化的配置方法是通过构建Config对象实例来实现的,具体配置可参加API。下列基础的连接配置:
// 默认连接地址 127.0.0.1:6379 无密码
RedissonClient redisson = Redisson.create();
// 指定
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
RedissonClient redisson = Redisson.create(config);
Config config = new Config();
config.useClusterServers()
.setScanInterval(2000) // 集群状态扫描间隔时间,单位是毫秒
//可以用"rediss://"来启用SSL连接
.addNodeAddress("redis://127.0.0.1:7000", "redis://127.0.0.1:7001")
.addNodeAddress("redis://127.0.0.1:7002");
RedissonClient redisson = Redisson.create(config);
Config config = new Config();
config.useSentinelServers()
.setMasterName("mymaster")
//可以用"rediss://"来启用SSL连接
.addSentinelAddress("127.0.0.1:26389", "127.0.0.1:26379")
.addSentinelAddress("127.0.0.1:26319");
RedissonClient redisson = Redisson.create(config);
Config config = new Config();
config.useMasterSlaveServers()
//可以用"rediss://"来启用SSL连接
.setMasterAddress("redis://127.0.0.1:6379")
.addSlaveAddress("redis://127.0.0.1:6389", "redis://127.0.0.1:6332", "redis://127.0.0.1:6419")
.addSlaveAddress("redis://127.0.0.1:6399");
RedissonClient redisson = Redisson.create(config);
//BigeSet示例
RBitSet set = redisson.getBitSet("simpleBitset");
set.set(0, true);
set.set(1812, false);
set.clear(0);
set.addAsync("e");
set.xor("anotherBitset");
// 步隆过滤器示例
RBloomFilter<SomeObject> bloomFilter = redisson.getBloomFilter("sample");
// 初始化布隆过滤器,预计统计元素数量为55000000,期望误差率为0.03
bloomFilter.tryInit(55000000L, 0.03);
bloomFilter.add(new SomeObject("field1Value", "field2Value"));
bloomFilter.add(new SomeObject("field5Value", "field8Value"));
bloomFilter.contains(new SomeObject("field1Value", "field8Value"));
基于Redis的Redisson分布式可重入锁RLock,实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
RLock对象完全符合Java的Lock规范。也就是说只有拥有锁的进程才能解锁,其他进程解锁则会抛出IllegalMonitorStateException错误。
// 防止IllegalMonitorStateException异常
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。
用于加锁不同ID集合时,只要执行集合与当前加锁集合有交集,就会阻塞等待。
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 所有的锁都上锁成功才算成功。
lock.lock();
...
lock.unlock();
写锁是一个排他锁(互斥锁,独享锁);读锁是 一个共享锁。
基于Redisson的Redisson分布式闭锁(CountDownLatch)Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.14.1</version>
</dependency>
MyRedissonConfig给容器配置一个RedissonClient实例即可,所有对redisson的使用都是通过RedissonClient对象。
@Configuration
public class MyRedissonConfig {
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() throws IOException {
//1、创建配置
Config config = new Config();
//Redis url should start with redis:// or rediss:// (for SSL connection)
//可以用"rediss://"来启用SSL连接
config.useSingleServer()
.setAddress("redis://localhost:6379")
.setPassword("123456")
.setDatabase(0);
//2、根据Config创建出RedissonClient实例
return Redisson.create(config);
}
}
@ResponseBody
@GetMapping("/hello")
public String hello() {
//1、获取一把锁,只要锁的名字一样,就是同一把锁
RLock lock = redisson.getLock("redisson:my‐lock");
//2、加锁
// lock.lock();
//阻塞式等待。默认加锁30s时间
//1)、锁的自动续期,如果业务超长,运行期间自动给锁续上新的30s。不用担心业务时间长,锁自动过期删掉
//2)、加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30s 以后自动删除
lock.lock(10, TimeUnit.SECONDS);
//10s钟自动解锁,自动解锁时间一定要大于业务执行时间
//问题:lock.lock(10, TimeUnit.SECONDS); 在锁时间到了以后,不会自动续期
//1、如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就 我们指定的时间
//2、如果我们未指定超时间件,就使用 30 * 1000【LockWatchdogTimeout看门狗的 默认时间】
// 只要占锁成功,就会启动一个定时任务。【重新给锁设置过期时间,新的过期时间就 是看门狗的默认时间】,每隔10s都会自动再次续期,续成满时间
// internalLockLeaseTime / 3 【看门狗时间 / 3,10s】 26
//最佳实战
//1)、lock.lock(10, TimeUnit.SECONDS); 省掉了整个续期操作。手动解锁
try {
System.out.println("加锁成功,执行业务..." + Thread.currentThread().getId());
Thread.sleep(60000);
} catch (Exception e) {
e.printStackTrace();
} finally {
//3、解锁 假设解锁代码没有运行,redisson会不会出现问题
System.out.println("释放锁..." + Thread.currentThread().getId());
lock.unlock();
// if (lock.isLocked() && lock.isHeldByCurrentThread()) {
// lock.unlock();
// }
}
return "hello";
}
@ResponseBody
@GetMapping("/read")
public String readValue() {
RReadWriteLock lock = redisson.getReadWriteLock("rw‐lock");
String s = "";
//加读锁
RLock rLock = lock.readLock();
rLock.lock();
System.out.println("读锁加锁成功..." + Thread.currentThread().getId());
try {
Thread.sleep(30000);
s = redisson.getBucket("writeValue").toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("读锁释放..." + Thread.currentThread().getId());
}
return s;
}
//保证一定能读到最新数据,修改期间,写锁是一个排他锁(互斥锁,独享锁)。读锁是 一个共享锁
//写锁没释放,读就必须等待
//读 + 读,相当于无锁,并发读,只会在redis中记录好,所有当前的读锁,他们都会时加锁成功
//写 + 读,等待写锁释放
//写 + 写,阻塞方式是同
//读 + 写,有读锁,写也需要等待
//只要有写的存在,都必须等待
@ResponseBody
@GetMapping("/write")
public String writeValue() {
RReadWriteLock lock = redisson.getReadWriteLock("rw‐lock");
String s = "";
RLock rLock = lock.writeLock();
//1、改数据加写锁,读数据加读锁
rLock.lock();
System.out.println("写锁加锁成功..." + Thread.currentThread().getId());
try {
s = UUID.randomUUID().toString();
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("写锁释放..." + Thread.currentThread().getId());
}
return s;
}
其中Jedis是用的最普遍的,Spring的RedisTemplate用的就是Jedis,适用很多单体应用或者伪分布式应用等;而Redisson更多应用于分布式场景,更强大,更可靠,作为分布式锁的选择,和zookeeper有着一样的地位。
一、什么是分布式锁我们的一些互斥资源,不能并行执行,需要一个东西来保证串行执行synchronized、lock都是单机锁但是这些锁都是在单台机器下生效,如果部署多台机器,或者互斥资源在不同的服务之间进行操作,那么就锁不住。分布式锁一定是独立于业务服务的。Redis本来就是一个单独的服务,所以,肯定是独立于我们业务服务的,本身就属于分布式的二、自己设计一个锁,如何实现实现分布式锁需要满足的需求:1、只能有一个线程能执行互斥的资源2、其他的线程想要执行互斥资源的时候,有线程正在执行的话,要么等待,要么报错那么为了实现这个需求我们需要做什么?1、通过一个标记来标记是不是有线程在执行,其他线程想要执
原文网址:SpringBoot--配置Redisson的方法_IT利刃出鞘的博客-CSDN博客简介说明 本文介绍如何在SpringBoot中配置Redisson。官网网址redisson-spring-boot-starter配置方案:redisson/redisson-spring-boot-starteratmaster·redisson/redisson·GitHubspring-boot-starter-data-redis配置方案:SpringBootReferenceDocumentation配置详解:2.配置方法·redisson/redissonWiki·GitHub备注
Redisson之lock()和tryLock()的区别和原理解析在Redisson中lock()方法与tryLock()方法是有区别的!我们先来阐述两者的区别,再分析它们的源码。lock()与tryLock()的区别(1)返回值:lock()是没有返回值的;tryLock()的返回值是boolean。(2)时机:lock()一直等锁释放;tryLock()获取到锁返回true,获取不到锁并直接返回false。(3)tryLock()是可以被打断的,被中断的;lock是不可以。tryLock()@OverridepublicbooleantryLock(longwaitTime,longlea
我确实有一张table,Foo。我在某些事件中向该表添加行。当前的整体设计使得无法避免重复消息。这会导致向表中添加重复行。我不能对表设置唯一约束,因为有不同类型的消息成为该表中的行。我只想避免重复特定类型的消息。由于重复的消息经常同时出现,而且该应用程序运行在多个节点上,所以我决定使用radisson来获取分布式锁。但是它似乎没有用。我仍然在表格中得到重复的行。根据用户ID、日期和类型检测重复消息。下面是简约的演示代码。我正在尝试在写入之前进行读取,并且此读取发生在跨应用程序节点的同步块(synchronizedblock)中。感谢对此的任何投入。if(updateEntry.getT
当我尝试使用Redisson连接Redis服务器时,有时会显示内存泄漏错误。我该如何解决。重现代码如下。预期行为它不应该有内存泄漏。实际行为[main]ERRORio.netty.util.ResourceLeakDetector-LEAK:HashedWheelTimer.release()wasnotcalledbeforeit'sgarbage-collected.Seehttp://netty.io/wiki/reference-counted-objects.htmlformoreinformation.Recentaccessrecords:Createdat:io.net
redissonClient.getNodesGroup().pingAll()返回true但仍然得到异常->[10-09-201821:00:05.337][redisson-netty-2-6][ERROR]DNSMonitor$1$1:98cr_id=parent_reqid=reqid=Unabletoresolvexxxx.redis.cache.windows.netjava.net.UnknownHostException:failedtoresolve'xxxx.redis.cache.windows.net'after4queries 最佳
我在spring中使用Redission进行锁定,它具有3.5.3的maven依赖版本和4.1.22.final的netty-all依赖版本。但是我的JavaVisualVM显示redission-netty线程始终处于运行阶段。谁能告诉我这背后的原因。 最佳答案 在应用关闭过程中是否调用了Redisson.shutdown方法? 关于java-Redisson-netty线程没有关闭,我们在StackOverflow上找到一个类似的问题: https://s
我正在将Redisson与Spring-boot一起使用,我需要将环境变量传递给redisson.yaml地址:“redis://${REDIS_HOST}:6379”传递环境变量时目前无法正常工作。---singleServerConfig:idleConnectionTimeout:10000pingTimeout:1000connectTimeout:10000timeout:3000retryAttempts:3retryInterval:1500password:nullsubscriptionsPerConnection:5clientName:nulladdress:"r
我有一个场景,我需要使用的数据结构是Map>.我想使用Redis将此数据存储为内存缓存。我感兴趣的一件事是,使子map的“key”(在本例中为Map>)在5分钟后过期。我在Redis中尝试过类似的东西(Redisson实现),RMap>parentMap=redisson.getMap("parentMap");RMapCache>childCache=redisson.getMapCache("childMapCache");childCache.put("test",newArrayList(),5,TimeUnit.Minutes);//Placingthechildcachei
尝试使用Redisson连接到Redis(在Docker上)...简单的东西..Configconfig=newConfig();config.useSingleServer().setAddress("redis://192.168.99.100:6379");RedissonClientredisson=Redisson.create(config);//第3行但我收到此错误(在第3行)-我是否遗漏了什么?Exceptioninthread"main"java.lang.IllegalArgumentException:hostnamecan'tbenullatjava.net.I