redis是做为缓存的主流选择,这里主要拿它和memcached比较一下:
redis是单线程模型,没有锁的概念,不存在资源竞争,对于同一key是原子操作;memcached是多线程模型。利用自身的cas操作实现锁的操作(等同与乐观所,每一个key对应会产生一个64bit的标记,当某个线程更新key的值是会比较这个标记有没有变化,有变化则放弃更新);
redis中有一个setnx函数(set if not exist,当且仅当 key 不存在,将 key 的值设为 value ,并返回1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0),可以利用它来实现一个简单的分布式锁;核心代码如下:
public class RedisLock implements Lock {
@Autowired
protected StringRedisTemplate redisTemplate;
private static final Logger logger = Logger.getLogger(RedisLock.class);
// lock flag stored in redis
private static final String LOCKED = "TRUE";
// timeout(ms)
private static final long TIME_OUT = 30000;
// lock expire time(s)
public static final int EXPIRE = 60;
// private Jedis jedis;
private String key;
// state flag
private volatile boolean locked = false;
private static ConcurrentMap<String, RedisLock> map = Maps.newConcurrentMap();
public RedisLock(String key) {
this.key = "_LOCK_" + key;
redisTemplate = (StringRedisTemplate) ApplicationContextHolder.getBean("redisTemplate");
}
public static RedisLock getInstance(String key) {
return map.getOrDefault(key, new RedisLock(key));
}
public void lock(long timeout) {
long nano = System.nanoTime();
timeout *= 1000000;
final Random r = new Random();
try {
while ((System.nanoTime() - nano) < timeout) {
if (redisTemplate.getConnectionFactory().getConnection().setNX(key.getBytes(), LOCKED.getBytes())) {
redisTemplate.expire(key, EXPIRE, TimeUnit.SECONDS);
locked = true;
logger.debug("add RedisLock[" + key + "].");
break;
}
Thread.sleep(3, r.nextInt(500));
}
} catch (Exception e) {
}
}
@Override
public void unlock() {
if (locked) {
logger.debug("release RedisLock[" + key + "].");
redisTemplate.delete(key);
}
}
@Override
public void lock() {
lock(TIME_OUT);
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public Condition newCondition() {
return null;
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
}
可以利用以上对象对共享资源进行锁定,功能类似于java内置锁ReentrantLock
其他常见用法:
if(getRedisClient().setnx("需要锁定的key", value)>0){
return "重复调用";
}
以上利用setnx的特性实现表单重复提交的问题。避免请求密集造成数据重复
分享到:
相关推荐
现在很多项目单机版已经不满足了,分布式变得越受欢迎,同时也带来很多问题,分布式锁也变得没那么容易实现,分享一个redis分布式锁工具类,里面的加锁采用lua脚本(脚本比较简单,采用java代码实现,无须外部调用...
本资源为一步一步实现redis分布式锁的demo,利用redis实现高可用的分布式锁,规避各种坑、坑、坑!
SpringBoot基于redis的分布式锁,有word使用文档,根据文档配置即可使用
用注解实现redis分布式锁,防止短时间内重复请求,尤其对于请求耗时较长的方法,希望对大家有帮助
redlock-py, 在 python 中,Redis分布式锁 redlock - python 中的分布式锁这个 python 库实现了基于redis的分布式锁管理器算法( ) 。要创建锁定管理器:dlm = Redlock([{"host":"localhost","port":
Redis分布式锁实现Redisson 15问.doc
redis分布式锁带方法名和过期时间,如果不传方法名自动获取改方法名做key,使锁的粒度到方法级别,释放锁的时间可以根据自己的需要自定义,默认5s,为了解决超大方法执行时间太长,还没有执行完,锁就被释放掉的问题.
redis分布式锁的工具类,采用的是Lua代码的方式,保证了Java执行方法的原子性。
Redis分布式锁在实现跨进程、跨机器的互斥访问时,虽功能强大,但也存在一些常见问题。这些问题主要源于网络延迟、系统时钟误差以及Redis自身的特性。 一个典型问题是锁的"死锁"现象,即因进程意外终止或网络故障,...
003 redis分布式锁 jedis分布式锁 Redisson分布式锁 分段锁
使用Redis分布式锁时,需要注意设置合适的超时时间和锁的释放机制,以防止因为锁未及时释放导致的资源浪费或系统阻塞等问题。 另外,还需要考虑锁的粒度和范围,尽量减小锁的范围,避免锁的持有时间过长或锁的竞争...
C#.net Redis分布式锁源码实现
主要介绍了Java基于redis实现分布式锁代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
使用命令介绍: SETNX SETNX key val 当且仅当key不存在时,set一个key为val的字符串,返回1;...为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。 delete delete key 删除key
redis分布式锁,包含单服务器上锁解锁情况,和分布式上锁解锁情况,全部封装在类里,有需要可以下载,希望可以帮助到你。
java面试题Redis分布式锁+zk 分布式锁.md
redis 分布式锁java 实现
最新springBoot++redis分布式锁+swagger
redis分布式锁工具包,提供纯Java方式调用,支持传统Spring工程, 为spring boot应用提供了starter,更方便快捷的调用