seo网站关键词优化价格,网站关键词和描述,wordpress 速度变慢,软件开发哪个培训机构好一、概述
分布式锁#xff0c;即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题#xff0c;而分布式锁#xff0c;就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是#xff0c;分布式系统中竞争共享资源的最小粒度从线程升级…一、概述
分布式锁即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题而分布式锁就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是分布式系统中竞争共享资源的最小粒度从线程升级成了进程。
基于 Redis 单机实现的分布式锁其方式和 Memcached 的实现方式类似利用 Redis 的 SETNX 命令此命令同样是原子性操作只有在 key 不存在的情况下才能 set 成功。而基于 Redis 多机实现的分布式锁Redlock是Redis 的作者 antirez 为了规范 Redis 分布式锁的实现提出的一个更安全有效的实现机制。
二、基于 Redis 单机实现的分布式锁
1、 使用 SETNX 指令
使用 Redis 的 SETNX 指令该指令只在 key 不存在的情况下将 key 的值设置为 value若 key 已经存在则 SETNX 命令不做任何动作。key 是锁的唯一标识可以按照业务需要锁定的资源来命名。
2、SETNX value值是(系统时间过期时间)
setnx(lockkey, 当前时间过期超时时间) 如果返回1则获取锁成功如果返回0则没有获取到锁 long expires System.currentTimeMillis() expireTime; //系统时间设置的过期时间
String expiresStr String.valueOf(expires);
// 如果当前锁不存在返回加锁成功
if (jedis.setnx(key_resource_id, expiresStr) 1) {return true;
}
// 如果锁已经存在获取锁的过期时间
String currentValueStr jedis.get(key_resource_id);
// 如果获取到的过期时间小于系统当前时间表示已经过期
if (currentValueStr ! null Long.parseLong(currentValueStr) System.currentTimeMillis()) {// 锁已过期获取上一个锁的过期时间并设置现在锁的过期时间不了解redis的getSet命令的小伙伴可以去官网看下哈String oldValueStr jedis.getSet(key_resource_id, expiresStr); if (oldValueStr ! null oldValueStr.equals(currentValueStr)) {// 考虑多线程并发的情况只有一个线程的设置值和当前值相同它才可以加锁return true;}
}
//其他情况均返回加锁失败
return false;
}
3、Redis分布式锁方案三使用Lua脚本(包含SETNX EXPIRE两条指令)
lua脚本如下 if redis.call(setnx,KEYS[1],ARGV[1]) 1 thenredis.call(expire,KEYS[1],ARGV[2])
elsereturn 0
end;
加锁代码如下 String lua_scripts if redis.call(setnx,KEYS[1],ARGV[1]) 1 then redis.call(expire,KEYS[1],ARGV[2]) return 1 else return 0 end;
Object result jedis.eval(lua_scripts, Collections.singletonList(key_resource_id), Collections.singletonList(values));
//判断是否成功
return result.equals(1L);
三、基于Redisson框架
其实 Redisson 也封装 可重入锁Reentrant Lock、公平锁Fair Lock、联锁MultiLock、红锁RedLock、读写锁ReadWriteLock、 信号量Semaphore、可过期性信号量PermitExpirableSemaphore、 闭锁CountDownLatch等。具体参考Redisson详解及开发实例
大体流程如下 watch dog自动延期机制 看门狗启动后对整体性能也会有一定影响默认情况下看门狗线程是不启动的。如果使用redisson进行加锁的同时设置了锁的过期时间也会导致看门狗机制失效 1、引入依赖 dependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion3.19.2/version
/dependency
2、配置类实现 Bean
public RedissonClient redissonClient(){
Config config new Config();
config.setTransportMode(TransportMode.EPOLL); // 默认是NIO的方式
config.useClusterServers()//可以用rediss://来启用SSL连接前缀必须是redis:// or rediss://.addNodeAddress(redis://127.0.0.1:7181);
return Redisson.create(config);
}
3、工具类 import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.UUID;/*** Redisson 加锁*/
Component
public class RedissonUtil {Resourceprivate RedissonClient redissonClient;public String getKey(){return UUID.randomUUID().toString();}public String getKey(Class? tClass, Thread thread){return tClass.toString() _ thread.getStackTrace()[2].getMethodName();}public RLock getClint(String key){RReadWriteLock lock redissonClient.getReadWriteLock(key);return lock.writeLock();}public void lock(String key) {this.getClint(key).lock();}public void unLock(String key) {this.getClint(key).unlock();}public void lock(String key, long expire) {try {this.getClint(key).tryLock(expire, TimeUnit.SECONDS);} catch (Exception e) {}}}
4、测试代码 AutowiredRedissonUtil redissonUtil;String key leo;long extime 10;boolean islock redissonUtil.lock(key, extime);if (islock) {try {} finally {redissonUtil.unLock(key);}}