分布式锁实现

1. 接口类DistributedLock

/**
 * 分布式锁
 */
public interface DistributedLock {

    /**
     * 加锁方法
     *
     * @param lockType 锁类型
     * @param bizId 业务流水号
     * @param expireSeconds 超时时间
     * @return true 加锁成功 false加锁失败
     */
    boolean lock(DistributedLockTypeEnum lockType, String bizId, int expireSeconds);

    /**
     * 锁释放.
     *
     * @param lockType 锁类型
     * @param bizId 业务流水号
     */
    boolean release(DistributedLockTypeEnum lockType, String bizId);

}

2.DistributedLock的分布式锁实现类

/**
 * 基于Tair的分布式锁实现
 *
 */
public class TairDistributedLock implements DistributedLock {

    /**
     * logger
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerNames.BIZ_SERVICE);

    /**
     * tair client
     */
    @Autowired
    private TairCacheClient tairCacheClient;

    /**
     * Lock.
     *
     * @param lockType       the biz type
     * @param bizId         the biz id
     * @param expireSeconds 过期时间
     * @return true, if successful
     */
    @Override
    public boolean lock(DistributedLockTypeEnum lockType, String bizId, int expireSeconds) {
        String tairKey = this.getTairKey(lockType, bizId);
        try {

            /**
             *  @notice
             *  1. 先查一次tair,如果能够查到,说明已有数据存在,直接返回false
             *  2. 如果不查询直接调用incr方法,则会导致过期时间被更新,tair锁一直不会失效的问题
             */
            Result<DataEntry> result = tairCacheClient.getInteger(tairKey);

            if (existLocked(result)) {

                LogUtil.warn(LOGGER, " lock already, id={0}, {1}", tairKey, result);

                return false;
            }

            Result<Integer> lockResult = tairCacheClient.incr(tairKey, 1, 0, expireSeconds);

            if (lockFailed(lockResult)) {

                LogUtil.warn(LOGGER, " lock failed, id={0}, {1}", tairKey, lockResult);

                return false;
            }

            LogUtil.info(LOGGER, " lock succeed, id={0}, {1}", tairKey, lockResult);

        } catch (Exception ex) {
            LogUtil.error(LOGGER, ex, " lock exception, id=" + tairKey);

            return false;
        }

        return true;
    }

    /**
     * Release.
     *
     * @param bizType the biz type
     * @param bizId   the biz id
     */
    @Override
    public boolean release(DistributedLockTypeEnum bizType, String bizId) {
        String tairKey = this.getTairKey(bizType, bizId);
        try {
            boolean result = tairCacheClient.removeObject(tairKey);

            if (!result) {

                LogUtil.error(LOGGER, " unlock failed, id=" + tairKey);

                return false;
            }

            LogUtil.info(LOGGER, " unlock succeed, id={0}", tairKey);

        } catch (Exception ex) {
            ModuleLogUtil.error(LOGGER, ex, " lock exception, id=" + tairKey);

            return false;
        }
        return true;
    }

    public boolean existLocked(Result<DataEntry> result) {

        return result != null && result.getValue() != null && result.getValue().getValue() != null;
    }

    public boolean lockFailed(Result<Integer> lockResult) {

        return null == lockResult || !lockResult.isSuccess() || lockResult.getValue() == null
                || lockResult.getValue() != 1;
    }

    /**
     * 获取tair key
     *
     * @param lockType
     * @param bizId
     * @return
     */
    public String getTairKey(DistributedLockTypeEnum lockType, String bizId) {
        if (lockType != null) {
            return OpcoreConstants.APP_NAME + lockType.getCode() + "-" + bizId;
        } else {
            return bizId;
        }
    }

}

3.锁类型枚举

/**
 * 分布式锁类型
 *
 */
public enum DistributedLockTypeEnum {

    /** 合同编号 */
    CONTRACT_NO("CONTRACT_NO", "合同编号"),



    /** 开通任务id */
    OPEN_TASK_ID("OPEN_TASK_ID", "开通任务id"),

  
    ;

    /**
     * 类型
     */
    private String code;
    /**
     * 描述
     */
    private String desc;

    DistributedLockTypeEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    /**
     * 通过枚举<code>code</code>获得枚举
     *
     * @param code 枚举代码
     * @return 枚举对象
     */
    public static DistributedLockTypeEnum getByCode(String code) {
        for (DistributedLockTypeEnum taskStatusEnum : values()) {
            if (taskStatusEnum.getCode().equals(code)) {
                return taskStatusEnum;
            }
        }
        return null;
    }

    /**
     * Getter method for property <tt>code</tt>.
     *
     * @return property value of code
     */
    public String getCode() {
        return code;
    }

    /**
     * Getter method for property <tt>desc</tt>.
     *
     * @return property value of desc
     */
    public String getDesc() {
        return desc;
    }
}

4.锁模版类

/**
 * 加锁模版
 * 
 */
public class LockTemplate {

    /**
     * 执行锁
     *
     * @param lock
     * @param callback
     */
    public static <R extends Object> R execute(DistributedLock lock, LockCallback callback) {

        String lockId = callback.getLockId();
        boolean locked = false;

        R result = null;

        try {

            locked = lock.lock(callback.getTargetType(), lockId, callback.getExpireSeconds());

            if (locked) {

                result = (R) callback.process();
            } else {

                result = (R) callback.handleFailed();
            }

        } finally {
            if (locked) {

                lock.release(callback.getTargetType(), lockId);
            }
        }

        return result;
    }
}

6.锁回调接口

/**
 * 锁回调接口
 *
 */
public interface LockCallback<R extends Object> {

    /**
     * 避免小概率不同业务,ID相同的冲突,由使用方决策是否重写。
     *
     * @return
     */
    default DistributedLockTypeEnum getTargetType() {
        return DistributedLockTypeEnum.CONTRACT_NO;
    }

    /**
     * 获取锁ID.
     */
    String getLockId();

    /**
     * 锁超时时间 默认超时时间为3秒.
     */
    default int getExpireSeconds() {
        return OpcoreConstants.COMMON_LOCK_EXPIRE_SECONDS;
    }

    /**
     * 执行业务逻辑.
     */
    R process();

    /**
     * 当没有获取到tair锁时的回调,默认不处理.
     */
    default R handleFailed() {

        throw new OpcoreException(OpcoreResultCodeEnum.PROCESS_FAILED, "get tair lock faild.");
    }

}

使用:

LockTemplate.execute(tairDistributedLock, new LockCallback() {

            @Override
            public DistributedLockTypeEnum getTargetType() {
                return DistributedLockTypeEnum.APPLY_ORDER_ID;
            }

            @Override
            public String getLockId() {
                return task.getReferenceId();
            }

            @Override
            public Object process() {

                //业务逻辑

                return null;

            }
        });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值