转;

Redisson实现分布式锁

Redisson文档参考:https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

  redis是实现分布式锁的一种方式,其他还可以基于数据库,zookeeper等方式实现;这里拿出redis单说一下,redis从原理上大概有两种实现方式,要么是调用redis原生的原子性命令,要么是通过eval执行封装好的lua脚本;而从使用上来讲也有两种方式,要么自己动手实现(参考:https://www.cnblogs.com/linjiqin/p/8003838.html),要么使用别人已经封装好的,例如Redis官方推荐的Redisson客户端。考虑到Redisson的官方推荐,加上大牛效应,当然是“拿来主义”好了。

开始引入

pom文件中引入依赖:

<!-- redisson 分布式锁实现 -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.8.2</version>
</dependency>

spring中配置:

  引入约束:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:redisson
="http://redisson.org/schema/redisson"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://redisson.org/schema/redisson
http://redisson.org/schema/redisson/redisson.xsd"
default-lazy-init="true">

测试staging环境:

<!-- redisson 客户端 配置实现 -->
<redisson:client id="redissonClient">
<redisson:cluster-servers password="${password}">
<redisson:node-address value="redis://127.0.0.1:6600"/>
<redisson:node-address value="redis://127.0.0.1:6601"/>
<redisson:node-address value="redis://127.0.0.1:6602"/>
</redisson:cluster-servers>
</redisson:client>

生产production环境:

<!-- redisson 客户端 配置实现 -->
<redisson:client id="redissonClient">
<redisson:cluster-servers password="${password}">
<redisson:node-address value="redis://127.0.0.1:6602"/>
<redisson:node-address value="redis://127.0.0.1:6603"/>
<redisson:node-address value="redis://127.0.0.2:6602"/>
<redisson:node-address value="redis://127.0.0.2:6603"/>
<redisson:node-address value="redis://127.0.0.3:6602"/>
<redisson:node-address value="redis://127.0.0.3:6603"/>
</redisson:cluster-servers>
</redisson:client>

业务中使用:

public class LockBiz {

    @Autowired
RedissonClient redissonClient; public boolean doWithLock(long groupId, OperateType operateType, String operator, List<Config> configList) {
boolean isLocked = false;
String lockName = "fi_config_groupid_" + groupId;
RLock lock = redissonClient.getLock(lockName);
if (lock == null) {
log.error("lock is null");
return false;
} try {
try {
boolean lockedState = lock.isLocked();
if (lockedState) {
log.error("lock_redisson state seems already locked: {}, name of lock is: {}", lockedState, lockName);
}
for (int i = 0; i < Constants.TRY_TIMES; ++i) {
isLocked = lock.tryLock(Constants.TRY_LOCK_TIME, Constants.AUTO_UNLOCK_TIMES, Constants.LOCK_TIME_UNIT);
log.info("lock_redisson result: {}, try times: {}, time consuming: {}", isLocked, (i+1), (System.currentTimeMillis() - startLock));
if (isLocked) {
break;
}
}
} catch (InterruptedException e) {
log.error("failed to get lock_redisson: ", e);
}
if (!isLocked) {
log.error("try lock_redisson failed");
}
/**
加锁成功,处理业务逻辑
*/
} finally {
if (isLocked) {
try {
lock.unlock();
} catch (Throwable t) {
log.error("failed to unlock_redisson, {}", ExceptionUtils.getStackTrace(t));
}
}
}
} }

注意事项:

  1. redisson的2版本和3版本在配置redis地址的时候貌似不一致,2版本无需前缀“redis://”,而3版本需要;

  2. getLock时,RLock lock = redissonClient.getLock(lockName);  这个lockName一定要唯一,redisson应该是将这个lockName同时作为lock的name和key的名称,如果和别人重复了,就需要和别人竞争同一把锁了,而不是自己的业务和自己的业务竞争锁了。(今天就出现了个问题,我把lockName设置为2,经常会出现加锁失败,并且是在循环加锁之前 这把锁就已经锁上了,现在想想应该是别人在其他地方给redis中添加了个key=2的,导致我无法加锁,排查了挺长时间)

Redisson的大概原理

首先是获取到了一个可重入锁:

然关键后是tryLock方法:

从上面可以看出,redisson底层也是基于封装Lua脚本实现分布式锁的,但是应该解决了一些其他可能存在的问题,例如官方说的:

Redisson实现分布式锁的更多相关文章

  1. 使用Redisson实现分布式锁,Spring AOP简化之

    源码 Redisson概述 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid).它不仅提供了一系列的分布式的Java常用对象,还提供了许多 ...

  2. Redisson实现分布式锁(3)—项目落地实现

    Redisson实现分布式锁(3)-项目落地实现 有关Redisson实现分布式锁前面写了两篇博客作为该项目落地的铺垫. 1.Redisson实现分布式锁(1)---原理 2.Redisson实现分布 ...

  3. Redisson实现分布式锁(2)—RedissonLock

    Redisson实现分布式锁(2)-RedissonLock 有关Redisson实现分布式锁上一篇博客讲了分布式的锁原理:Redisson实现分布式锁---原理 这篇主要讲RedissonLock和 ...

  4. Redisson实现分布式锁(1)---原理

    Redisson实现分布式锁(1)---原理 有关Redisson作为实现分布式锁,总的分3大模块来讲. 1.Redisson实现分布式锁原理 2.Redisson实现分布式锁的源码解析 3.Redi ...

  5. 利用Redisson实现分布式锁及其底层原理解析

    Redis介绍 参考地址:https://blog.csdn.net/turbo_zone/article/details/83422215 redis是一个key-value存储系统.和Memcac ...

  6. 【高并发】你知道吗?大家都在使用Redisson实现分布式锁了!!

    写在前面 忘记之前在哪个群里有朋友在问:有出分布式锁的文章吗-@冰河?我的回答是:这周会有,也是[高并发]专题的.想了想,还是先发一个如何使用Redisson实现分布式锁的文章吧?为啥?因为使用Red ...

  7. Redisson 实现分布式锁的原理分析

    写在前面 在了解分布式锁具体实现方案之前,我们应该先思考一下使用分布式锁必须要考虑的一些问题.​ 互斥性:在任意时刻,只能有一个进程持有锁. 防死锁:即使有一个进程在持有锁的期间崩溃而未能主动释放锁, ...

  8. spring boot:用redis+redisson实现分布式锁(redisson3.11.1/spring boot 2.2)

    一,为什么要使用分布式锁? 如果在并发时锁定代码的执行,java中用synchronized锁保证了线程的原子性和可见性 但java锁只在单机上有效,如果是多台服务器上的并发访问,则需要使用分布式锁, ...

  9. 冷饭新炒:理解Redisson中分布式锁的实现

    前提 在很早很早之前,写过一篇文章介绍过Redis中的red lock的实现,但是在生产环境中,笔者所负责的项目使用的分布式锁组件一直是Redisson.Redisson是具备多种内存数据网格特性的基 ...

随机推荐

  1. 《JavaScript高级程序设计》笔记:BOM(八)

    BOM(浏览器对象模型)提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关. window对象 全局作用域 定义全局变量与在window对象上直接定义属性还是有一点差别:全局变量不能通过 ...

  2. WEB框架-Django框架学习(二)- 模型层

    今日份整理为模型层 1.ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库, ...

  3. 突击战 (uva 11729)贪心

    思路:就是把J大的放在前面.为什么这样贪心呢? 看看这个图 #include<iostream> #include<algorithm> #include<vector& ...

  4. flask wtforms组件详解

    一.简介 在flask内部并没有提供全面的表单验证,所以当我们不借助第三方插件来处理时候代码会显得混乱,而官方推荐的一个表单验证插件就是wtforms.wtfroms是一个支持多种web框架的form ...

  5. Element-UI动态更换主题

    参考:vue-基于elementui换肤[自定义主题] 实践: 需求1.后期维护主题色不更换:  直接在线主题生成工具下载,在APP.VUE引入:(注意Element UI 版本1.3?2.0) 需求 ...

  6. 使用Harbor配置Kubernetes私有镜像仓库

    通常情况下,在私有云环境中使用kubernetes时,我们要从docker registry拉取镜像的时候,都会给docker daemo配置–insecure-registry属性来告诉docker ...

  7. 企业出口退税申报系统的Sqlite数据库破解及读写

    QQ:564955427 原始出处:https://www.cnblogs.com/Charltsing/p/TSSB.html 最近一些朋友反映龙图的企业出口退税申报系统的Sqlite数据库改变了加 ...

  8. form单选框

    form中的单选框: var resultStartRadio = new Ext.form.RadioGroup({ id : 'resultStartRadio', name :"for ...

  9. 微信中如何做到访问app的下载链接时直接跳到默认浏览器去执行下载

    在我们使用微信营销的时候,很容易碰到H5链接在微信内无法打开或在微信内无法打开app下载页的情况.通常这种情况微信会给个提示 “已停止访问该网址” ,那么导致这个情况的因素有哪些呢,主要有以下四点 1 ...

  10. C#之Using(转)

    1.using指令. using 命名空间名字.例如: using System; 这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常 ...