Consul 分布式锁

基于Consul的分布式锁主要利用Key/Value存储API中的acquire和release操作来实现。acquire和release操作是类似Check-And-Set的操作:

acquire操作只有当锁不存在持有者时才会返回true,并且set设置的Value值,同时执行操作的session会持有对该Key的锁,否则就返回false
release操作则是使用指定的session来释放某个Key的锁,如果指定的session无效,那么会返回false,否则就会set设置Value值,并返回true

未被上锁

image.png

被上锁

image.png

编码如下

package com.qxwz.ops.station.change.util;

import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.kv.model.PutParams;
import com.ecwid.consul.v1.session.model.NewSession;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 基于Consul的互斥锁
 *
 * @author muxin.sun
 */
public class Lock {

    private static final String prefix = "lock/";  // 同步锁参数前缀
    private volatile String sessionId;
    private final ConsulClient consulClient;
    private final String sessionName;
    private final String lockKey;

    /**
     *
     * @param consulClient  consul client
     * @param sessionName   同步锁的session名称
     * @param lockKey       同步锁在consul的KV存储中的Key路径,会自动增加prefix前缀,方便归类查询
     */
    public Lock(final ConsulClient consulClient,
                final String sessionName,
                final String lockKey) {
        this.consulClient = consulClient;
        this.sessionName = sessionName;
        this.lockKey = prefix + lockKey;
    }

    /**
     * 获取同步锁
     *
     * @param block     是否阻塞,直到获取到锁为止
     * @return true OR false 获取锁成功
     */
    public Boolean lock(boolean block) throws RuntimeException {
        if (Objects.isNull(sessionId)) {
            synchronized (Lock.class) {
                if (Objects.isNull(sessionId)) {
                    sessionId = createSession(sessionName);
                    while(true) {
                        PutParams putParams = new PutParams();
                        putParams.setAcquireSession(sessionId);
                        if(consulClient.setKVValue(lockKey, "lock:" + LocalDateTime.now(), putParams).getValue()) {
                            return true;
                        } else if (block) {
                            continue;
                        }
                        return false;
                    }
                }
            }
        }
        throw new RuntimeException(sessionId + " - Already locked!");
    }

    /**
     * 释放同步锁
     *
     * @return true OR false 释放同步锁成功
     */
    public Boolean unlock() {
        PutParams putParams = new PutParams();
        putParams.setReleaseSession(sessionId);
        boolean result = consulClient.setKVValue(lockKey, "unlock:" + LocalDateTime.now(), putParams).getValue();
        consulClient.sessionDestroy(sessionId, null);
        return result;
    }

    /**
     * 创建session
     * @param sessionName session name
     * @return sessionId
     */
    private String createSession(final String sessionName) {
        NewSession newSession = new NewSession();
        newSession.setName(sessionName);
        return consulClient.sessionCreate(newSession, null).getValue();
    }

}

参考如下:http://blog.didispace.com/spring-cloud-consul-lock-and-semphore/

你可能感兴趣的:(Consul 分布式锁)