Lua官网

http://doc.redisfans.com/script/eval.html

问题重现:预约功能,用jemter测试,30个不同用户同时预约,2个用户重复发送请求,即重复发送消息场景,结果导致重复消费

避免重复消费方式

1.如第6行,重复原因:第10行,业务逻辑耗时比较长,还没执行第11行,导致6行,执行通过,重复的数据都进来了

2.如第5行+12行,高并发下,加分布式锁,重复请求(具体场景是什么),只有一个能执行业务逻辑。这样不够,6行还是要保留,保证幂等。

分析:分布式锁只能保证高并发下幂等行,无法保证持久幂等。这里注意:分布式锁与existKey,都不是一个固定值,保证10业务逻辑可以并发执行。

高并发与幂等行没有关系。

1 String key = RedisEnum.APPOINT_RECORD_KEY.toKey(reqVO.getLiveId(), reqVO.getUid());
2 String uniqueVal = UUID.randomUUID().toString();
3 String lockKey = RedisEnum.APPOINT_RECORD_LOCK_KEY.toKey(reqVO.getLiveId(), reqVO.getUid());
4 try {
5    if (redisManager.tryLock(lockKey, uniqueVal, APPOINT_RECORD_LOCK_KEY.expired)) {6      Boolean exist = redisManager.existsKey(key);7      if (Boolean.TRUE.equals(exist)) {8         log.error("saveAppoint exception already appointed reqParam:{}", JSON.toJSONString(reqVO));9        throw ExceptionUtils.throwException(LIVE_APPOINTED);}
10 todo 处理业务逻辑
11 redisManager.put(key, RedisEnum.APPOINT_RECORD_KEY.expired, JSON.toJSONString(reqVO));}
} catch (Exception e) {log.error("Saving appoint exception", e);throw ExceptionUtils.throwException(LIVE_APPOINTED);
} finally {12  redisManager.releaseLock(lockKey, uniqueVal);
}
return false;

参考:

https://blog.csdn.net/qq_39736103/article/details/116452752?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

lua实现

加锁:

 public boolean tryLock(String lockKey, String randomUnValue, int expireTime) {Jedis jedis = null;boolean var6;try {jedis = this.jedisPool.getResource();Long result = (Long)jedis.eval(LuaSecript.SETNX_AND_EXPIRE.getScript(), 1, new String[]{lockKey, randomUnValue, String.valueOf(expireTime)});if (result != 1L) {return false;}var6 = true;} catch (Exception var10) {this.logger.error("Try lock failed", var10);return false;} finally {if (jedis != null) {jedis.close();}}return var6;}
public enum LuaSecript {SETNX_AND_EXPIRE("local is_existed = redis.call('setnx', KEYS[1], ARGV[1]);if (is_existed == 1) then redis.call('expire', KEYS[1], ARGV[2]);return 1; end; return 0;"),DEL_KEY_AND_EQUAL_VAL("if (redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]);else return 0;end; "),ZRANGEBYSCORE_ZREM("local data = redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2], 'WITHSCORES', 'LIMIT', ARGV[3], ARGV[4]);if table.getn(data) > 0 then for k,v in pairs(data) do if (k % 2) ~=0 then redis.call('ZREM', KEYS[1], v);end;end;return data;end;");private String script;private LuaSecript(String script) {this.script = script;}public String getScript() {return this.script;}
}

解锁:

 public boolean releaseLock(String lockKey, String randomUnValue) {Jedis jedis = null;boolean var5;try {jedis = this.jedisPool.getResource();jedis.eval(LuaSecript.DEL_KEY_AND_EQUAL_VAL.getScript(), 1, new String[]{lockKey, randomUnValue});return true;} catch (Exception var9) {this.logger.error("Release lock failed", var9);var5 = false;} finally {if (jedis != null) {jedis.close();}}return var5;}

依赖

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

使用lua实现redis分布式锁相关推荐

  1. 【代码学习】lua+redis分布式锁代码实现实例

    文章目录 分布式锁场景和介绍: 分布式锁模板类: 锁实现类 lua脚本加锁和解锁 分布式速度限制 测试分布式锁 分布式锁场景和介绍: 分布式锁演进-基本原理 分布式锁演进-阶段一 分布式锁演进-阶段二 ...

  2. Redis分布式锁—SETNX+Lua脚本实现篇

    前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...

  3. 使用redis分布式锁+lua脚本实现分布式定时任务控制demo

    2019独角兽企业重金招聘Python工程师标准>>> 分布式系统经常要遇到定时任务执行的问题,不能重复执行,但很多时候又不能统一到一个微服务里面,因为这样就失去了微服务的意义.由于 ...

  4. 基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性

    为了保证数据的争用安全,通常要采用锁机制控制. 如果是单应用部署,直接通过synchronized关键字修改方法,就能解决,但是如果是分布式的部署 该方法就不能解决这个问题啦,此时就引出了一个分布式锁 ...

  5. Redis分布式锁使用不当,酿成一个重大事故,超卖了100瓶飞天茅台!!!

    点击关注公众号,Java干货及时送达 来源:juejin.cn/post/6854573212831842311 基于Redis使用分布式锁在当今已经不是什么新鲜事了. 本篇文章主要是基于我们实际项目 ...

  6. Redis 分布式锁使用不当,酿成一个重大事故,超卖了100瓶飞天茅台!!!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 基于Redis使用分布式锁在当今已经不是什么新鲜事了. 本 ...

  7. 秒杀商品超卖事故:Redis分布式锁请慎用!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:浪漫先生 来源:juejin.im/post/6854573 ...

  8. 记一次由Redis分布式锁造成的重大事故,避免以后踩坑!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:浪漫先生 juejin.im/post/5f159cd8f2 ...

  9. Redis 分布式锁没这么简单,网上大多数都有 bug

    Redis 分布式锁这个话题似乎烂大街了,不管你是面试还是工作,随处可见,「码哥」为啥还写? 因为看过很多文章没有将分布式锁的各种问题讲明白,所以准备写一篇,也当做自己的学习总结. 在进入正文之前,我 ...

  10. 深度剖析:Redis分布式锁到底安全吗?看完这篇文章彻底懂了!

    ‍‍‍‍‍‍‍‍‍‍‍‍阅读本文大约需要 20 分钟. 大家好,我是 Kaito. 这篇文章我想和你聊一聊,关于 Redis 分布式锁的「安全性」问题. Redis 分布式锁的话题,很多文章已经写烂了 ...

最新文章

  1. OpenCV+python:膨胀和腐蚀
  2. 删除空值_空白单元格行,如何快速批量删除?简单方法,效率飞升
  3. 智能停车O2O 独角兽初现:“ETCP停车”获5000万美金A轮融资
  4. 使用Python进行汽车黑客攻击:泄露GPS和OBDIICAN总线数据
  5. 运用div css和java_如何将css应用于div模式
  6. python爬虫JS逆向加密破解之百度翻译
  7. Gym102028G Shortest Paths on Random Forests 生成函数、多项式Exp
  8. Mybatis的缓存
  9. js 监听浏览器刷新操作
  10. vue-property-decorator
  11. linux中的 bin sh,Linux-#!/bin/sh理解
  12. 第一次作业补充:项目调研
  13. 《赐我》-一只白羊 同步歌词
  14. 计算机怎样将多行文字转换成表格,怎么把表格里的字变成两行
  15. 海报与Banner的区别
  16. 解决APP抓包问题【网络安全】
  17. 用Python机器人监听微信群聊 !
  18. 小远qq1611532647淘宝主图设计
  19. 自动控制原理3.2---一阶系统的时域分析
  20. linux apache fcgi,Apache使用fcgi方式与PHP结合

热门文章

  1. BZOJ 1002: [FJOI2007]轮状病毒【生成树的计数与基尔霍夫矩阵简单讲解+高精度】
  2. thinkphp无法加载控制器:Admin
  3. c#中 字节数组到浮点型转换
  4. 第二章、Linux操作系统及常用命令
  5. Java入门的程序汇总
  6. flashback database操作步骤
  7. linux下定时执行sh
  8. 从备用类型总盗用steal page
  9. DPDK QOS 3 -- rte meter令牌桶的实现
  10. 【紫书第十一章】图论模型与算法入门