您现在的位置是:首页 > 文章详情

使用redis和zookeeper实现分布式锁

日期:2018-11-27点击:735

1.分布式锁


分布式锁一般用在分布式系统或者多个应用中,用来控制同一任务是否执行或者任务的执行顺序。在项目中,部署了多个tomcat应用,在执行定时任务时就会遇到同一任务可能执行多次的情况,我们可以借助分布式锁,保证在同一时间只有一个tomcat应用执行了定时任务。


2.分布式锁的实现方式


          1.使用redis的setnx()和expire()

          2.使用redis的getset()

          3.使用zookeeper的创建节点node

          4.使用zookeeper的创建临时序列节点


3.使用redis的setnx()和expire()来实现分布式锁

setnx(key,value) 如果key不存在,设置为当前key的值为value;如果key存在,直接返回。 expire()来设置超时时间

定义注解类:

@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Lockable{     // redis缓存key     String key();     // redis缓存key中的数据     String value() default "";     // 过期时间(秒),默认为一分钟     long expire() default 60; }

定时任务增加注解@Lockable:

 @Lockable(key = "DistributedLock:dealExpireRecords")  public void dealExpireRecords() {  }

定义一个aop切面LockAspect,使用@Around处理所有注解为@Lockable的方法,通过连接点确认此注解是用在方法上,通过方法获取注解信息,使用setIfAbsent来判断是否获取分布式锁,如果没有获取分布式锁,直接返回;如果获取到分布式锁,通过expire设置过期时间,并调用指定方法。

@Component @Slf4j @Aspect public class LockAspect {     @Autowired     private RedisTemplate redisTemplate;     @Around("@annotation(com.records.aop.Lockable)")     public Object distributeLock(ProceedingJoinPoint pjp) {         Object resultObject = null;         //确认此注解是用在方法上         Signature signature = pjp.getSignature();         if (!(signature instanceof MethodSignature)) {             log.error("Lockable is method annotation!");             return resultObject;         }         MethodSignature methodSignature = (MethodSignature) signature;         Method targetMethod = methodSignature.getMethod();         //获取注解信息         Lockable lockable = targetMethod.getAnnotation(Lockable.class);         String key = lockable.key();         String value = lockable.value();         long expire = lockable.expire();         // 分布式锁,如果没有此key,设置此值并返回true;如果有此key,则返回false         boolean result = redisTemplate.boundValueOps(key).setIfAbsent(value);         if (!result) {             //其他程序已经获取分布式锁             return resultObject;         }         //设置过期时间,默认一分钟         redisTemplate.boundValueOps(key).expire(expire, TimeUnit.SECONDS);         try {             resultObject = pjp.proceed(); //调用对应方法执行         } catch (Throwable throwable) {             throwable.printStackTrace();         }         return resultObject;     } }

4.使用redis的getset()来实现分布式锁


此方法使redisTemplate.boundValueOps(key).getAndSet(value)的方法,如果返回空,表示获取了分布式锁;如果返回不为空,表示分布式锁已经被其他程序占用


5.使用zookeeper的创建节点node


使用zookeeper创建节点node,如果创建节点成功,表示获取了此分布式锁;如果创建节点失败,表示此分布式锁已经被其他程序占用(多个程序同时创建一个节点node,只有一个能够创建成功)


6.使用zookeeper的创建临时序列节点


使用zookeeper创建临时序列节点来实现分布式锁,适用于顺序执行的程序,大体思路就是创建临时序列节点,找出最小的序列节点,获取分布式锁,程序执行完成之后此序列节点消失,通过watch来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推......


原文链接:https://blog.roncoo.com/article/129138
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章