【redis】分布式锁
2017-02-15 16:07
148 查看
1)setnx(lockkey, 当前时间+过期超时时间) ,如果返回1,则获取锁成功;如果返回0则没有获取到锁,转向2。
2.)get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向3。
3.)计算newExpireTime=当前时间+过期超时时间,然后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。
4.)判断currentExpireTime与oldExpireTime 是否相等,如果相等,说明当前getset设置成功,获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试。
5) 在获取到锁之后,当前线程可以开始做自增操作,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行delete释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理。
上面是新方案,区别不大
基于redis的分布式锁,欢迎大家批评
2.)get(lockkey)获取值oldExpireTime ,并将这个value值与当前的系统时间进行比较,如果小于当前系统时间,则认为这个锁已经超时,可以允许别的请求重新获取,转向3。
3.)计算newExpireTime=当前时间+过期超时时间,然后getset(lockkey, newExpireTime) 会返回当前lockkey的值currentExpireTime。
4.)判断currentExpireTime与oldExpireTime 是否相等,如果相等,说明当前getset设置成功,获取到了锁。如果不相等,说明这个锁又被别的请求获取走了,那么当前请求可以直接返回失败,或者继续重试。
5) 在获取到锁之后,当前线程可以开始做自增操作,当处理完毕后,比较自己的处理时间和对于锁设置的超时时间,如果小于锁设置的超时时间,则直接执行delete释放锁;如果大于锁设置的超时时间,则不需要再锁进行处理。
上面是新方案,区别不大
基于redis的分布式锁,欢迎大家批评
import javax.annotation.Resource; import org.springframework.stereotype.Component; @Component public class DistributeLock { @Resource(name = "enableRedis") Redis redis; /** * 默认锁的超时时间,30s */ static final int DEFAULT_KEY_TIMEOUT = 30; private void sleep() { try { Thread.sleep(200L); } catch (InterruptedException e) { } } /** * 会一直阻塞,直到加锁成功 * * @param key */ public void lock(String key) { while (redis.setnx(key, "1") != 1) { sleep(); } redis.expire(key, DEFAULT_KEY_TIMEOUT); } /** * 尝试加锁 * * @param key * @return 加锁失败返回false,or true */ public boolean tryLock(String key) { boolean locked = redis.setnx(key, "1") == 1; if (locked) { redis.expire(key, DEFAULT_KEY_TIMEOUT); } return locked; } /** * 尝试加锁,会在一段时间内重复加锁,直到加锁成功 或 超时 * * @param key * @param millis * 尝试加锁时长,单位:秒 * @return 加锁失败返回false,or true * @throws InterruptedException */ public boolean tryLock(String key, long millis) throws InterruptedException { long deadline = System.currentTimeMillis() + millis; while (redis.setnx(key, "1") != 1) { sleep(); millis = deadline - System.currentTimeMillis(); if (millis <= 0L) { // 超时,加锁失败 // 可以顺便检查该锁是不是没有设置超时时间 if (redis.ttl(key) < 0) { // 以防,该锁没有设置超时时间 redis.expire(key, DEFAULT_KEY_TIMEOUT); } return false; } } redis.expire(key, DEFAULT_KEY_TIMEOUT); return true; } public void unlock(String key) { redis.del(key); } }
相关文章推荐
- 使用Redis实现分布式锁
- 分布式缓存技术redis学习系列(三)——redis高级应用(主从、事务与锁、持久化)
- Codis 一个分布式的 Redis 解决方案
- redis作为分布式锁的要点
- Redis 分布式锁的正确实现方式
- Redis笔记整理(二):Java API使用与Redis分布式集群环境搭建
- Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式)介绍
- 使用redis解决分布式单例
- Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式…)介绍
- 用Python组合Celery Redis RabbitMQ进行分布式数据抓取
- Redis分布式锁的正确实现方式
- j2ee分布式架构 dubbo + springmvc + mybatis + ehcache + redis 技术介绍
- 分布式缓存Redis之事务
- 分布式缓存技术redis学习系列(一)——redis简介以及linux上的安装以及操作redis问题整理
- Redis实现分布式环境下的分布式锁机制
- spring session和redis集群打造分布式会话使用方案及错误解决
- Redis分布式锁的简单实现分析
- Redis 持久化、分布式、内存优化及存储过程
- 用 Docker 构建分布式 Redis 集群
- redis分布式锁