Redis分布式锁的一点小理解
1、在分布式系统中,我们使用锁机制只能保证同一个JVM中一次只有一个线程访问,但是在分布式的系统中锁就不起作用了,这时候就要用到分布式锁(有多种,这里指 redis)
2、在 redis当中可以使用命令 setnx(key, value)来实现分布式锁
setnx:当key不存在的时候设置成功,返回1,若存在的话返回0表示失败。使用这个命令的话要搭配 expire(key, time)来设置过期时间,但是这种组合存在问题,如下:
   try {
        if (redisclient. setnx(key 1) == 1) { //
            redisClient.expire(key, 1000);//
        }
    } finally {
        redisClient.del(key);
    }
如上代码,看上去没什么问题,但是极端情况下如果在1处执行完毕2处还没执行这时候这台机器宕机了,那么这个锁将是无期限的,且不会被删除,也就是说设置setnx和expire是两个命令,不具备原子性。 针对这个问题,可以使用 redis2.6版本之后的命令set(key, value, expirefime,NX)来解决,这个命令跟 setnx一样,但是多了过期时间,可以很好的解决这个问题。
3、解决这个问题之后,还存在着一个问题:如果在过期时间内程序代码没执行完,那么其他其他机器线程获得这个锁,这样会造成同时有两个线程执行一段代码,并且A机器(过期还没执行完)中finally会删除key,导致误删到B机器锁(当前获得锁的机器)的情况
1、此时我们可以在相同的机器上开一个守护线程(如上面例子就在A机器再开一个守护线程),这个线程主要作用是在key快过期的时候进行续命操作,保证代码执行完毕。 2、关于误删,我们可以把value设成线程id,删除前判断一下是否是自己的线程ID,是的话再执行删除,如下面代码
     try {
            ....
        } finally {
            if (threadId equals(redisclient get(key)) {//
                redisclient.del(key);//
            }
        }
这时一般情况都没问题,但是这里的1和2又跟前面的问题类似---不具备原子性,所以还是有出错的可能,但是 redis中没有支持获取删除的原子性命令,该怎么解决呢? 我们可以通过工Lua脚本来解决,例如本例中可以像下面这么写
   String luascript = "if redis call('get', KEYS[1])==ARGV[l] then return redis.call('del', KEYS[1]) else return 0 end";
     redisClient.eval(luaScript, Collections.singletonList(key), Collections.singletonList(threadId));
4、到这里,基本就没什么问题了,最终的代码如下
  try {
        String luascript = "if redis call('get, KeY[1])==ARGV[l] then return redis.call('del', KEY[1]) else return 0 end";
        string threadId = Thread.currentThread() getId();
        while (redisclient set(key, threadId, 1000, NX) == 1) {
         // dosomething()
        }
    } finally {
        redisClient.eval(luaScript, Collections.singletonList(key), Collections.singletonList(threadId));
    }
Redis分布式锁的一点小理解的更多相关文章
- 手撕redis分布式锁,隔壁张小帅都看懂了!
		
前言 上一篇老猫和小伙伴们分享了为什么要使用分布式锁以及分布式锁的实现思路原理,目前我们主要采用第三方的组件作为分布式锁的工具.上一篇运用了Mysql中的select ...for update实现了 ...
 - 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
		
首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...
 - Why failover-based implementations are not enough  Redis分布式锁实现      SET resource_name my_random_value NX PX 30000
		
核心 SET resource_name my_random_value NX PX 30000 Distributed locks with Redis – Redis https://redis. ...
 - Redis分布式锁 (图解-秒懂-史上最全)
		
文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...
 - Redis分布式锁
		
Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...
 - Redlock(redis分布式锁)原理分析
		
Redlock:全名叫做 Redis Distributed Lock;即使用redis实现的分布式锁: 使用场景:多个服务间保证同一时刻同一时间段内同一用户只能有一个请求(防止关键业务出现并发攻击) ...
 - SpringBoot集成Redis分布式锁以及Redis缓存
		
https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...
 - Redis专题(3):锁的基本概念到Redis分布式锁实现
		
拓展阅读:Redis闲谈(1):构建知识图谱 Redis专题(2):Redis数据结构底层探秘 近来,分布式的问题被广泛提及,比如分布式事务.分布式框架.ZooKeeper.SpringCloud等等 ...
 - 死磕 java同步系列之redis分布式锁进化史
		
问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...
 
随机推荐
- HDU - 3416-Marriage Match IV (最大流 + 最短路)
			
HDU - 3416:http://acm.hdu.edu.cn/showproblem.php?pid=3416 参考:https://www.cnblogs.com/kuangbin/archiv ...
 - codeforces 814 C. An impassioned circulation of affection(二分+思维)
			
题目链接:http://codeforces.com/contest/814/problem/C 题意:给出一串字符串然后q个询问,问替换掉将m个字符替换为字符c,能得到的最长的连续的字符c是多长 题 ...
 - Spreading the Wealth uva 11300
			
A Communist regime is trying to redistribute wealth in a village. They have have decided to sit ever ...
 - Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么?
			
相信大家已经对 kafka 的基本概念已经有一定的了解了,下面直接来分析一下 ISR 和 AR 的概念. ISR and AR 简单来说,分区中的所有副本统称为 AR (Assigned Replic ...
 - React-Native组件样式合集
			
最近在阅读RN的文档,但有一点深感遗憾的是——官方对绝大多数RN组件没有用Gif图或者静态图的方式呈现给大家. 所以我通过百度查询,一个一个的查到了这些RN组件的UI表现图,下面呈现给大家 阅前必 ...
 - Scrapy框架的下载与安装
			
一.下载scrapy 首先,如果安装了anaconda, 可以直接在terminal窗口中输入: conda install scrapy 在图示符中,输入y, 表示继续处理信息 二.验证 是否安装成 ...
 - python判断一个数是否为整数
 - 策略模式+注解 干掉业务代码中冗余的if else...
			
前言: 之前写过一个工作中常见升级模式-策略模式 的文章,里面讲了具体是怎样使用策略模式去抽象现实中的业务代码,今天来拿出实际代码来写个demo,这里做个整理来加深自己对策略模式的理解. 一.业务 ...
 - Linux常用命令 —— 进程类
			
service (CentOs6) 1.service 服务名 start -------------- 启动 2.service 服务名 stop ...
 - Winform中设置DevExpress的RadioGroup的items从配置文件中加载
			
场景 DevExpress的RadioGroup的items选项如果是不确定的话,需要其从配置文件中加载. 实现 在项目目录下新建Config文件夹,文件夹下新建xml配置文件. <?xml v ...