分布式锁

本文介绍了锁的概念,强调其在并发环境中的协调作用。文章重点讨论了Redis分布式锁的实现,包括SETNX和SET命令的应用,以及通过LUA脚本确保解锁操作的原子性。还提到Redis崩溃可能导致锁失效的问题,以及可能的解决方案如Redlock算法。
摘要由CSDN通过智能技术生成

####什么是锁?
 锁是一个多方可以共同访问的元素,各个访问者通过对该元素的信息的判断,按照一定事先约定的行为进行协调的功能。这个元素可以是任何的东西,根据事先约定的行为的不同也会随之变化。

 例如,一个队列,如果来访者发现自己的id在该队列的头部,那么就认为自己拥有了锁,可以执行某些逻辑,这时候这个队列就相当于一个锁。锁也可以是一个boolean类型的对象,当他为true或者false时,其他线程可以来竞争使得boolean状态改变,从而认为自己获取了锁(当然需要考虑使用场景)。锁也可以是一个信号量,也可以是一个节点,例如zookeeper中,一个节点存在与否就意味着是否可以竞争锁(当然行为是我们自己来定的,zookeeper和redis仅仅是提供了一个放置锁的地方)。当然,最重要的一点就是原子性,我们在加锁和解锁的时候,要充分考虑使用场景来决定对锁的判断策略

####redis锁的实现
 对于redis分布式锁来说,常用的莫过于SETNX,SET,DEL这几个函数了
tip:现在SET函数可以传递参数,例如过期时间,在已存在值时的反应,对于添加成功或者失败的返回值这几个元素,所以SET已经完全可以取代SETNX,甚至说比SETNX表现更好。因为SETNX在加锁时还要设置过期时间字段,需要由客户端根据这个字段来判断锁是否过期,这样一牵扯到非原子性的问题,就会十分复杂

 最简单的加锁解锁代码如下,由于在解锁时,伴随着锁过期的可能,我们需要先判断锁是否是本客户端加的,再去解锁,否则A加锁,A过期,B加锁,A完成任务解锁,就把B加的锁解掉了。解锁操作我们可以想象,他是先查询再操作,不是原子性,所以我们需要封装LUA脚本来使这两条语句具备原子性
具体SET参数意义可以自行搜索

/**
* Non-blocking try to hold a lock
* if true,the work must be finished within millisecond,else the distributed-lock is meaningless
* @param key the key of lock
* @param value a unique String,it will be used When release
* @param expiration it will expirate after now+expiration
* @return true if access,else false
* */
public boolean tryLock(String key,String value,long expiration){
   
    //try to create a record if not exist
    Object res = redisTemplate.execute((RedisCallback) redisConnection -> {
   
        JedisCommands connect = (JedisCommands) redisConnection.getNativeConnection();
        //SETNX can be replace by SET from Redis 2.6.12 version
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值