尚品汇-(二十一)

目录:

(1)使用redis实现分布式锁

(2)优化之设置锁的过期时间

(3.)优化之UUID防误删

(4)优化之LUA脚本保证删除的原子性


(1)使用redis实现分布式锁

(解决集群服务设置Reids的问题) 

 

1. 多个客户端同时获取锁(setnx)

2. 获取成功,执行业务逻辑{从db获取数据,放入缓存},执行完成释放锁(del)

3. 其他客户端等待重试

更改前面的代码

@Override
public void testLock() {
   // 1. 从redis中获取锁,setnx
   Boolean lock = this.redisTemplate.opsForValue().setIfAbsent("lock", "111");
   if (lock) {
      // 查询redis中的num值
      String value = (String)this.redisTemplate.opsForValue().get("num");
      // 没有该值return
      if (StringUtils.isBlank(value)){
         return ;
      }
      // 有值就转成成int
      int num = Integer.parseInt(value);
      // 把redis中的num值+1
      this.redisTemplate.opsForValue().set("num", String.valueOf(++num));

      // 2. 释放锁 del
      this.redisTemplate.delete("lock");
   } else {
      // 3. 每隔1秒钟回调一次,再次尝试获取锁
      try {
         Thread.sleep(100);
         testLock();
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
}

重启,服务集群,通过网关压力测试:

基本实现。

问题:setnx刚好获取到锁,业务逻辑出现异常,导致锁无法释放

解决:设置过期时间,自动释放锁。

(2)优化之设置锁的过期时间

setnx刚好获取到锁,业务逻辑出现异常,导致锁无法释放

设置过期时间,自动释放锁

设置过期时间有两种方式:

1. 首先想到通过expire设置过期时间(缺乏原子性:如果在setnx和expire之间出现异常,锁也无法释放)

2. 在set时指定过期时间(推荐)

设置过期时间:

压力测试肯定也没有问题。自行测试

问题:可能会释放其他服务器的锁。

场景:如果业务逻辑的执行时间是7s。执行流程如下

  1. index1业务逻辑没执行完,3秒后锁被自动释放。
  2. index2获取到锁,执行业务逻辑,3秒后锁被自动释放。
  3. index3获取到锁,执行业务逻辑
  4. index1业务逻辑执行完成,开始调用del释放锁,这时释放的是index3的锁,      导致index3的业务只执行1s就被别人释放。

最终等于没锁的情况。

解决:setnx获取锁时,设置一个指定的唯一值(例如:uuid);释放前获取这个值,判断是否自己的锁  

(3.)优化之UUID防误删

问题:删除操作缺乏原子性。

场景:

  1. 1  index1执行删除时,查询到的lock值确实和uuid相等

  1. 2.  index1执行删除前,lock刚好过期时间已到,被redis自动释放

在redis中没有了锁。

  1. 3  index2获取了lock,index2线程获取到了cpu的资源,开始执行方法

      1.4  index1执行删除,此时会把index2的lock删除

index1 因为已经在方法中了,所以不需要重新上锁。index1有执行的权限。index1已经比较完成了,这个时候,开始执行

删除的index2的锁!

(4)优化之LUA脚本保证删除的原子性

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 13:42:03       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 13:42:03       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 13:42:03       57 阅读
  4. Python语言-面向对象

    2024-07-19 13:42:03       68 阅读

热门阅读

  1. 一篇就够mysql高阶知识总结

    2024-07-19 13:42:03       19 阅读
  2. oracle创建服务

    2024-07-19 13:42:03       22 阅读
  3. 音视频中文件的复用和解复用

    2024-07-19 13:42:03       23 阅读
  4. PHP 调用 JD 详情 API 接口:提升电商体验的关键

    2024-07-19 13:42:03       20 阅读
  5. 域名解析出错的解决办法

    2024-07-19 13:42:03       19 阅读
  6. 裸金属服务器

    2024-07-19 13:42:03       22 阅读
  7. [Makefile] 第四章:大型项目中的makefile

    2024-07-19 13:42:03       17 阅读
  8. 前端传值到后端,后端解析为科学计数法

    2024-07-19 13:42:03       16 阅读
  9. 2024 年 6 大 SwaggerHub 替代方案

    2024-07-19 13:42:03       16 阅读
  10. PHP 与 1688 详情 API 接口的完美对接

    2024-07-19 13:42:03       17 阅读
  11. 在状态流图中重用自定义C代码

    2024-07-19 13:42:03       17 阅读