0719~分布式锁

概念:在分布式环境下,保证某个资源在同一时间访问时,只有一个线程能访问到资源;

分布式锁的实现方式:

1.基于数据库实现:

innodb行锁;

排他锁:一次只允许一个线程访问,只有等一个线程执行完后才会有下个线程进入;

乐观锁:

版本号控制;在数据库中加一个Version字段;

基于数据库主键实现分布式锁;

基于数据库索引实现分布式锁;

乐观锁的缺点:常见的ABA问题;

2.基于Redis实现:

出现的问题:

原子性问题:设置超时时间

if(jedis.setnx(lock_stock,1) == 1){	//获取锁
    expire(lock_stock,5000)		 //设置锁超时
    try {
        业务代码需要10秒执行完毕
    } finally {
        jedis.del(lock_stock)			 //释放锁
    }
}

死锁问题:(没有释放锁/没有删除锁);删除锁判断一下是不是自己的锁;把value设置uuid

//A-uuid:1    redis:123-1
//B-uuid:2    redis:123-2
String uuid = UUID.randomUUID().toString();
if(jedis.set('123', uuid,"NX","EX",5) == 1){	//获取锁并设置超时
    try {
        //业务代码
    } finally {
        String lockValue = jedis.get("123");	//获取锁的值
        if(lockValue.equals(uuid)){			//判断是不是自己的锁
            jedis.del("123")			 	  //释放锁
        }
    }
}

释放锁的原子性问题:lua脚本保证原子性;

String uuid = UUID.randomUUID().toString();
if(jedis.set('123',uuid,"NX","EX",5) == 1){	//获取锁并设置超时
    try {
        业务代码
    } finally {
        //lua脚本
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        
        if 
        	redis.call('get', '123') == '1111111' 
        then 
            return redis.call('del', '123') 
        else 
            return 0 end
            
            
        //执行脚本
        jedis.eval(script, Collections.singletonList("123"),Collections.singletonList(uuid));
    }
}

 redis提供的redis命令,setnx,比如三个线程同时进入一个业务,A线程进去了,只有A线程执行完释放锁后,其他两个线程才会执行;只有key不存在才会存value返回1,key不存在不会存value返回0;

但是会有原子性的问题,如果代码没有执行完就出错了,那么数据的一致性如何保证呢?

此时用Redisson来操作;

Redission是什么?

是Java用来操作redis的工具包,Redisson的宗旨是让用户redis的操作分离,为了是让用户更注重处理业务代码;

Redission常见的锁:

可重入锁;线程可重新进入的锁;

联锁;在分布式场景下使用,必须等其他几个线程都上锁之后,主线程才能拿到锁;

红锁;和联锁一样,唯一区别就是其他几个线程只需要大部分上锁就可以了;

读写锁;只有写完之后,读的线程才能执行;

闭锁(重点):如下图,CountdownLatch里面有一个初始值,就是线程的数量,线程每执行完一个就会减一,只有当CountdownLatch里面的值为零的时候,await方法才会放行,否则在await方法出等待;

 

信号量:并发场景下,把数据库里的库存先拿到缓存里面预热,然后下单在缓存里进行库存扣减;

公平锁:保持先进先出的原则,和队列一样;

3.基于zookeeper实现(临时顺序节点+监听):

zookeeper:解决分布式服务,保证数据一致性的协调解决方案;是层次型的目录树的数据结构;

原理图:

 四种节点分类:

1.持久化节点:

2.持久化顺序节点:

3.临时节点:

4.临时顺序化节点(重点):

使用原理图:

 主要实现原理:临时顺序节点+监听机制实现的;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值