redisson 实战
1,[Redis的三个框架:Jedis,Redisson,Lettuce
概念:
Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持,
Redisson:实现了分布式和可扩展的Java数据结构。
Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。
优点:
Jedis:比较全面的提供了Redis的操作特性
Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列
Lettuce:主要在一些分布式缓存框架上使用比较多
可伸缩:
Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。
Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作
Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作
结论:
建议使用:Jedis + Redisson
2,redisson 在spring boot 中配置
1,pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.12.1</version>
</dependency>
2, config
1,redisson-single.yaml
clusterServersConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: null
subscriptionsPerConnection: 5
clientName: null
loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
slaveSubscriptionConnectionMinimumIdleSize: 1
slaveSubscriptionConnectionPoolSize: 50
slaveConnectionMinimumIdleSize: 32
slaveConnectionPoolSize: 64
masterConnectionMinimumIdleSize: 32
masterConnectionPoolSize: 64
readMode: "SLAVE"
nodeAddresses:
- "redis://127.0.0.1:7001"
- "redis://127.0.0.1:7002"
- "redis://127.0.0.1:7003"
scanInterval: 1000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
"transportMode":"NIO"
2,redisson-cluster.yaml
clusterServersConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: null
subscriptionsPerConnection: 5
clientName: null
loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
slaveSubscriptionConnectionMinimumIdleSize: 1
slaveSubscriptionConnectionPoolSize: 50
slaveConnectionMinimumIdleSize: 32
slaveConnectionPoolSize: 64
masterConnectionMinimumIdleSize: 32
masterConnectionPoolSize: 64
readMode: "SLAVE"
nodeAddresses:
- "redis://127.0.0.1:7001"
- "redis://127.0.0.1:7002"
- "redis://127.0.0.1:7003"
scanInterval: 1000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
"transportMode":"NIO"
3,application.yml
spring:
redis:
redisson:
config: classpath:config/redisson-single.yaml
4,Redis Lock 测试接口
package mydlq.club.lock.controller;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Redis Lock 测试接口
*/
@Slf4j
@RestController
public class LockController {
/** Redisson 对象 */
@Autowired
private RedissonClient redissonClient;
/** 线程池 */
ExecutorService executor = Executors.newFixedThreadPool(10);
@GetMapping("/lock")
public void lockTest() {
for (int i = 0; i < 1000; i++) {
executor.submit(() -> {
// 获取锁对象(可以为"可重入锁"、"公平锁",如果redis是集群模式,还可以使用"红锁")
//RLock lock = redissonClient.getFairLock("test"); //公平锁
RLock lock = redissonClient.getLock("test"); //可重入锁
try {
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
// 如果获取锁成功,则执行对应逻辑
if (res) {
log.info("获取分布式锁,执行对应逻辑1");
log.info("获取分布式锁,执行对应逻辑2");
log.info("获取分布式锁,执行对应逻辑3");
}
} catch (InterruptedException e) {
log.error("", e);
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
});
}
}
}
3,redisson 使用
1,使用 RAtomicLong 实现 Redis 原子操作
package redissonCase;
import org.redisson.Redisson;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
/**
* 使用 RAtomicLong 实现 Redis 原子操作
* RAtomicLong 是 Java 中 AtomicLong 类的分布式“替代品”,
* 用于在并发环境中保存长值。
* 以下示例代码演示了 RAtomicLong 的用法:
*/
public class AtomicLongExamples {
public static void main(String[] args) {
// 默认连接上127.0.0.1:6379
RedissonClient client = Redisson.create();
RAtomicLong atomicLong = client.getAtomicLong("myLong");
System.out.println("Init value: " + atomicLong.get());
atomicLong.incrementAndGet();
System.out.println("Current value: " + atomicLong.get());
atomicLong.addAndGet(10L);
System.out.println("Final value: " + atomicLong.get());
client.shutdown();
}
}
2,Redisson 还包括 RMap,它是 Java Map 集合的分布式并发实现
package redissonCase;
import org.redisson.Redisson;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
/**
* Redisson 还包括 RMap,它是 Java Map 集合的分布式并发实现
*/
public class ListExamples {
public static void main(String[] args) {
// 默认连接上 127.0.0.1:6379
RedissonClient client = Redisson.create();
// RList 继承了 java.util.List 接口
RList<String> nameList = client.getList("nameList");
nameList.clear();
nameList.add("bingo");
nameList.add("yanglbme");
nameList.add("yanglbme - Overview");
nameList.remove(-1);
boolean contains = nameList.contains("yanglbme");
System.out.println("==========================");
System.out.println("List size: " + nameList.size());
System.out.println("Is list contains name 'yanglbme': " + contains);
nameList.forEach(System.out::println);
client.shutdown();
}
}
3,RLock 是 Java 中可重入锁的分布式实现,
package redissonCase;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
/**
* RLock 是 Java 中可重入锁的分布式实现,下面的代码演示了 RLock 的用法:
*/
public class LockExamples {
public static void main(String[] args) throws InterruptedException {
// 默认连接上127.0.0.1:6379
RedissonClient client = Redisson.create();
// RLock 继承了 java.util.concurrent.locks.Lock 接口
RLock lock = client.getLock("lock");
lock.lock();
System.out.println("lock acquired");
Thread t = new Thread(() -> {
RLock lock1 = client.getLock("lock");
lock1.lock();
System.out.println("lock acquired by thread");
lock1.unlock();
System.out.println("lock released by thread");
});
t.start();
t.join(1000);
lock.unlock();
System.out.println("lock released");
t.join();
client.shutdown();
}
}