• 使用redis,zookeeper实现分布式锁


    1.分布式锁

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

    2.分布式锁的实现方式

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

              2.使用redis的getset()

              3.使用zookeeper的创建节点node

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

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

    [java] view plain copy
     
    1. setnx(key,value) 如果key不存在,设置为当前key的值为value;如果key存在,直接返回。  
    2. expire()来设置超时时间  

    定义注解类:

    [java] view plain copy
     
    1. @Target({ElementType.METHOD})  
    2. @Retention(RetentionPolicy.RUNTIME)  
    3. public @interface Lockable{  
    4.     // redis缓存key  
    5.     String key();  
    6.     // redis缓存key中的数据  
    7.     String value() default "";  
    8.     // 过期时间(秒),默认为一分钟  
    9.     long expire() default 60;  
    10. }  

    定时任务增加注解@Lockable:

    [java] view plain copy
     
    1.  @Lockable(key = "DistributedLock:dealExpireRecords")  
    2.  public void dealExpireRecords() {  
    3.  }  

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

    [java] view plain copy
     
    1. @Component  
    2. @Slf4j  
    3. @Aspect  
    4. public class LockAspect {  
    5.   
    6.     @Autowired  
    7.     private RedisTemplate redisTemplate;  
    8.   
    9.     @Around("@annotation(com.records.aop.Lockable)")  
    10.     public Object distributeLock(ProceedingJoinPoint pjp) {  
    11.         Object resultObject = null;  
    12.   
    13.         //确认此注解是用在方法上  
    14.         Signature signature = pjp.getSignature();  
    15.         if (!(signature instanceof MethodSignature)) {  
    16.             log.error("Lockable is method annotation!");  
    17.             return resultObject;  
    18.         }  
    19.   
    20.         MethodSignature methodSignature = (MethodSignature) signature;  
    21.         Method targetMethod = methodSignature.getMethod();  
    22.   
    23.         //获取注解信息  
    24.         Lockable lockable = targetMethod.getAnnotation(Lockable.class);  
    25.         String key = lockable.key();  
    26.         String value = lockable.value();  
    27.         long expire = lockable.expire();  
    28.   
    29.         // 分布式锁,如果没有此key,设置此值并返回true;如果有此key,则返回false  
    30.         boolean result = redisTemplate.boundValueOps(key).setIfAbsent(value);  
    31.         if (!result) {  
    32.             //其他程序已经获取分布式锁  
    33.             return resultObject;  
    34.         }  
    35.   
    36.         //设置过期时间,默认一分钟  
    37.         redisTemplate.boundValueOps(key).expire(expire, TimeUnit.SECONDS);  
    38.   
    39.         try {  
    40.             resultObject = pjp.proceed(); //调用对应方法执行  
    41.         } catch (Throwable throwable) {  
    42.             throwable.printStackTrace();  
    43.         }  
    44.         return resultObject;  
    45.     }  
    46. }  

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

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

    5.使用zookeeper的创建节点node

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

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

    使用zookeeper创建临时序列节点来实现分布式锁,适用于顺序执行的程序,大体思路就是创建临时序列节点,找出最小的序列节点,获取分布式锁,程序执行完成之后此序列节点消失,通过watch来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推......更多资源共享尽在Redis缓存技术交流组:288724942

  • 相关阅读:
    eclipse安装Genymotion插件
    [Eclipse插件] 安装和使用JD-Eclipse插件
    [Eclipse插件] Eclipse中如何安装和使用GrepCode插件
    [Android Studio] Android Studio如何删除module(转载)
    前端html基本标签
    python实现简单FTP
    文件的md5计算
    suprocess模块
    几个小例子
    configparser模块
  • 原文地址:https://www.cnblogs.com/xifenglou/p/8854912.html
Copyright © 2020-2023  润新知