Springboot-cli 开发脚手架系列
简介
Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。
优势:
- 自带分布式锁
- watch dog自动延期机制,无需手动对锁时间进行续期
- 缓存存储结构丰富
- 支持队列、延时队列
- 支持Topic机制
1. 环境
- 依赖
pom.xml
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.14.0</version>
</dependency>
- yml配置(简配版)
# redis 配置
redisson:
# 是否集群
cluster: false
# 数组格式,参考<yml配置数组>,若开启集群模式,最少配置3个节点
address:
- redis://192.168.41.128:6379
# 连接超时时间
connect-timeout: 3
# 密码
password: 123456
# redis数据库序号,只有单机模式下生效
database: 0
# 传输模式 linux上开启会有更高的性能
use-epoll: false
2. 客户端配置
- 读取yml配置
/**
* redisson yml配置
* @author : qiDing
*/
@Data
@Accessors(chain = true)
@Configuration
@ConfigurationProperties(prefix = RedissonProperties.PREFIX)
public class RedissonProperties {
public static final String PREFIX = "redisson";
/**
* 连接超时,单位:毫秒
*/
private Integer connectTimeout;
/**
* 密码
*/
private String password;
/**
* 服务器地址
*/
private String[] address;
/**
* 数据库序号,只有单机模式下生效
*/
private Integer database;
/**
* 传输模式 linux上开启会有更高的性能
*/
private Boolean useEpoll;
}
- 配置redisson客户端
/**
* Redisson 核心配置
* 更多配置参考 https://github.com/redisson/redisson/wiki/2.-Configuration
* @author ding
*/
@Configuration
@ComponentScan
@EnableCaching
@RequiredArgsConstructor
public class RedissonConfig {
@Resource
private RedissonProperties redissonProperties;
/**
* 单机配置
*/
@Bean
@ConditionalOnExpression("'${redisson.cluster}' == 'false'")
public RedissonClient getRedisson() {
Config config = new Config();
config.setTransportMode(redissonProperties.getUseEpoll() ? TransportMode.EPOLL : TransportMode.NIO)
.setCodec(JsonJacksonCodec.INSTANCE)
.useSingleServer()
.setPassword(redissonProperties.getPassword())
.setDatabase(redissonProperties.getDatabase())
.setAddress(redissonProperties.getAddress()[0]);
return Redisson.create(config);
}
/**
* 集群配置
*/
@Bean
@ConditionalOnExpression("'${redisson.cluster}' == 'true'")
public RedissonClient getClusterRedisson() {
Config config = new Config();
config.setTransportMode(redissonProperties.getUseEpoll() ? TransportMode.EPOLL : TransportMode.NIO)
.setCodec(JsonJacksonCodec.INSTANCE)
.useClusterServers()
// 集群状态扫描间隔时间,单位是毫秒
.setScanInterval(3000)
.setPassword(redissonProperties.getPassword())
.addNodeAddress(redissonProperties.getAddress());
return Redisson.create(config);
}
}
3. 模拟产品业务实战
- 编写业务缓存类
ProductCache
@Component
@RequiredArgsConstructor
@Slf4j
public class ProductCache {
private final RedissonClient redissonClient;
/**
* 存储桶形式存放
*/
public void setBucket(String key, Product product) {
redissonClient.getBucket(key).set(product);
}
/**
* 存储桶形式存放
*
* @param timeout 超时时间
*/
public void setBucket(String key, Product product, long timeout) {
redissonClient.getBucket(key).set(product, timeout, TimeUnit.SECONDS);
}
/**
* 获取值
*/
public Product getBucket(String key) {
RBucket<Product> product = redissonClient.getBucket(key);
return product.get();
}
/**
* 以map的形式存放
*
* @param timeout 超时时间
*/
public void putMapCache(Long productId, Product product, long timeout) {
redissonClient.getMapCache("productMap").put(productId, product, timeout, TimeUnit.SECONDS);
}
/**
* 获取map中的值
*/
public Product getMapByKey(Long productId) {
RMapCache<Long, Product> productMap = redissonClient.getMapCache("productMap");
return productMap.get(productId);
}
/**
* 以set的形式存放
*
* @param timeout 超时时间
*/
public void addSetCache(Product product, long timeout) {
redissonClient.getSetCache("productSet").add(product, timeout, TimeUnit.SECONDS);
}
/**
* 打印set集合
*/
public void printSet() {
RSetCache<Product> product = redissonClient.getSetCache("product");
product.iterator()
.forEachRemaining(p -> log.info("读取到:{}", p));
}
/**
* 实现分布式锁
*/
public void lockTest() {
RLock lock = redissonClient.getLock("productId");
lock.lock();
try {
// 执行业务代码
log.info("执行业务代码");
} finally {
lock.unlock();
}
}
}
4. 效果演示
- 编写测试类
DomeApplicationTests
@SpringBootTest
@Slf4j
class DomeApplicationTests {
@Autowired
ProductCache productCache;
@Test
void setBucket() {
Product product = new Product()
.setProductId(1L)
.setProductName("F12战斗鸡")
.setCreatedDate(new Date());
productCache.setBucket("key001", product);
}
@Test
void getBucket() {
Product p = productCache.getBucket("key001");
log.info("获取到数据:{}", p);
}
@Test
void putMapCache() {
for (int i = 0; i < 10; i++) {
Product product = new Product()
.setProductId(1L + i)
.setProductName("F12战斗鸡")
.setCreatedDate(new Date());
productCache.putMapCache(1L + i, product, 3600);
}
}
@Test
void getMapByKey() {
Product p = productCache.getMapByKey(1L);
log.info("获取到数据:{}", p);
}
@Test
void addSet() {
for (int i = 0; i < 10; i++) {
Product product = new Product()
.setProductId(1L + i)
.setProductName("F12战斗鸡")
.setCreatedDate(new Date());
productCache.addSetCache(product, 3600);
}
}
@Test
void printSet() {
productCache.printSet();
}
}
- 存储桶形式存储
- MapCache形式存储
这里可以发现我们明明是设置了有效期,但这里TTL为什么是-1呢?通过观察我们可以发现,缓存中多了redisson_timeout_set
这个key,其实这个就是redission用来计算key过期时间的。
- SetCache形式存储
5. 分布式锁
- 利用该框架暴露出来的接口,获取锁对象:
redission.getLock("xxx")
- 加锁:
lock .lock()
- 解锁:
lock.unlock()
/**
* 实现分布式锁
*/
public void lockTest() {
RLock lock = redissonClient.getLock("productId");
lock.lock();
try {
// 执行业务代码
log.info("执行业务代码");
} finally {
lock.unlock();
}
}
6. 源码分享
本项目已收录
Springboot、SpringCloud全家桶教程+源码,各种常用框架使用案例都有哦,具备完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,快来看看吧。