java 分布式锁

公司项目有一个功能需要用到分布式锁功能,一开始使用redis(redisson)实现分布式锁,后来比较以后使用zookeeper(spring-integration-zookeeper),这边做下总结:

分布式的 CAP 理论告诉我们:任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。

基于 CAP理论,很多系统在设计之初就要对这三者做出取舍。

目前常见的三种分布式锁:

1 基于数据库实现的分布式锁

a 乐观锁:基于表主键唯一做分布式锁

b 悲观锁:基于数据库排他锁做分布式锁,for update,InnoDB 引擎在加锁的时候,只有通过索引进行检索的时候才会使用行级锁,否则会使用表级锁。mysql数据库的默认引擎(5.1版本之后)是InnoDB,所以这块要多注意

2 基于缓存的分布式锁

基于 redis的 setnx()、expire() 方法做分布式锁:

  setnx:SET if Not Exists,其主要有两个参数 setnx(key, value)。该方法是原子的,如果 key 不存在,则设置当前 key 成功,返回 1;如果当前 key 已经存在,则设置当前 key 失败,返回 0

  expire:设置过期时间,要注意的是 setnx 命令不能设置 key 的超时时间,只能通过 expire() 来对 key 设置

基于 REDISSON 做分布式锁:redisson 是 redis 官方的分布式锁组件,里面有封装好的api

3 基于Zookeeper实现的分布式锁

ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名:

  a 基于开源库Curator,它是一个ZooKeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁

  b 基于spring-integration-zookeeper

几种方案的比较

从理解的难易程度角度(从低到高)

数据库 > 缓存 > Zookeeper

从实现的复杂性角度(从低到高)

Zookeeper > 缓存 > 数据库

从性能角度(从高到低)

缓存 > Zookeeper >= 数据库

从可靠性角度(从高到低)

Zookeeper > 缓存 > 数据库

4 还有一种基于 Consul 做分布式锁:

出自程序员DD https://blog.didispace.com/spring-cloud-consul-lock-and-semphore/

基于Consul的分布式锁主要利用Key/Value存储API中的acquire和release操作来实现。acquire和release操作是类似Check-And-Set的操作:

  • acquire操作只有当锁不存在持有者时才会返回true,并且set设置的Value值,同时执行操作的session会持有对该Key的锁,否则就返回false
  • release操作则是使用指定的session来释放某个Key的锁,如果指定的session无效,那么会返回false,否则就会set设置Value值,并返回true

具体实现中主要使用了这几个Key/Value的API:

 项目组综合比较之后倾向于使用Spring Integration 优雅的实现分布式锁,最终使用spring-integration-zookeeper

Spring Integration在基于Spring的应用程序中实现轻量级消息传递,并支持通过声明适配器与外部系统集成。 Spring Integration的主要目标是提供一个简单的模型来构建企业集成解决方案,同时保持关注点的分离,这对于生成可维护,可测试的代码至关重要。我们熟知的 Spring Cloud Stream的底层就是Spring Integration。

Spring Integration提供的全局锁目前为如下存储提供了实现:

  • Gemfire
  • JDBC
  • Redis
  • Zookeeper
原文地址:https://www.cnblogs.com/hzzjj/p/14727441.html