分布式 - 分布式锁

分布式 - 分布式锁

目录

分布式锁流行的三种方式与分析

实现原理

关系型数据库实现

Redis实现

Zookeeper实现

自动释放锁

​​​​​​​Redisson客户端与SpringBoot整合

Curator客户端与SpringBoot整合


分布式锁流行的三种方式与分析

实现原理

关系型数据库实现

  • SELECT lock_name FROM lock WHERE lock_name = 'order' FOR UPDATE;
    • for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级加锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁.即使多个用户对一个表均使用了共享更新,但也不允许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。
    • 也就是说,在业务中,FOR UPDATE 标记该查询已加锁,当前查询上了锁,只能串行,当前操作结束后,其他查询数据的请求才可以执行,利用这一点,将该操作与写操作进行捆绑,即达到分布式锁的目的。

Redis实现

#格式:SETNX KEY VALUE

setnx keyname value


#格式:SET KEY VALUE [EX SECONDS] [PX MILLISECODS] [NX|XX]

set keyname value ex 100 nx
  • setnx命令,如果有该key值,则设置失败;没有该key设置成功。但setnx命令没有过期时间
  • 需要额外对key设置过期时间,但是这是两种不同意义的操作操作,不能保证其原子性
  • SET KEY VALUE [EX SECONDS] [PX MILLISECODS] [NX|XX]”与“SETNX KEY VALUE”意义基本相通,只是多了个过期时间
  • 也就是说,在业务中,先为一个指定的key赋值,如果成功赋值,就代表抢占了锁,与写操作进行捆绑,事务结束后释放锁即可,即使服务宕机没来得及释放锁,缓存过期后也会自动释放。

Zookeeper实现

ZooKeeper 的分层命名空间

  •  Zookeeper临时节点是有序的且不允许有父节点,watch可以对节点监视,而且居3.6.0 中的新功能:客户端还可以在 znode 上设置永久的递归监​​视,这些监视在触发时不会被删除,并且会以递归方式触发注册的 znode 以及任何子 znode 上的更改
  • 也就是说,在业务中,执行时先到 Zookeeper 创建一个父节点,区分锁的用途,然后在该节点下创建临时节点,临时节点都是有序的,watch特性获取该父节点下的所有子节点,对比自己创建的节点在所有节点中是否是第一个,是就执行业务,否就等watch监视特性监视前一个节点,当前一个节点消失,自己是第一个节点时执行,执行时与写操作捆绑,执行结束后删除节点。

自动释放锁

  • 例如 redis 与 Zookeeper 封装获取锁的实体类,获取锁的实体类实现 AutoCloseable接口,接口中就一个 close 关闭方法,只需在 close 中补全自己的逻辑操作即可
  • 表示该对象生命周期结束,自动执行关闭操作
  • AutoCloseable类解释:一个可能持有资源(例如文件或套接字句柄)直到关闭的对象。 当退出在资源规范标头中声明了对象的-with-resources 块时,将自动调用对象的close()方法。这种构造确保及时释放,避免资源耗尽异常和否则可能发生的错误。AutoCloseabletry,当然也可以封装IO操作

​​​​​​​Redisson客户端与SpringBoot整合

Redisson官方文档

  • maven依赖
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
  • 方法一
    • application.yml
  redis:
    host: 192.168.50.201
    port: 6379
    timeout:  1000
    database: 0
    password: chenyb111
    jedis:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0
  • 方法二
    • application.yml
spring:
  redis:
    redisson:
      # 配置单点模式
      config: classpath:redisson.yml
    jedis:
      pool:
        max-active: 8  #最大连接数
        max-wait: -1 #最大阻塞等待时间(负数表示没限制)
        max-idle: 8 #最大空闲

  •  redisson.yml
# 单节点配置
singleServerConfig:
  # 连接空闲超时,单位:毫秒
  idleConnectionTimeout: 10000
  # 连接超时,单位:毫秒
  connectTimeout: 10000
  # 命令等待超时,单位:毫秒
  timeout: 3000
  # 命令失败重试次数,如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。
  # 如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
  retryAttempts: 3
  # 命令重试发送时间间隔,单位:毫秒
  retryInterval: 1500
#  # 重新连接时间间隔,单位:毫秒
#  reconnectionTimeout: 3000
#  # 执行失败最大次数
#  failedAttempts: 3
  # 密码
  password: 
  # 单个连接最大订阅数量
  subscriptionsPerConnection: 5
  # 客户端名称
  clientName: null
#  # 节点地址
  address: redis://ip
  # 发布和订阅连接的最小空闲连接数
  subscriptionConnectionMinimumIdleSize: 1
  # 发布和订阅连接池大小
  subscriptionConnectionPoolSize: 50
  # 最小空闲连接数
  connectionMinimumIdleSize: 32
  # 连接池大小
  connectionPoolSize: 64
  # 数据库编号
  database: 0
  # DNS监测时间间隔,单位:毫秒
  dnsMonitoringInterval: 5000

  •  对象注入即可
@Autowired
privete RedissonClient redissonClient

public viod redisLockDemo (){


    //获取锁
    redissonClient.getLock("keyName").tryLock(0L,-1L, TimeUnit.SECONDS);
    
    //释放锁
    redissonClient.getLock("keyName").unlock();
}

Curator客户端与SpringBoot整合

Curator官方文档

  • maven依赖
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>5.2.0</version>
</dependency>
  • 创建对象即可
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3)
CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", retryPolicy);


client.start();
InterProcessMutex lock = new InterProcessMutex(client, "ZK父级目录");


if ( lock.acquire("有效时间", "TimeUnit.SECONDS时间单位") ) 
{
    try 
    {    //获得锁
        // do some work inside of the critical section here
    }
    finally
    {

        //释放锁
        lock.release();
    }
}
  • 可以将创建client用Bean封装
    • @Autowired注入即可

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值