0
点赞
收藏
分享

微信扫一扫

分布式锁.

目录

分布式锁

1、jvm层面的加锁,单机锁

2、分布式锁
分布式微服务架构,拆分后各个服务之间为了避免冲突和数据故障而加入的一种锁

问题
以下这种架构会带来的问题就是:如果redis存储数据,多台springboot修改Redis,也就是多台springboot各有一个线程对这个数据进行访问,而数据时不能同时被两个线程同时修改的,就会出现问题
在这里插入图片描述
分布式锁原理

jvm锁原理:为了防止两个线程对同一堆内存数据访问,增加一个第三方标记这个数据是否正在被一个线程访问,synchronized中第三方就是自己的对象头,对象头中标记有锁还是无锁,lock就是lock对象里的信号量;

而在分布式,数据存储在所有springboot共享的区域,jvm锁只能在一个服务内起作用,这时就需要分布式锁,而分布式锁也是通过第三方信号来标记这个数据是否正在被访问,这个第三方可以使redis也可以是其他信号量;

有分布式锁还需要jvm锁吗?

分布式锁可以保证所有进程只有一个线程对该数据访问,不需要jvm锁也可以保证数据安全;但是会增加网络的IO,所以会在每个进程内使用jvm锁达到类似过滤效果,提高性能

两大类分布式锁

类cas自旋式

mysql redis

一个线程访问到数据然后加上了锁,其他访问该数据的线程不断以询问的方式自旋获取锁;自旋询问时不是依靠cpu了而是网络IO,性能大大下降

event事件通知锁状态

zookeeper etcd

一个线程访问到数据然后加上了锁,其他线程看见数据被锁就类似阻塞,等到这条数据释放锁,通知一个正在等待的线程,告知它可以访问

Redis分布式锁

出现问题与解决

案例

一个基础的分布式业务逻辑
在这里插入图片描述

单机超卖问题

给整个方法加锁,两种锁看状态

  • sync:下死命令,进来抢锁,必须抢完完成业务
  • lock:有trylock(),尝试抢锁,可是设定时间,抢不到可以释放

在这里插入图片描述

分布式问题

使用反向代理负载均衡访问多个服务
JMeter做压测,输入线程数和http请求
高并发单机锁还是能出现超卖,一个商品买了两次

单机锁没办法解决分布式问题

  1. 声明锁
    在这里插入图片描述
  2. 加锁释放锁
    在这里插入图片描述
保证释放锁

如果出现异常的话,可能无法释放锁

必须在 finally代码块里释放锁

redis宕机如何保证释放锁

给锁设置过期时间,到时间后自动释放锁
在这里插入图片描述

设置时间不保证原子性

写在一起保证原子性
在这里插入图片描述

业务代码过多,锁超过时间自动释放
  1. A线程进来拿到锁,处理自己的业务超过10秒,锁自动释放
  2. B线程进来发现没有锁,自己加了一把锁
  3. A线程完成任务,释放了过期的锁,删了别人的锁
  4. B线程锁被释放,其他线程都能进来

判断,只能删自己的锁
在这里插入图片描述

finally块里的判断和解锁不是原子的

使用 lua 脚本:Jedis.eval(script)

用其他方法

在这里插入图片描述

set两条数据保证原子
在这里插入图片描述
watch:乐观锁,监控期间有人把数据改了,就取消提交,释放这次操作,不覆盖
在这里插入图片描述
使用Redis事务保证原子性删除锁
在这里插入图片描述

锁过期时间续期

业务逻辑没执行完,锁续期,缓存续命

主从结构锁丢失

异步复制导致锁丢失

主节点没来得及把刚set的数据给从节点,就挂了

Redisson

直接用Redisson获得锁、加锁lock()、释放锁unlock()
在这里插入图片描述
直接释放锁在超高并发也会出现问题,所以要判断一下
1.是否持有锁
2.是否当前线程所持有
在这里插入图片描述

举报

相关推荐

Redis与分布式-分布式锁

0 条评论