ETCD锁

etcd中的锁是tryLock模式(每次lock都是尝试lock),也就是尝试锁定某个key,如果该key当前状态下是被锁定的话,就无法锁定。引入etcd租约,该租约的效果是给该锁添加失效时长,租约到期,该锁失效,自动释放。代码如下:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.coreos.jetcd.Client;
import com.coreos.jetcd.Lease;
import com.coreos.jetcd.Lock;
import com.coreos.jetcd.data.ByteSequence;
import com.test.errorcode.EtcdError;
import com.test.exception.EtcdException;
import com.test.service.DistributedLock;

@Service
public class DistributedLockImpl implements DistributedLock {
   private static final Log logger = LogFactory.getLog(DistributedLockImpl.class);
   @Autowired
   private Lock lockClient;
   @Autowired
   private Lease leaseClient;
   @Value("${etcd.ttlOfLease}")//配置文件中配置租约的时长
   private long ttlOfLease;
   @Value("${etcd.connectionTimeout}")//连接超时时长
   private long connectionTimeout;
   @Value("${etcd.lockTimeout}")//尝试锁定的超时时长
   private long lockTimeout;

   public Long lock(String lockName) throws EtcdException{
      logger.debug("start to lock required resource:[" + lockName + "]");
      Long leaseId = 0L;

      // 创建一个租约,租约有效期为ttlOfLease,租约获取超时时间为connectionTimeout
      try {
         leaseId = leaseClient.grant(ttlOfLease).get(connectionTimeout, TimeUnit.SECONDS).getID();
         logger.debug("release id is [" + leaseId + "]");
      } catch (InterruptedException | ExecutionException | TimeoutException e) {
         logger.error("create lease error " + e);
         throw new EtcdException(EtcdError.LEASE_CREATE_ERROR);
      }

      // 执行加锁操作,并为锁对应的key绑定租约
      try {
         lockClient.lock(ByteSequence.fromString(lockName), leaseId).get(lockTimeout, TimeUnit.MILLISECONDS);
      } catch (InterruptedException | ExecutionException | TimeoutException e) {
         logger.error("lock resource [" + lockName + "]" + "failed." + e);
         logger.error("revoke lease [" + leaseId + "]");
         leaseClient.revoke(leaseId);
         throw new EtcdException(EtcdError.GET_RESOURCE_LOCK_ERROR, lockName);
      }
      return leaseId;
   }

   /**
    * 解锁操作,释放锁、解除租约
    * 
    * @param lockName:锁名
    * @param lockResult:加锁操作返回的结果
    */
   public void unLock(String lockName, Long leaseId) {
      logger.debug("start to unlock required resource:[" + lockName + "]" + " whth lease[" + leaseId + "]");
      try {
         // 释放锁
         lockClient.unlock(ByteSequence.fromString(lockName)).get(connectionTimeout, TimeUnit.SECONDS);
         // 删除租约
         if (null != leaseId) {
            leaseClient.revoke(leaseId);
         }
      } catch (InterruptedException | ExecutionException | TimeoutException e) {
         logger.error("unlock resource [" + lockName + "]" + "failed." + e);
         throw new EtcdException(EtcdError.DELETE_RESOURCE_LOCK_ERROR, lockName);
      }
   }
   
}

jar包为:

compile 'com.coreos:jetcd-core:0.0.2'
compile 'org.mousio:etcd4j:2.10.0'
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值