PowerJob LockService方法工作流程源码解读

 更新时间:2024年01月12日 09:20:11   作者:codecraft  
这篇文章主要为大家介绍了PowerJob LockService方法工作流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下PowerJob的LockService

LockService

tech/powerjob/server/extension/LockService.java

public interface LockService {
    /**
     * 上锁(获取锁),立即返回,不会阻塞等待锁
     * @param name 锁名称
     * @param maxLockTime 最长持有锁的时间,单位毫秒(ms)
     * @return true -> 获取到锁,false -> 未获取到锁
     */
    boolean tryLock(String name, long maxLockTime);
    /**
     * 释放锁
     * @param name 锁名称
     */
    void unlock(String name);
}
LockService接口定义了tryLock、unlock方法

DatabaseLockService

tech/powerjob/server/extension/defaultimpl/DatabaseLockService.java

@Slf4j
@Service
public class DatabaseLockService implements LockService {
    private final String ownerIp;
    private final OmsLockRepository omsLockRepository;
    @Autowired
    public DatabaseLockService(OmsLockRepository omsLockRepository) {
        this.ownerIp = NetUtils.getLocalHost();
        this.omsLockRepository = omsLockRepository;
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            int num = omsLockRepository.deleteByOwnerIP(ownerIp);
            log.info("[DatabaseLockService] execute shutdown hook, release all lock(owner={},num={})", ownerIp, num);
        }));
    }
    @Override
    public boolean tryLock(String name, long maxLockTime) {
        OmsLockDO newLock = new OmsLockDO(name, ownerIp, maxLockTime);
        try {
            omsLockRepository.saveAndFlush(newLock);
            return true;
        } catch (DataIntegrityViolationException ignore) {
        } catch (Exception e) {
            log.warn("[DatabaseLockService] write lock to database failed, lockName = {}.", name, e);
        }
        OmsLockDO omsLockDO = omsLockRepository.findByLockName(name);
        long lockedMillions = System.currentTimeMillis() - omsLockDO.getGmtCreate().getTime();
        // 锁超时,强制释放锁并重新尝试获取
        if (lockedMillions > omsLockDO.getMaxLockTime()) {
            log.warn("[DatabaseLockService] The lock[{}] already timeout, will be unlocked now.", omsLockDO);
            unlock(name);
            return tryLock(name, maxLockTime);
        }
        return false;
    }
    @Override
    public void unlock(String name) {
        try {
            CommonUtils.executeWithRetry0(() -> omsLockRepository.deleteByLockName(name));
        }catch (Exception e) {
            log.error("[DatabaseLockService] unlock {} failed.", name, e);
        }
    }
}
DatabaseLockService基于数据库实现了LockService,其构造器依赖OmsLockRepository,同时注册了ShutdownHook,在关闭的时候执行omsLockRepository.deleteByOwnerIP(ownerIp);其tryLock方法创建OmsLockDO,然后执行omsLockRepository.saveAndFlush,若成功则返回,若有异常则通过omsLockRepository.findByLockName找到omsLockDO,计算加锁时间,若超过MaxLockTime则执行unlock再重新tryLock;其unlock执行omsLockRepository.deleteByLockName

NetUtils.getLocalHost

tech/powerjob/common/utils/NetUtils.java

public static String getLocalHost() {
        if (HOST_ADDRESS != null) {
            return HOST_ADDRESS;
        }
        String addressFromJVM = System.getProperty(PowerJobDKey.BIND_LOCAL_ADDRESS);
        if (StringUtils.isNotEmpty(addressFromJVM)) {
            log.info("[Net] use address from[{}]: {}", PowerJobDKey.BIND_LOCAL_ADDRESS, addressFromJVM);
            return HOST_ADDRESS = addressFromJVM;
        }
        InetAddress address = getLocalAddress();
        if (address != null) {
            return HOST_ADDRESS = address.getHostAddress();
        }
        return LOCALHOST_VALUE;
    }
    public static InetAddress getLocalAddress() {
        if (LOCAL_ADDRESS != null) {
            return LOCAL_ADDRESS;
        }
        InetAddress localAddress = getLocalAddress0();
        LOCAL_ADDRESS = localAddress;
        return localAddress;
    }    
    private static InetAddress getLocalAddress0() {
        // @since 2.7.6, choose the {@link NetworkInterface} first
        try {
            InetAddress addressOp = getFirstReachableInetAddress( findNetworkInterface());
            if (addressOp != null) {
                return addressOp;
            }
        } catch (Throwable e) {
            log.warn("[Net] getLocalAddress0 failed.", e);
        }
        InetAddress localAddress = null;
        try {
            localAddress = InetAddress.getLocalHost();
            Optional<InetAddress> addressOp = toValidAddress(localAddress);
            if (addressOp.isPresent()) {
                return addressOp.get();
            }
        } catch (Throwable e) {
            log.warn("[Net] getLocalAddress0 failed.", e);
        }
        return localAddress;
    }
NetUtils的getLocalHost先判断HOST_ADDRESS是否有值,有则直接返回,否则先从系统属性读取powerjob.network.local.address,读取不到则取LOCAL_ADDRESS,若LOCAL_ADDRESS为null则通过getLocalAddress0获取

OmsLockDO

tech/powerjob/server/persistence/remote/model/OmsLockDO.java

@Data
@Entity
@NoArgsConstructor
@Table(uniqueConstraints = {@UniqueConstraint(name = "uidx01_oms_lock", columnNames = {"lockName"})})
public class OmsLockDO {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
    @GenericGenerator(name = "native", strategy = "native")
    private Long id;

    private String lockName;

    private String ownerIP;
    /**
     * 最长持有锁的时间
     */
    private Long maxLockTime;

    private Date gmtCreate;

    private Date gmtModified;

    public OmsLockDO(String lockName, String ownerIP, Long maxLockTime) {
        this.lockName = lockName;
        this.ownerIP = ownerIP;
        this.maxLockTime = maxLockTime;
        this.gmtCreate = new Date();
        this.gmtModified = this.gmtCreate;
    }
}
OmsLockDO定义lockName为唯一索引,它还定义了ownerIP、maxLockTime

OmsLockRepository

tech/powerjob/server/persistence/remote/repository/OmsLockRepository.java

public interface OmsLockRepository extends JpaRepository&lt;OmsLockDO, Long&gt; {

    @Modifying
    @Transactional(rollbackOn = Exception.class)
    @Query(value = "delete from OmsLockDO where lockName = ?1")
    int deleteByLockName(String lockName);

    OmsLockDO findByLockName(String lockName);

    @Modifying
    @Transactional(rollbackOn = Exception.class)
    int deleteByOwnerIP(String ip);
}
OmsLockRepository继承了JpaRepository,它定义了deleteByLockName、findByLockName、deleteByOwnerIP方法

小结

LockService接口定义了tryLock、unlock方法;DatabaseLockService基于数据库实现了LockService,其构造器依赖OmsLockRepository,同时注册了ShutdownHook,在关闭的时候执行omsLockRepository.deleteByOwnerIP(ownerIp);其tryLock方法创建OmsLockDO,然后执行omsLockRepository.saveAndFlush,若成功则返回,若有异常则通过omsLockRepository.findByLockName找到omsLockDO,计算加锁时间,若超过MaxLockTime则执行unlock再重新tryLock;其unlock执行omsLockRepository.deleteByLockName。

以上就是PowerJob LockService方法工作流程源码解读的详细内容,更多关于PowerJob LockService的资料请关注脚本之家其它相关文章!

相关文章

  • Java数据结构之树和二叉树的相关资料

    Java数据结构之树和二叉树的相关资料

    这篇文章主要介绍了Java 数据结构之树和二叉树相关资料,文中通过示例代码和一些相关题目来做介绍,非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下!
    2023-01-01
  • Java中List常用操作比for循环更优雅的写法示例

    Java中List常用操作比for循环更优雅的写法示例

    List是Java中比较常用的集合类,关于List接口有很多实现类,下面这篇文章主要给大家介绍了关于Java中List常用操作比for循环更优雅的写法,需要的朋友可以参考下
    2021-11-11
  • java的nio的使用示例分享

    java的nio的使用示例分享

    这篇教程展示了5个在Java编程的一些常见场景里使用NIO和NIO.2包的简单示例,需要的朋友可以参考下
    2014-03-03
  • Java设置PDF跨页表格重复显示表头行的步骤详解

    Java设置PDF跨页表格重复显示表头行的步骤详解

    这篇文章主要给大家介绍了关于Java设置PDF跨页表格重复显示表头行的相关资料,这里使用的是Free Spire.PDF for Java的jar包,Spire.PDF for Java 是一款专门对 PDF 文档进行操作的 Java 类库,需要的朋友可以参考下
    2021-07-07
  • SpringBoot Maven升级自带的jar包版本问题

    SpringBoot Maven升级自带的jar包版本问题

    这篇文章主要介绍了SpringBoot Maven升级自带的jar包版本问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Mybatis结果生成键值对的实例代码

    Mybatis结果生成键值对的实例代码

    这篇文章主要介绍了Mybatis结果生成键值对的实例代码,以及MyBatis返回Map键值对数据的实现方法,非常不错,具有参考借鉴价值,需要的的朋友参考下
    2017-02-02
  • java数据类型转换陷阱包括列表陷阱

    java数据类型转换陷阱包括列表陷阱

    这篇文章主要介绍了java数据类型转换的一些陷阱,包括基本数据类型转换列表陷阱,基本上这一篇就把常见的问题就给大家分享一下
    2020-10-10
  • Java线程优先级变量及功能

    Java线程优先级变量及功能

    这篇文章主要介绍了Java线程优先级变量及功能,关于优先级的问可能有两个或更多线程被分配了相同的优先级,那么它们的执行取决于操作系统,更多相关介绍,需要的小伙伴可以参考一下
    2022-06-06
  • Java定时器问题实例解析

    Java定时器问题实例解析

    这篇文章主要结合实例介绍了java当中的定时器的一些问题,有需要的朋友可以参考一下
    2017-04-04
  • Java多线程事务回滚@Transactional失效处理方案

    Java多线程事务回滚@Transactional失效处理方案

    这篇文章主要介绍了Java多线程事务回滚@Transactional失效处理方案,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08

最新评论