分布式锁的使用原创
金蝶云社区-ooodz
ooodz
11人赞赏了该文章 4,452次浏览 未经作者许可,禁止转载编辑于2024年01月31日 17:05:01
summary-icon摘要由AI智能服务提供

本文概述了分布式锁在微服务环境中的必要性及其实现方式,特别强调了苍穹平台使用zookeeper实现的两种模式:性能模式和稳定模式。性能模式在会话断开时锁自动消失,适用于能处理锁丢失的场景;稳定模式则在微服务节点不在注册中心时才失效,保证了锁的安全性。同时介绍了分布式锁接口`kd.bos.dlock.DLock`的主要方法,包括锁的申请、释放和模式切换,以及通过Monitor查看锁信息的方法。

1. 分布式锁概述

如果需要独占某个资源,在分布式环境下(微服务),不能用JDK的锁,需要使用分布式锁服务。


苍穹平台分布式锁使用zookeeper实现,有两种模式:

1) 性能模式:使用临时点存储锁信息,zk会话断开,锁自动消失。

2) 稳定模式:使用持久化节点存储锁信息,zk断开锁不消失,只有同时在微服务节点不在注册中心了,锁才会失效(在下次被申请时判断解锁)。

默认启用稳定模式(通过系统参数DLock.performance=false配置),在代码中,申请锁前可指定模式。


性能模式用于能自行处理可能存在锁丢失的情况。

性能模式下zk会话断开(如网络原因)锁自动消失,而微服务节点可能还在运行中,已获取锁的代码也可能还在跑,故存在锁同时被申请使用的风险。

稳定模式则无此问题,已获得锁在异常宕机后,下个锁申请者,只需等待宕机的微服务节点在注册中心消失,即可获得(解除旧锁),最快秒级,最迟约10分钟,依赖于注册中心的节点列表更新。


2. 分布式锁接口:kd.bos.dlock.DLock


public interface DLock extends AutoCloseable{

    /**
    * 获取锁,一直等待,直到获取。
    */
    void lock();
    
    /**
    * 尝试获取锁,不等待,获取到返回true(无锁竞争的情况下必为true),否则返回false。
    */
    boolean tryLock();
    
    /**
    * 尝试获取锁,在timeoutMillis毫秒内获取到,返回true,否则返回false。
    */
    boolean tryLock(long timeoutMillis);
    
    /**
    * 释放锁
    */
    void unlock();
    
    /**
    * 等同unlock
    */
    void close();
    
    /**
    *  快速模式
    */
    DLock fastMode();
    
    /**
    * 稳定模式
    */
    DLock stableMode();
    
    //////////////////////////////////////////////////////////////////////////////////////
    
    /**
    * 分布式锁对象,不可重入。
    */
    static DLock create(String key);
    static DLock create(String key, String desc);
    
    /**
    * 分布式锁对象,可重入(仅在本jvm范围内)。
    */
    static DLock createReentrant(String key);
    static DLock createReentrant(String key, String desc);
    
    /**
    * 获取所有锁信息
    */
    static Map<String, DLockInfo> getAllLockInfo();
    
    /**
    * 获取key对应的锁信息,不存在则返回null。
    */
    static DLockInfo getLockInfo(String key);
 
}


3. 简单例子


tryLock

DLock lock = DLock.create("bos/test_key", "测试锁信息");
// lock.fastMode(); //转换未性能模式,须在申请(tryLock/lock)前设置。

// 未获得锁则返回false
if (lock.tryLock()) {
    try {
        // 在这里处理业务逻辑...
    } finally {
        // 解锁
        lock.unlock();
    }
}


lock

// lock(): 一直等待直到获得锁
try(DLock lock = DLock.create("bos/test_key", "测试锁信息").lock()) {
    // 在这里处理业务逻辑...
}



获取锁信息

DLockInfo lockInfo = DLock.getLockInfo("bos/test_key");



4.Monitor查看锁信息

在monitor中,点击任一节点的“分布式锁”,即可查看到集群内所有分布式锁信息,列出的锁可操作unlock和clear:


1)分布式锁的配置信息

DLock.type=zookeeper
DLock.performance=false


2)循环列出租户账套信息及其锁信息

tenantId=tenant_devcorelib_dev, accountName=devcorelib_dev_oracle, accountNumber=devcorelib_dev_oracle, accountId=201912161501544917, count=1


{
    key: bos/test_key,
    desc: 测试锁信息,
    waitingLocks: 0,
    createTime: 2020-11-17 19:48:16.758,
    instance: 172.19.114.96,
    createThread: Thread[xxx/traceId:ea1185e16ef8700e/time:1605613684643,5,main],
    owner: 1710f598ce78d81,
    pttl: 0,
    storePath:/devcorelib_dev/runtime/__dlock__201912161501544917/
}

waitingLocks:表示该锁的申请者等待个数

instance:当前拥有锁的微服务节点ip

createThread:拥有锁的线程,结合monitor的线程堆栈可查到什么代码在调用

owner:使用的zk连接ID

pttl: redis版的锁剩余时间,zk版无意义

storePath:锁在zk中的存储路径,含集群、账套信息(按集群、账套隔离)。



图标赞 11
11人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!