浅谈Java基于Consul创建分布式锁
作者:Blue92120
这篇文章主要介绍了浅谈基于Consul创建分布式锁,Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置Consul是分布式的、高可用的、可横向扩展的,需要的朋友可以参考下
Consul
Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。
Consul是分布式的、高可用的、可横向扩展的。它具备以下特性 :
- 服务发现:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易。
- 健康检查:健康检测使consul可以快速的告警在集群中的操作。
- 键/值存储:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
- 多数据中心:无需复杂的配置,即可支持任意数量的区域。
一句话概况:Consul既可以用于注册中心和配置中心,也可以做keyValue存储。使用Consul做分布式锁的底层原理就是keyValue存储。
基于consul的分布式锁
ConsulClient 是一个比较核心的类(consul客户端),keyvalue存储要用。
private ConsulClient consulClient; @PostConstruct public void init(){ consulClient = new ConsulClient(consulLockConfig.getHost(),consulLockConfig.getPort()); }
createSession方法用于创建一个会话并返回sessionId,ttl是过期时间。我们在释放锁的时候会用到这个sessionId。
/** * 创建一个sessionId * @param lockName * @param ttlSeconds * @return */ private String createSession(String lockName,int ttlSeconds){ NewSession session = new NewSession(); //session.setBehavior(Session.Behavior.DELETE); session.setBehavior(Session.Behavior.RELEASE); session.setName("session " + lockName); session.setTtl(ttlSeconds + "s"); return consulClient.sessionCreate(session, null).getValue(); }
加锁的实现:
/** * 获取锁 * @param lockName 锁的名称(key) * @param ttlSeconds 锁的超时时间 * @return */ private boolean tryLock(String lockName,int ttlSeconds){ try { PutParams putParams = new PutParams(); String sessionId = createSession(lockName, ttlSeconds); SessionIdHolder.setSessionId(sessionId); log.info("consul加锁开始(线程:{},锁名称:{},sessionId:{})",Thread.currentThread().getName(), lockName,sessionId); putParams.setAcquireSession(sessionId); //2.将构件好的LockContext存储在consul中 String key = consulLockConfig.PREFIX+lockName; //加锁成功 Boolean value = consulClient.setKVValue(key, sessionId, putParams).getValue(); if(value){ //开起一个新的线程去执行锁续命--调用看门狗的方式实现 if(consulLockConfig.isRenewal()){ //如果续期 new ConsulWatchDog(consulClient).watchSession(sessionId,ttlSeconds);//启动看门狗 } log.info("consul加锁成功(线程:{},锁名称:{},sessionId:{})",Thread.currentThread().getName(), lockName,sessionId); return true; }else{ //将sessionId删除 //consulClient.deleteKVValue(key); log.info("consul加锁失败(线程:{},锁名称:{},sessionId:{})",Thread.currentThread().getName(), lockName,sessionId); return false; } }catch (Exception e){ e.printStackTrace(); return false; } }
解锁的实现:
/** * 释放锁 */ public boolean unLock(String lockName){ //log.info("consul释放锁开始(线程:{},锁名称:{})",Thread.currentThread().getName(),lockName); String sessionId = SessionIdHolder.getSessionId(); try { //先根据锁名称找到对应的sessionId session 是需要进行存储的 现在我们是通过一个lockContnt 假如说业务上不在一个微服务里释放锁 对应的 其他微服务如何获取到这把锁呢 String key = consulLockConfig.PREFIX+lockName; Response<GetValue> kvValue = consulClient.getKVValue(key); if(kvValue==null) return false; GetValue value = kvValue.getValue(); if(value==null) return false; //log.info("consul释放锁开始(线程:{},锁名称:{},sessionId:{})",Thread.currentThread().getName(),lockName,sessionId); PutParams putParams = new PutParams(); putParams.setReleaseSession(sessionId); consulClient.setKVValue(key, sessionId, putParams); //String sessionId = value.getDecodedValue(); consulClient.sessionDestroy(sessionId, null);// key value也会被删除 是使用的DELETE //删除对应的 sessionId存储 //consulClient.deleteKVValue(key); log.info("consul释放锁成功(线程:{},锁名称:{},sessionId:{})",Thread.currentThread().getName(),lockName,sessionId); return true; }catch (Exception e){ e.printStackTrace(); log.info("consul释放锁出错(线程:{},锁名称:{},sessionId:{})",Thread.currentThread().getName(),lockName,sessionId); return false; } }
到此这篇关于浅谈Java基于Consul创建分布锁的文章就介绍到这了,更多相关Consul创建分布锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!