分布式锁

149 阅读3分钟
分布式锁
  1. 控制分布式系统之间同步访问共享资源的一种方式

  2. 解决方案

    1. Redis分布式锁

      1. 命令:加锁加过期时间set key value nx ex 10s,释放del key
      2. setNx 加锁,如果为空就set值,并返回1,如果存在(不为空)不进行操作,并返回0
      3. setNx 是redis命令中的方法,setIfAbsent 是java中的方法
      4. Redisson 通过lock,unlock方法加锁解锁,后台维持一个watchDog线程,每10s判断锁是否存在,存在自动续期
    2. Zookeeper分布式锁,通过顺序,临时节点去做

      1. 排他锁(独占锁):在获取锁的时候,所有客户端尝试去创建临时子节点,最终只有一个能创建成功,获得锁,然后那些没抢到锁的节点注册监听,进入等待(羊群效应)

      2. 共享锁(读锁):所有客户端去创建临时顺序节点,然后调用getChildren接口来获取所有的子节点列表,去判断是否拿到锁,编号最小的获取锁,其他的注册监听,监听的是比他序号小的那一个节点,进入等待 还可以用封装好的Curator去做,锁方案:排他锁,读写锁,可重入排他锁(acquire加锁,release释放)

      3. CountDownLatch:让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒,做减法(共享锁)

      4. CyclicBarrier:与CountDownLatch相反,也就是做加法,开始是0,加到某个值的时候就执行

    3. 基于数据库

      1. 悲观锁:就是修改数据的时候先加锁,依靠数据库提供的锁机制 "For Update"
      2. 乐观锁:可以基于Version机制来实现,操作数据的时候先给表加一个版本,每操作一次,版本+1,更新之前先查询版本号,更新的时候再去比对一次,相等更新,不相等,就不更新,是一种无锁化修改值的操作,CAS就是乐观锁
分布式事务

事务是访问数据库的一个操作序列,CURD满足ACID原则

  1. ACID原则

    1. 原子性:不可分割
    2. 一致性:数据一致
    3. 隔离性:互不影响
    4. 持久性:数据持久
  2. CAP理论

    1. Consistency:一致性,当数据分布在多个节点上,从任意结点读取到的数据都是最新的状态
    2. Availability:可用性,所有请求都有响应,不会出现响应超时或响应错误
    3. Partition tolerance:分区容错性,一个节点挂了不影响其他节点提供服务
  3. BASE理论

    1. Basically Available:基本可用
    2. Soft state:软状态
    3. Eventually consistent:最终一致性
  4. 解决方案

    1. 通过@Transactional注解来做事务控制,他是基于SpringAOP来实现的,实质上就是拦截对象方法,对方法进行改造,增强,将具体的逻辑与事务处理解耦,默认情况下,只有来自外部的方法调用才会被AOP代理捕获,类内部方法之间调用不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰
    // 场景:充值,退款
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    
    1. Propagation:事务传播行为

      1. 默认required 如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务
      2. requires_new 创建一个新的事务,如果当前存在,则把当前事务挂起
    2. Isolation:事务隔离级别

      1. 读未提交: 脏读
      2. 读已提交: 不可重复读
      3. 重复读: 幻读
      4. 序列化,隔离级别越高,并发能力越低
      5. Isolation.DEFAULT:使用底层数据库默认的隔离级别,mysql默认 重复读
    3. RollbackFor :事务回滚的异常类型,默认只有RuntimeException才会回滚