分布式锁:多个请求都去抢某个资源的时候,需要給这个资源添加锁,谁先获取到锁,谁执行某先操作,其他请求只能阻塞,只有当上一个请求释放了锁以后,再获取锁,再去操作;
redis实现分布式锁主要是用的 SETNX 命令
格式 setnx key value 将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则
SETNX 不做任何动作。 SETNX 是『 SET if Not eXists』 (如果不存在,则 SET)的简写
返回值:
设置成功,返回 1 。
设置失败,返回 0 。
实例代码
示例代码:
redis> EXISTS job # job 不存在
(integer) 0
redis> SETNX job "programmer" # job 设置成功
(integer) 1
redis> SETNX job "code-farmer" # 尝试覆盖 job ,失败
(integer) 0
redis> GET job # 没有被覆盖
"programmer"
还有就是可用给其设置过期时间
格式: setex key seconds value
将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。 如果 key 已经存在, SETEX
命令将覆写旧值。 这个命令类似于以下两个命令: SET key value EXPIRE key seconds # 设置生存时间
不同之处是, SETEX 是一个原子性(atomic)操作,关联值和设置生存时间两个动作会 在同一时间内完成,该命令在 Redis
用作缓存时,非常实用。可用版本:
版本 >= 2.0.0
返回值:
设置成功时返回 OK 。
当 seconds 参数不合法时,返回一个错误。
示例代码:
# 在 key 不存在时进行 SETEX
redis> SETEX cache_user_id 60 10086
OK
redis> GET cache_user_id # 值
"10086"
redis> TTL cache_user_id # 剩余生存时间
(integer) 49
# key 已经存在时, SETEX 覆盖旧值
redis> SET cd "timeless"
OK
redis> SETEX cd 3000 "goodbye my love"
OK
redis> GET cd
"goodbye my love"
redis> TTL cd
(integer) 2997
2java实现demo
实现思路
2.1 获取redis分布式锁 ,进行操作
2.2执行完操作进行锁释放
2.3 可以通过jedis 或使用springboot提供的RedisTemplate来操作redis或者Redisson框架
本demo使用 RedisTemplate来实现
@Component
public class DemoRedisDistributedLock {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 获得锁
* @param lockId 锁ID ,这个要是一个唯一值例如:UUID
* @param millisecond 过期时间
*/
public boolean getLock(String lockId, long millisecond) {
Boolean success = redisTemplate.opsForValue().setIfAbsent(lockId, "lock",
millisecond, TimeUnit.MILLISECONDS);
return success != null && success;
}
/**
*当处理完业务逻辑后,需要手动的把锁释放掉。
@param lockId 锁ID ,这个是释放的锁
*/
public void releaseLock(String lockId) {
redisTemplate.delete(lockId);
}
}
//注意当锁过期了,但是遇到问题,还没有执行完,这个问题上面的代码没法处理,这个时候应该有一个锁续命的操作,比如另开一个线程,监控当前的锁有没有释放,没有释放那么就把 过期时间延长;
可以参考以下博文 Redisson框架
解决过期没执行完操作问题
哈哈以后写一篇 Redisson实现redis的demo