redis分布式锁要点

gitee项目:redis-lock-starter

核心知识清单

  1. @AspectJ切面编程
  2. redis分布式锁
  3. 自定义注解的使用
  4. spring.factories编写starter应用
  5. redisson加锁api

注意点

  1. 业务内校验不可少

    • 分布式锁控制竞争时只有一个能进入方法,方法一旦结束就会释放锁,并不持久化资源的占用情况。
    • 演示示例:https://gitee.com/fantasyzsp/redis-lock-starter/blob/master/src/test/java/com/sishu/redis/lock/redisson/business/AnnotatedController.java#L47-51
  2. 保证锁切面/或拦截器优先级高于Spring事务

    • 在事务开始前就抢占锁独占资源,避免事务内受隔离性质影响使得业务内查DB的校验不生效。

    • 演示示例:

      • com.sishu.redis.test.AnnotatedControllerTest#insertWithUniqueAge,注意查看方法链里拦截器的顺序。
      • org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept这里查看目标方法拦截器链顺序。
  3. 锁特性:可重入排它锁

    • 业务内开启多线程时,需要注意锁的排他性。
    • 解锁时,需要注意不要破坏重入记录(减次数,而不是直接删除key)。
    • 看需求考虑后期追加更多锁特性进去。比如不可重入,公平与非公平,读写锁等。

拓展

  1. redis分布式锁注意点

    • 有效期设定不足导致的问题

      • 多个线程同时进入临界区。(T1未执行完毕,锁失效了导致等待的T2也进入临界区),T1可能释放掉T2的锁,恶化锁对并发的控制。

      • 解决方案

        1. 按照业务,设定合理的有效期。

        2. 定时延长锁有效期(redisson采用异步线程定时刷新TTL)。

    • 加锁原子性问题

      • 使用 set key value px milliseconds nx 命令,在加锁的同时设定有效期。(redisson几乎所有操作都用到了lua脚本实现,具有原子性)。
    • 批量加锁时按一致的顺序加锁防死锁

      • 将key排序后在进行加锁,同时建议解锁时逆序解锁,尽可能保证线程能够一次性获取同一组资源。
        • 示例:
          • T1加锁ABCDE五个资源,T2加锁ABCDE五个资源,对A的竞争只有一个能成功,只要竞争A成功,就可以获取同组资源。
          • T1加锁ABCDE五个资源,T2加锁BCDEF五个资源,T3加锁CDEFG。不排序时,可能导致T1持有B,T2持有C,T3持有D,谁都无法加锁成功。
    • 加锁客户机突然宕机导致死锁问题

      • 解决方案
        • 常规的try finally范式无法解决,只有设定较长的过期时间。
        • 不设定过期时间,异常出现时相关资源的访问一直有问题,需要人肉处理。
    • redis服务器宕机

      • 可以参考这篇文章的讲解 https://crazyfzw.github.io/2019/04/15/distributed-locks-with-redis/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值