一、概述
之前的文章中,有提到过用redission组件实现分布式锁,现实上除了几种经常被采用的,如:
基于关系型数据库
基于Redission组件
基于Apache Curator组件,通过Zk的临时顺序节点模子实现的
除了以上比力常用的方式,这篇文章简单说一下感觉被大伙儿忽略的一种实现方式,那就是通过 Spring Integration 这个新兴组件来实现,现实上它的焦点目标就是提供一个简单的模子来实现复杂的企业集成解决方案,为基于Spring的应用添加异步的、消息驱动的举动,让Spring用户可以直观的、增量的采用,更详细的内容可以通过官网深入相识。Spring Integration提供的全局锁现在为如下存储提供了实现:
Redis
Zookeeper
Gemfire
JDBC
它们利用类似的API抽象,这意味着,不论利用哪种存储,你的编码体验都是一样的。试想一下你当前项目是基于zookeeper实现的分布式锁,后续由于特殊需求厘革,你想换成redis的实现,我们只需要修改相干依赖和设置就可以了,无需修改代码。
二、API阐明
在利用 Spring Integration 实现分布式锁之前,我们需要重点关注几个方法:
lock():加锁,如果已经被其他线程锁住或者当火线程不能获取锁则壅闭;
lockInterruptibly():加锁,除非当火线程被打断;
tryLock():尝试加锁,如果已经有其他锁锁住,获取当火线程不能加锁,则返回false,加锁失败;加锁成功则返回true;
tryLock(long time, TimeUnit unit):尝试在指定时间内加锁,如果已经有其他锁锁住,获取当火线程不能加锁,则返回false,加锁失败;加锁成功则返回true;
unlock():R解锁。
三、案例
采用Redis和Zookeeper可能各人更密切,就以这俩为例,JDBC和Gemfire可以本身玩玩,Gemfire实在我也不会,嗯:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-zookeeper</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies> 复制代码
# 端口随意改几个,分别启动,模拟多个实例 server.port=12010 spring.redis.host=192.168.56.10 复制代码
package com.ideax.lock.plus.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.integration.redis.util.RedisLockRegistry; /** * Redis锁配置类 * * @author zhangxs **/ @Configuration public class RedisLockConfiguration { @Bean public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) { return new RedisLockRegistry(redisConnectionFactory, "redis-lock"); } } 复制代码
package com.ideax.lock.plus.config; import org.apache.curator.framework.CuratorFramework; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.zookeeper.config.CuratorFrameworkFactoryBean; import org.springframework.integration.zookeeper.lock.ZookeeperLockRegistry; /** * Zk锁配置类 * * @author zhangxs **/ @Configuration public class ZkLockConfiguration { @Bean public CuratorFrameworkFactoryBean curatorFrameworkFactoryBean() { return new CuratorFrameworkFactoryBean("10.18.28.115:2181"); } @Bean public ZookeeperLockRegistry zookeeperLockRegistry(CuratorFramework curatorFramework) { return new ZookeeperLockRegistry(curatorFramework, "/zookeeper-lock"); } } 复制代码
package com.ideax.lock.plus.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.redis.util.RedisLockRegistry; import org.springframework.integration.zookeeper.lock.ZookeeperLockRegistry; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; /** * 锁测试接口 * * @author zhangxs **/ @RestController @RequestMapping("lock") public class LockController { @Autowired private RedisLockRegistry redisLockRegistry; @Autowired private ZookeeperLockRegistry zookeeperLockRegistry; @GetMapping("redis") public void redisDual() { businessMethod(redisLockRegistry.obtain("redis")); } @GetMapping("zk") public void zkDual() { businessMethod(zookeeperLockRegistry.obtain("zookeeper")); } protected void businessMethod(Lock lock) { try { if (lock.tryLock(3, TimeUnit.SECONDS)) { System.out.println("锁对象就绪..."); TimeUnit.SECONDS.sleep(5); } } catch (InterruptedException ie) { System.out.println("锁获取失败..."); ie.printStackTrace(); } finally { lock.unlock(); } } } 复制代码
1、短时间内对12008和12009端口下redis接口发出哀求:
2、…12008/lock/redis的哀求先拿到锁:
3、…12009/lock/redis的哀求获取锁失败:
由此可证实,Redis分布式锁见效。
4、短时间内对12008和12009端口下zk接口发出哀求:
5、…12009/lock/zk的哀求先拿到锁:
6、…12010/lock/zk的哀求获取锁失败:
由此可证实,Zookeeper分布式锁见效。
四、总结
个人非常保举这种实现方式,更加机动。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!