likes
comments
collection
share

分布式锁课题

作者站长头像
站长
· 阅读数 17

分布式锁概念

解决分布式服务下,多线程环境对同一份资源竞争的数据安全性分布式锁是 用于保证整个集群内的多线程并发线程安全性的一种手段

分布式锁特征

高性能、可重入、防死锁和互斥性

  • 高性能:最求高QPS

  • 可重入:当一次请求的代码中包含两个锁时,并且递归调用两个锁时,要保证可重入,否则会出现死锁 ,重入几次就要释放几次

public synchronized void test1() {
    // 阻塞卡死了 
    test2(); 
} 
public synchronized void test2() { 
    test1()
}
  • 防死锁 除上面的情况下,如果加锁后服务器宕机,锁不释放也会产生死锁

  • 互斥性

实现分布式锁的方式

  • Mysql 性能低下,通过insert时的唯一索引实现
  • redis 可以通过setNx方法实现,这个是最简单的分布式锁,比如执行一个方法时,加一个锁,且不设置过期时间,或者设置一个很大的过期时间,但是有弊端,对于业务量不高也可以使用 另外一种就是使用redission框架,这个安全性更高
  • zookeeper 该锁最安全,但是成本有点大,因为还要引进zookeeper

使用场景

  • 保证接口的幂等,防止重复提交,这个时很高频的使用
  • 分布式的任务调度,分布式的系统可能多个执行器执行定时任务,防止任务重复执行,使用分布式锁,这个在我执行实现的任务调度中也使用过
  • 防止超卖的情况 这个实际工作中我也遇到过,做过抢单业务都会遇到此种情况

使用redis实现分布式锁特性

  • 原子性 由于redis的设置分布式锁,需要两个命令
  1. 设置key value
  2. 设置过期时间 即便使用setNx方法,底层也是两个命令 setNX item-4 111 set item-4 111 EX 20 如果第一个命令执行成功了,第二个失败了,那么就没有了过期时间,照成死锁,就不具备原子性,要么都成功,要么都失败,所以要通过使用lua脚本来解决
  • 过期时间 上面说了,没有过期时间可能会出现死锁的情况

  • 锁续期 如果一个业务锁到了过期时间但是业务没有执行完,就会造成锁失效,没有锁住,这部分的解决方案就是通过watchdog来实现

  • 正确释放锁 A上的锁被B释放了,这样就会造成错误释放锁,原因是A与B的key值是相同的,所以要注意key值

使用redis实现分布式锁的部署方式

  1. 单机 简单,但是风险大
  2. 哨兵 主从 如果mater挂掉,又没同步到slave会导致,锁丢失
  3. 集群 虽然是集群但是,也是部署在集群中其中一台机器上,挂掉就没了
  4. 红锁 全都是master,但是性能低,成本高

redission实现分布式锁

加锁

分布式锁课题

解锁

分布式锁课题

watchdog锁续期

分布式锁课题