redis实现分布式锁

1.主要命令:

  • setnx
  • setex

2.主要问题:

使用redis实现分布式锁,利用上面两个命令的特性。但是最重要的是锁要有过期时间,不然万一服务器宕机或者redis宕机,redis锁将永远得不到释放,出现死锁,其他线程一直获取不到资源。为了避免这种情况发生就必须保证这两个命令setnx与setex(设置过期时间)执行的原子性。

还有一个问题就是如果设置了过期时间,但是线程a在过期时间内没有执行完,这时可能会出现:
B执行到一半,serverA才执行完,这是serverA会释放serverB得锁,会导致无锁。
解决方法保证释放删除得锁与当前锁住得锁是同一个资源,即key,value完全一样,可通过lua脚本,getValue和delKey是一个原子性操作。

3.解决办法:

1.lua脚本实现setnx,setex两个命令的原子性:

读取lua脚本

/*** 获取lua结果* @param key* @param value* @return*/public Boolean luaExpress(String key,String value) {lockScript = new DefaultRedisScript<Boolean>();lockScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("add.lua")));lockScript.setResultType(Boolean.class);// 封装参数List<Object> keyList = new ArrayList<Object>();keyList.add(key);keyList.add(value);Boolean result = (Boolean) redisTemplate.execute(lockScript, keyList);Long expire = redisTemplate.getExpire(key);System.out.println("超时时间:"+expire);return result;}

lua脚本:

local lockKey = KEYS[1]
local lockValue = KEYS[2]-- setnx info
local result_1 = redis.call('SETNX', lockKey, lockValue)
if result_1 == 1
then
local result_2= redis.call('SETEX', lockKey,3600, lockValue)
return result_1
else
return result_1
end

2. lua脚本保证释放的是当前锁:

/*** 释放锁操作* @param key* @param value* @return*/private boolean releaseLock(String key, String value) {lockScript = new DefaultRedisScript<Boolean>();lockScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("unlock.lua")));lockScript.setResultType(Boolean.class);// 封装参数List<Object> keyList = new ArrayList<Object>();keyList.add(key);keyList.add(value);Boolean result = (Boolean) redisTemplate.execute(lockScript, keyList);return result;}

unlock.lua

local lockKey = KEYS[1]
local lockValue = KEYS[2]-- get key
local result_1 = redis.call('get', lockKey)
if result_1 == lockValue
then
local result_2= redis.call('del', lockKey)
return result_2
else
return false
end

3. 采用RedisConnection获取JRedisCommand得java客户端:

  • https://docs.spring.io/spring-data/redis/docs/2.0.3.RELEASE/api/
  • 搜索redisconnection
  • 点击RedisStringCommands
  • 搜索set方法,即可查找到

 public boolean setLock(String key, long expire) {try {Boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {@Overridepublic Boolean doInRedis(RedisConnection connection) throws DataAccessException {return connection.set(key.getBytes(), getHostIp().getBytes(), Expiration.seconds(expire) ,RedisStringCommands.SetOption.ifAbsent());}});return result;} catch (Exception e) {logger.error("set redis occured an exception", e);}return false;}public String get(String key) {try {RedisCallback<String> callback = (connection) -> {JedisCommands commands = (JedisCommands) connection.getNativeConnection();return commands.get(key);};String result = redisTemplate.execute(callback);return result;} catch (Exception e) {logger.error("get redis occured an exception", e);}return "";}

redis实现setnx,setex连用实现分布式锁相关推荐

  1. 【Redis Lua 脚本 可重入分布式锁】

    文章目录 前言 一.最简单的版本:setnx key value 获取锁成功 获取锁失败 释放锁 缺点 二.升级版本:set key value [ex seconds] [nx] 获取锁成功 获取锁 ...

  2. redis mysql 解决超卖_Redis 分布式锁解决超卖问题

    Redis 分布式锁解决超卖问题 1,Redis 事物介绍 1. Redis 事物是可以一次执行多个命令, 本质是一组命令的集合. 2. 一个事务中的所有命令都会序列化, 按顺序串行化的执行而不会被其 ...

  3. 视频教程- 19年录制Redis实战教程 高可用秒杀分布式锁布隆过滤器实战 SpringBoot教程整合-Java

    19年录制Redis实战教程 高可用秒杀分布式锁布隆过滤器实战 SpringBoot教程整合 7年的开发架构经验,曾就职于国内一线互联网公司,开发工程师,现在是某创业公司技术负责人, 擅长语言有nod ...

  4. redis 的惊群处理和分布式锁的应用例子

    在并发量比较高的情况下redis有很多应用场景,提升查询效率,缓解底层DBio ,下面列举两个平时开发中应用过的两个例子,欢迎各位一起讨论改进. 1 . redis 惊群处理 1.1 方案的由来 Re ...

  5. 什么是分布式锁?redis、zookeeper、etcd实现分布式锁有什么不同之处?

    目录 分布式锁定义 目的 基于redis分布式锁 基于zookeeper实现的分布式锁 edis.zookeeper.etcd实现分布式锁的比较 建议选择etcd实现分布式锁 分布式锁定义 分布式环境 ...

  6. 多机器使用setnx 设置同一个key_Redisson分布式锁的简单使用

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 一:前言 我在实际环境中遇到了这样一种问题,分布式生成id的问题!因为业务逻辑的问题,我有个生成id的方法,是根据业务标识 ...

  7. Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析Redis分布式锁的正确使用姿势!...

    Redis分布式锁基本原理 采用 redis 实现分布式锁,主要是利用其单线程命令执行的特性,一般是 setnx, 只会有一个线程会执行成功,也就是只有一个线程能成功获取锁:看着很完美. 然而-- 看 ...

  8. 面试干货10——聊一聊Redis的应用吧!(实现分布式锁、缓存、抽奖、热搜、点赞、商品筛选..)

    Redis这样用 一.String类型 1. 对String类型的理解 2. 常用命令如下 3. 应用场景 ① 分布式锁 ② 缓存设计 ③ 全局唯一序列号.计数器(value为Numbers类型) ④ ...

  9. Redis高阶使用之Redisson分布式锁源码解析

    一.何为分布式锁 1.锁synchronized lock 单机锁 2.我们的一些互斥资源 不能并行执行 需要一个东西来保证是串行执行的 锁synchronized 3.分布式锁:这个锁存储一定是独立 ...

最新文章

  1. 人工智能十大流行算法
  2. Python--day8--Socket编程/异常处理
  3. python精要(78)-模块与包组织(1)-绝对导入
  4. 7天拿到阿里安卓岗位offer,统统给你解决!
  5. 创建者模式 --- 单例模式
  6. Android开机动画总结
  7. 日知录(九):PR视频剪辑Creo
  8. noip2005 篝火晚会
  9. 神经网络评价模型,神经网络评价指标
  10. 数据库sql中S P J SPJ 表的创建
  11. NTP 服务的配置和使用
  12. 程序员这条路,选择深耕技术,还是全面学习比较好?
  13. 如何在Fedora 上dnf安装Node.js
  14. 前端css样式如何设置内边框
  15. 【机器学习原理实战01】Ridge回归模型
  16. CPU构成详细介绍以及工作原理
  17. 非核心版本的计算机上_哪个版本的Microsoft Office最好使用、来占用最少的资源...
  18. centos6安装GitLab全程详解和常见问题解决
  19. 实验向:neural-doodle amp; fast neural-doodle demo 复现流程
  20. 键盘没坏,快捷键可以用,但不能打字

热门文章

  1. IOTOS物联中台从0到1开发modbus_rtu驱动 实例详解
  2. 一个程序员的十年程序人生感悟
  3. 经典SQL语句大全:http://www.cnblogs.com/yubinfeng/archive/2010/11/02/1867386.html
  4. 最好的贵人,是努力的自己
  5. FOR 循环 珠峰折纸
  6. puzzle(1411)《文字》拼单词、一字不落、汉字魔法
  7. 安卓禁用硬件加速_Android硬件加速
  8. 教师节我用Python做了个学生点名系统送给老师当礼物,这回毕业稳了
  9. Hibernate——入门
  10. CF1111C Creative Snap