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

    1、分布式锁目前可能存在的问题(基于redis客户端jedis)
    加锁: set key value [expiration EX seconds|PX milliseconds] [NX|XX]
    该加锁方式是从Redis2.8之后便支持这种原子性加锁方式,之前设置setnx和设置过期时间不是原子性的。

    String ret = jedis.set(getKey(key), 
                           new CacheEntity<T>(serializable, version, System.currentTimeMillis()).getBytes(), 
                           "NX".getBytes(),
                           "EX".getBytes(), 
                           expireSecond);
    return StringUtils.equals("OK", ret);

    参数解释如下:

    • EX second :设置key的过期时间为 second 秒
    • PX millisecond :设置key的过期时间为 millisecond 毫秒
    • NX :只在key不存在时,才对key进行设置操作
    • XX :只在key已经存在时,才对key进行设置操作

    解锁

    ret = jedis.del(getKey(key));

    使用

    if (!lock.tryLockXxx(key)) {
      return ;
    }
    try {
      // TODO
    } finally { lock.unlockXxx(key); }

    基于jedis实现的分布式锁缺点

    • 不支持重入
    • 加锁时设置的value无意义
    • 锁超时时间不能自动续期,所以不好取值
    • 锁超时时间 > 业务执行时间,业务正常执行完成释放锁,没问题,业务节点奔溃,尚未释放锁,会导致其他业务系统线程最多等待整个超时时间
    • 锁超时时间 < 业务执行时间,锁超时自动释放,业务执行完成,再执行unlock,可能会错误的解锁
    • 加锁key设置在Master节点上,尚未同步到slave就宕机了,salve提升为新的master,没有上一个锁的信息,其他线程依然可以获取同一个key的锁

    2、Redisson客户端优势

    • 支持 SSL
    • 线程安全的实现
    • Reactive Streams API
    • 异步 API
    • 异步连接池
    • Lua 脚本
    • 分布式Java对象
    • Object holder, Binary stream holder, Geospatial holder, BitSet, AtomicLong, AtomicDouble, PublishSubscribe, Bloom filter, HyperLogLog
    • 分布式Java集合
    • Map, Multimap, Set, List, SortedSet, ScoredSortedSet, LexSortedSet, Queue, Deque, Blocking Queue, Bounded Blocking Queue, Blocking Deque, Delayed Queue, Priority Queue, Priority Deque
    • 分布式锁和同步器
    • Lock, FairLock, MultiLock, RedLock, ReadWriteLock, Semaphore, PermitExpirableSemaphore, CountDownLatch

    Redisson的基本用法参考这篇博客《基于redission的分布式锁

    自动续期源码:

    // tryAcquireAsync -> scheduleExpirationRenewal -> renewExpiration
    // 自动续期
    private void renewExpiration() {
        ...
    
        Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
            @Override
            public void run(Timeout timeout) throws Exception {
                ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());
                if (ent == null) {
                    return;
                }
                Long threadId = ent.getFirstThreadId();
                if (threadId == null) {
                    return;
                }
    
                RFuture<Boolean> future = renewExpirationAsync(threadId);
                future.onComplete((res, e) -> {
                    if (e != null) {
                        log.error("Can't update lock " + getRawName() + " expiration", e);
                        EXPIRATION_RENEWAL_MAP.remove(getEntryName());
                        return;
                    }
    
                    if (res) {
                        // reschedule itself
                        renewExpiration();
                    }
                });
            }
        }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);
    
        ...
    }

    真正执行续期的lua脚本

    protected RFuture<Boolean> renewExpirationAsync(long threadId) {
        return evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
                              "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
                              "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                              "return 1; " +
                              "end; " +
                              "return 0;",
                              Collections.singletonList(getRawName()),
                              internalLockLeaseTime, getLockName(threadId));
    }

    Netty中的时间轮算法 HashedWheelTimer

     

    郭慕荣博客园
  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/jelly12345/p/14944612.html
Copyright © 2011-2022 走看看