What is Consul? How to create distributed locks based on Consul

Consul is an open source tool launched by HashiCorp, which is used to realize service discovery and configuration of distributed systems. Consul is distributed, highly available, and horizontally scalable. It has the following characteristics:

Service discovery: Consul makes service registration and service discovery easy through DNS or HTTP interfaces. Health check: Health check enables consul to quickly alert the operation in the cluster. Key/value store: A system for storing dynamic configuration. Provides a simple HTTP interface that can be operated anywhere. Multi-datacenter: Support any number of regions without complicated configuration.

One-sentence summary: Consul can be used not only for registration centers and configuration centers, but also for keyValue storage. The underlying principle of using Consul as a distributed lock is keyValue storage.

Distributed lock based on consul

ConsulClient is a relatively core class (consul client), which is used for keyvalue storage.

    private ConsulClient consulClient;

    @PostConstruct
    public void init(){
        consulClient = new ConsulClient(consulLockConfig.getHost(),consulLockConfig.getPort());
    }

The createSession method is used to create a session and return the sessionId, ttl is the expiration time. We will use this sessionId when releasing the lock.

    /**
     * 创建一个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();
    }

Implementation of locking:

/**
 * 获取锁
 * @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;
	}
}

Implementation of unlocking:

/**
 * 释放锁
 */
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;
	}
}

Supongo que te gusta

Origin blog.csdn.net/Blue92120/article/details/131663530
Recomendado
Clasificación