基于tair的分布式锁实现原理

分布式锁概述分布式锁的实现主要分为三种方式:1、基于Mysql的行锁实现优点:实现简单,不需要额外的中间件来协助实现缺点:增大了数据库的读写压力可能增大数据库的死锁的产生。例如:如果琐是数据库中的行A,然后甲获得A的锁后执行操作,然后请求资源B,而乙当前正持有B的资源却在请求分布式锁A,那么引起死锁。2、基于Zookeeper的实现(可以设计为公平锁、也可以设计为非公平锁)基本原理其实是基于Zookeeper的强一致性和顺序一致性特点,实现方式如下:在Zookeeper中建立一个路径r
摘要由CSDN通过智能技术生成

分布式锁概述

分布式锁的实现主要分为三种方式:
1、基于Mysql的行锁实现

优点:
实现简单,不需要额外的中间件来协助实现
缺点:

  • 增大了数据库的读写压力
  • 可能增大数据库的死锁的产生。例如:如果琐是数据库中的行A,然后甲获得A的锁后执行操作,然后请求资源B,而乙当前正持有B的资源却在请求分布式锁A,那么引起死锁。

2、基于Zookeeper的实现(可以设计为公平锁、也可以设计为非公平锁)
基本原理其实是基于Zookeeper的强一致性和顺序一致性特点,实现方式如下:
在Zookeeper中建立一个路径route,当某服务器需要请求锁资源时就在route下写入临时顺序节点,然后观察自己是否是当前路径下的最小节点,如果是则说明当前自己持有锁,如果不是则启动监听器监听前一节点的删除时间,当前一节点删除后自己获得锁。由于当本节点在设置监听器的时候可能前一节点已经被删除了,从而引起死锁,但是在Zookeeper中设置监听器的操作是原子性的,从而避免这个问题。

优点:
1、实现简单
2、由于是临时节点,所以天然没有死锁的问题
缺点:
需要接入zk,并且需要在客户端引入复杂的逻辑

3、基于Tair、Redis等分布式缓存中间件的实现

优点:简单、高效,且公司都有部署这些缓存中间件


基于Tair的分布式锁实现方案

基本原理是在全局下Tair只用一个唯一控制点,从而实现加锁控制。

1、基于incr和decr实现

在Tair中提供了两个函数:

Result incr(int namespace, Serializable key, int value, int defaultValue, 
            int expireTime, int lowBound, int upperBound)
Result decr(int namespace, Serializable key, int value, int defaultValue, 
            int expireTime, int lowBound, int upperBound)

可以为namespace空间下key下的值增加或者减少value的大小,同时可以设置值的最大值和最小值。
因此这种分布式锁的实现方式为:
1、设置key下的值的最大值为1,最小值为0.默认值为0
2、当某服务器需要加锁时就尝试为key值加1,如果当前value为0则成功并且加锁,否则返回失败,调用函数:
incr(namespace, key, 1,0, expireTime, 0, 1);
3、加锁成功后执行事务,然后解锁即可
缺点:

  • 该锁是不可重入的,因为无法通过value区分是哪台服务器加的锁。
  • 由于无法根据value判断是哪一台服务器,因此会出现锁被其它服务器误解的情况


2、基于get/put/invalide方式实现

实现方式如下:
1、当服务器需要获取锁时调用get(namespace,key)查看当前key下value是否存在,如果存在说明当前锁已被占用。
2、如果当前value存在则说明锁为空,则通过put(namespace,key,version,value,expireTime)上锁,即为key下写入value,注意这个地方version一定为2,因此在put时如果有其它锁一起在抢,当锁被抢走后下次再写value的version已经变为三,因此其它服务器无法写入,只能继续等待。
3、最后通过invalid(namespace,key,value)解锁,即删除该key值下的value。

分布式锁DistributedLock概览

使用方法

DistributedLock锁是注解形式,使用方法是在需要加锁执行的方法上写上注解,如下:

@DistributedLock(customizeLockKey = "test")
public String test1(){
   
    for (int i = 0; i < 100; i++) {
   
        System.out.println("Thread1 run...");
        try {
   
            Thread.sleep(100);
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        }
    }
    return "Thread1 finish";
}

其中加的锁就是字符串test。

代码测试

定义两个分别加分布式锁的方法,但是加的锁不一样

@Component
public class ConcurentApply{
   
    @DistributedLock(customizeLockKey = "test1")
    public String test2(){
   
        for (int i = 0; i < 100; i++) {
   
            System.out.println("Thread2 run...");
            try {
   
                Thread.sleep(100);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
        return "Thread2 finish";
    }
    @DistributedLock(customizeLockKey = "test")
    public String test1(){
   
        for (int i = 0; i < 100; i++) {
   
            System.out.println("Thread1 run...");
            try {
   
                Thread.sleep(100);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        }
        return "Thread1 finish";
    }
}

然后定义一个继承自Thread的类来调用test2方法来实现两个方法并发执行:

@Component
public class Thread1 extends Thread{
   
    @Autowired
    private ConcurentApply apply;
    public void run(){
   
        System.out.println(apply.test2());
    }
}

然后再业务代码中调用这两个方法,让这两个带锁的方法并发执行,查看效果:

@Autowired
private lateinit var td: Thread1;

@Autowired
private lateinit var apply: ConcurentApply;


override fun queryAlgos(param: ZimaAlgoParam?): List<ZimaAlgo?>? {
   
    td.start();
    apply.test1();
    return algoDao.queryAlgos(param)
}

执行后系统输出如下:

[TairLock]tryLock success, key=TM_M_P_DistributedLock_test, value=B-M1AEMD6R-2128.local__http-nio-7001-exec-1__5137d1f6-3ff9-4421-97a0-2a9ccdf1d9d8
[TairLock]tryLockWait success, key=TM_M_P_DistributedLock_test
Thread1 run...
Thread1 run...
Thread1 run...
Thread1 run...
Thread1 run...
... ... ... ...
[TairLock]tryLock success, key=TM_M_P_DistributedLock_test1, value=B-M1AEMD6R-2128.local__Thread-83__a44dd850-6d58-42a2-9228-6fdb197c54f1
[TairLock]tryLockWait success, key=TM_M_P_DistributedLock_test1
Thread2 run...
Thread1 run...
Thread2 run...
Thread1 run...
Thread2 run...
Thread1 run...
Thread2 run...
Thread1 run...
Thread2 run...
Thread1 run...
Thread2 run...
Thread1 run...
Thread2 run...
Thread1 run...
... ... ... ...
[TairLock]unlock success, key=TM_M_P_DistributedLock_test, threadValue=B-M1AEMD6R-2128.local__http-nio-7001-exec-1__5137d1f6-3ff9-4421-97a0-2a9ccdf1d9d8
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
Thread2 run...
... ... ... ...
[TairLock]unlock success, key=TM_M_P_DistributedLock_test1, threadValue=B-M1AEMD6R-2128.local__Thread-83__a44dd850-6d
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值