ava世界的”半壁江山”——Spring早就提供了分布式锁的实现。早期,分布式锁的相关代码存在于Spring Cloud的子项目Spring Cloud Cluster中,后来被迁到Spring Integration中。
Spring Cloud Cluster的GitHub:/spring-cloud/spring-cloud-cluster,里面有些用例,以及基于ETCD、hazelcast的分布式锁实现值得一看。Spring Integration的GitHub:GitHub - spring-projects/spring-integration: Spring Integration provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns (EIP)
TIPS
这就是明明Spring Cloud官方说自己实现了
Global Locks
,但又无法找到任何相关文档的原因——人家早把相关代码搬迁到Spring Integration了。
可能有不少童鞋对Spring Integration不是很熟悉,简单介绍一下——官方说法,这是一个企业集成模式
的实现;通俗地说,Spring Integration的定位是一个轻量级的ESB,尽管它做了很多ESB不做的事情。顺便说一下,Spring Cloud Stream的底层也是Spring Integration。
Spring Integration提供的全局锁目前为如下存储提供了实现:
GemfireJDBCRedisZookeeper
它们使用相同的API抽象——这正是Spring最擅长的。这意味着,不论使用哪种存储,你的编码体验是一样的,有一天想更换实现,只需要修改依赖和配置就可以了,无需修改代码。
TIPS
实现无关性:举个例子,你目前有一个基于Redis的分布式锁,但有一天想讲存储改为Consul。此时,统一的API至关重要——我相信你不会希望仅仅是修改了分布式锁的存储,就得让开发把相关代码翻新一遍。
大学的时候,不也讲过面向接口编程的重要性嘛。
因此,即使Spring Integration没有为您使用的存储提供实现(例如Consul),你也应该基于Spring Integration的API去开发。这样未来的某一天,一旦Spring Integration为你的存储提供支持,你就可以无痛切换啦。
编码
下面以Redis为例,讲解Spring Integration里面如何使用分布式锁。
加依赖
写配置:
写代码:初始化
强烈建议阅读一下org.springframework.integration.redis.util.RedisLockRegistry
的注释,它详细描述了该类的特性,例如可重入性以及锁在Redis中如何存储等。
写代码:测试
测试
启动1个实例,访问http://localhost:8080/test
,会看到类似如下的日志:
启动2个实例,并迅速访问两个实例的/test
端点,会在第二个实例上看到类似如下日志:
说明第二个实例没有拿到锁,证明了分布式锁的存在。