什么是分布式锁:

本地锁(synchronized、ReentrantLock):只能锁住单个JVM内部,集群多台服务器时,本地锁失效

分布式锁:跨服务器、跨进程都能生效的锁

保证:同一时刻,只有一个服务的一个线程能执行业务

适用场景:

  • 秒杀防超卖
  • 一人一单防重复下单
  • 定时任务集群只跑一次
  • 缓存击穿互斥锁
  • 库存减扣、订单创建

分布式锁必须满足的四个条件:

1.互斥性:同一时刻只有一个线程加锁成功

2.防死锁:服务挂了锁能自动过期释放

3.可重入:同一个线程能多次加锁(不会自己卡死自己)

4.放误删:不能把别人的锁删了

分布式锁的三种实现方式:

1.Redis实现分布式锁

核心命令:set lockKey value NX EX 过期时间

  • NX:互斥,key不存在才设置
  • EX:自动过期(防死锁)

Q:直接删锁有什么坑?

A:超时自动释放后,别的线程拿到锁,这边业务跑完顺手delete,误删别人的锁

S:Lua脚本原子解锁,先判断锁的id是不是自己的(UUID),是自己的才删,原子执行不被插队

原生Redis锁缺点

  • 不可重入
  • 没有锁续命(业务没跑完锁过期了)
  • 主从切换有锁丢失的风险

2.Redisson分布式锁

基于Redis封装好的框架,解决原生Redis所有痛点

  • 自带可重入
  • 看门狗锁续命(业务没跑完自动延长锁时间)
  • 公平锁、读写锁、红锁
  • Lua脚本全部封装好,不用自己写

看门狗:Redisson加锁成功后,后台自动启动一个定时线程(看门狗),核心场景是业务执行时间 > 锁过期时间,锁提前自动过期导致锁失效,加了看门狗之后只要业务还没执行完就会一直自动续期,业务执行完手动解锁,看门狗停止

公平锁:默认锁是谁抢到就是谁的没有顺序,可能出现线程饥饿:一直抢不到锁,而公平锁是先到先得有顺序FIFO,Redis底层用有序队列记录等待线程,锁释放后依次唤醒下一个

读写锁:读和读共享不互斥,读和写、写和写互斥,适合读多写少的场景。加读锁:其他线程可以继续加读锁,不能加写锁;加写锁:其他线程啥都不能干,完全互斥

红锁:向多个独立的Redis节点(不做主从、互不关联)加锁,过半成功才算加红锁,解决主从切换锁丢失的问题;成本高、性能差,实际项目中用的少

3.Zookeeper分布式锁

原理:临时有序节点、监听节点变化

优点:强一致性、无超时问题

缺点:性能比Redis差、维护重,现在企业基本不用

Redis主从

  • 主节点:负责写(增删改),也可以读
  • 从节点:只负责读,自动同步主节点所有数据

核心作用:

  1. 读写分离:写走主库,读走从库,分担压力,提高并发
  2. 数据备份:从节点完整复制主节点数据,不怕数据丢失
  3. 高可用基础:主节点挂了可以手动/自动把从晋升为主,继续提供服务
  • 客户端在 Master 加分布式锁成功
  • 锁数据还没同步到 Slave
  • 此时 Master 突然宕机
  • Slave 被选举成新 Master
  • 新主里没有之前的锁
  • 其他线程又能加锁成功 → 锁失效、超卖、并发错乱

Redis分布式锁的原子性问题

学习Redisson

实现分布式锁Redis和Redisson对比

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐