zoukankan      html  css  js  c++  java
  • 分布式锁

    1.分布式锁

     https://www.cnblogs.com/liuyang0/p/6744076.html

    https://www.cnblogs.com/austinspark-jessylu/p/8043726.html

     

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

    1). 多任务环境中才需要;

    2). 任务都需要对一个共享资源进行写操作;

    3).对资源的访问是互斥的;

    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来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推...

  • 相关阅读:
    Advanced Installer文件和文件夹页面中的临时文件操作
    celery使用方法
    网站高并发之道
    大话程序猿眼里的高并发
    StringTokenizer类的使用
    linux下查看最消耗CPU、内存的进程
    分享10条PHP性能优化的小技巧,帮助你更好的用PHP开发:
    json 除去转义字符以及查看json错误
    关于 redis、memcache、mongoDB 的对比
    QPS 与 TPS 简介
  • 原文地址:https://www.cnblogs.com/newlangwen/p/8413267.html
Copyright © 2011-2022 走看看