springboot 集成redisson 分布式锁
2020-04-21 本文已影响0人
型火
什么是分布式锁?
首先,什么是锁? 所谓锁,就是防止共享资源被抢占,限制同一时间只有一个角色获得资源的工具.
计算机和现实世界的逻辑都是相通的,可以联想到生活中的公共厕所. (有人-->无人 == 获得锁,锁释放, 一夫当关万夫莫开~)
那什么是分布式锁? 分布式对应的是单机, 单机的锁可以使用synchronize,但这属于JVM级别,其限制范围无法超出当前机器, 而在正式环境中,不可能是单机,都是分布式环境(即多台机器组成集群对外服务), 因此要保证同一时间只有一台机器获得共享资源,就必须有一个中间层来进行管理.
比如执行定时任务,如果不加分布式锁,就会导致每台机器上都重复执行一遍.
什么情况下使用分布式锁
- 定时任务避免重复执行;
- 高并发下缓存未命中时查询数据库避免缓存击穿,需保证只有一个线程查询db;
- 避免用户重复提交,用户多次点击请求时前端限制是一方面,后端需要保证只有一次请求入库;
如何实现分布式锁
上面说了,必须有中间层来进行管理,这个中间层即常用的中间件, 比如:
- 数据库
- redis
- zookeeper
最常见的是使用redis的 setNx(只有key不存在时set成功), 但一般个人实现的redis分布式锁可能不能满足生产环境高并发下的复杂情况,我们使用三方开源组件redisson;
redisson是什么
官方解释:
Redisson是架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid)。Redis官方推荐
Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。
注: 分布式锁只是redisson的一个小功能
最简单方式使用redisson分布式锁
1. 添加依赖(3.6.5)
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
2.注入redisson 对象
- 单机模式
/**
* 注入 redisson client
*
* @return
*/
@Bean
public Redisson redisson() {
Config config = new Config();
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig
.setAddress("redis://" + redissonConfig.getHost() + ":" + redissonConfig.getPort())
.setDatabase(redissonConfig.getDatabase());
singleServerConfig.setConnectionMinimumIdleSize(10);
if (StringUtils.isNotEmpty(redissonConfig.getPassword())) {
singleServerConfig.setPassword(redissonConfig.getPassword());
}
return (Redisson) Redisson.create(config);
}
@Data
@Component
@ConfigurationProperties(prefix ="spring.redis")
public class RedissonConfig {
@ApiModelProperty("host")
private String host;
@ApiModelProperty("port")
private String port;
@ApiModelProperty("database")
private Integer database;
@ApiModelProperty("password")
private String password;
}
- 哨兵模式(略)
- redis cluster模式(略)
3.加锁
- retreen lock ( 可重入锁)
RLock redissonLock = redisson.getLock(lockKey);
try {
log.info("分布式锁锁定 start...");
redissonLock.lock();
// TODO 业务逻辑
} finally {
log.info("分布式锁锁定 end...");
redissonLock.unlock();
}