• Redis 实现分布式锁

    • 单机模式的Redis分布式锁
    • 集群模式的Redis分布式锁 Redlock

Redis 实现分布式锁

单机模式的Redis分布式锁

  • 优缺点

    • 实现比较轻,大多数时候能满足需求;因为是单机单实例部署,如果redis服务宕机,那么所有需要获取分布式锁的地方均无法获取锁,将全部阻塞,需要做好降级处理。
    • 当锁过期后,执行任务的进程还没有执行完,但是锁因为自动过期已经解锁,可能被其它进程重新加锁,这就造成多个进程同时获取到了锁,这需要额外的方案来解决这种问题。
  • 实现代码
      import redis.clients.jedis.Jedis;import java.util.Collections;public class JedisDistributedLock {private static final String LOCK_SUCCESS = "OK";private static final Long RELEASE_SUCCESS = 1L;private static final String SET_IF_NOT_EXIST = "NX";private static final String SET_WITH_EXPIRE_TIME = "PX";// 获取锁,不设置超时时间public static boolean getLock(Jedis jedis, String lockKey, String requestId){String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST);if(LOCK_SUCCESS.equals(result)){return true;}return false;}// 获取锁, 设置超时时间,单位为毫秒public static boolean getLock(Jedis jedis, String lockKey, String requestId, Long expireTime){/*** jedis.set(key, value, nxxx, expx, time)** Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1* GB).* @param key* @param value* @param NXXX NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key if it already exist.* @param EXPX EX|PX, expire time units: EX = seconds; PX = milliseconds** @return Status code reply set成功,返回 OK*/String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);if(LOCK_SUCCESS.equals(result)){return true;}return false;}//释放锁public static boolean releaseLock(Jedis jedis, String lockKey, String requestId){// Lua脚本String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));if(RELEASE_SUCCESS.equals(result)){return true;}return false;}}
    

集群模式的Redis分布式锁 Redlock

  • 优缺点

    • Redlock是Redis的作者antirez给出的集群模式的Redis分布式锁,它基于N个完全独立的Redis节点
    • 部分节点宕机,依然可以保证锁的可用性
    • 当某个节点宕机后,又立即重启了,可能会出现两个客户端同时持有同一把锁,如果节点设置了持久化,出现这种情况的几率会降低
    • 和单机模式Redis锁相比,实现难度要大一些
  • 实现代码

    • 搭建redis集群
    # 安装指定版本的redis
    cd /opt
    wget http://download.redis.io/releases/redis-3.2.8.tar.gz
    tar xzf redis-3.2.8.tar.gz && rm redis-3.2.8.tar.gz
    cd redis-3.2.8
    make
    
    # 构建redis集群
    cd
    mkdir cluster-test
    cd cluster-test
    mkdir conf logs bin
    # 拷贝客户端服务器文件
    rsync -avp /opt/redis-3.2.8/src/redis-server bin/
    rsync -avp /opt/redis-3.2.8/src/redis-cli bin/
    # 配置文件
    for i in 7000 7001 7002 7003 7004 7005; do
    cat << EOF > conf/${i}.conf
    port ${i}
    cluster-enabled yes
    cluster-config-file nodes-${i}.conf
    cluster-node-timeout 5000
    appendonly yes
    logfile "logs/${i}.log"
    appendfilename "appendonly-${i}.aof"
    EOF
    done
    # 启动
    cd ${HOME}/cluster-test
    for i in 7000 7001 7002 7003 7004 7005; do
    ./bin/redis-server ./conf/${i}.conf &
    done
    # 创建集群
    sudo apt-get install -y ruby rubygems
    gem install redis
    cd /opt/redis-3.2.8/src/
    ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
    # 测试
    cd ${HOME}/cluster-test/
    ./bin/redis-cli -c -p 7000 cluser nodes
    # 停止
    #cd ${HOME}/cluster-test
    #for i in 7000 7001 7002 7003 7004 7005; do
    #./bin/redis-cli -p ${i} shutdown && echo "redis ${i} 已停止"
    #done
    

    脚本执行后,出现如下日志,说明集群搭建成功

    >>> Creating cluster
    >>> Performing hash slots allocation on 6 nodes...
    Using 3 masters:
    127.0.0.1:7000
    127.0.0.1:7001
    127.0.0.1:7002
    Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
    Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
    Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
    M: d0e3588845a839052d9e611853740edd3b348966 127.0.0.1:7000
    slots:0-5460 (5461 slots) master
    M: 4f5518e78c1ea1c25bab0d0147f12c0281fd5f96 127.0.0.1:7001
    slots:5461-10922 (5462 slots) master
    M: 5724fb03c4527389be0d556c5dc5419a12d367c5 127.0.0.1:7002
    slots:10923-16383 (5461 slots) master
    S: 1206f7a76b8050b10e2e602fad422faee95efdb5 127.0.0.1:7003
    replicates d0e3588845a839052d9e611853740edd3b348966
    S: 8f421f529c86cefbf033e1e3a1687a9767802bd2 127.0.0.1:7004
    replicates 4f5518e78c1ea1c25bab0d0147f12c0281fd5f96
    S: d94710251235efde7da4073cc4ff104d9298bd0f 127.0.0.1:7005
    replicates 5724fb03c4527389be0d556c5dc5419a12d367c5
    Can I set the above configuration? (type 'yes' to accept): yes
    >>> Nodes configuration updated
    >>> Assign a different config epoch to each node
    >>> Sending CLUSTER MEET messages to join the cluster
    Waiting for the cluster to join...
    >>> Performing Cluster Check (using node 127.0.0.1:7000)
    M: d0e3588845a839052d9e611853740edd3b348966 127.0.0.1:7000
    slots:0-5460 (5461 slots) master
    1 additional replica(s)
    S: 8f421f529c86cefbf033e1e3a1687a9767802bd2 127.0.0.1:7004
    slots: (0 slots) slave
    replicates 4f5518e78c1ea1c25bab0d0147f12c0281fd5f96
    S: 1206f7a76b8050b10e2e602fad422faee95efdb5 127.0.0.1:7003
    slots: (0 slots) slave
    replicates d0e3588845a839052d9e611853740edd3b348966
    M: 4f5518e78c1ea1c25bab0d0147f12c0281fd5f96 127.0.0.1:7001
    slots:5461-10922 (5462 slots) master
    1 additional replica(s)
    S: d94710251235efde7da4073cc4ff104d9298bd0f 127.0.0.1:7005
    slots: (0 slots) slave
    replicates 5724fb03c4527389be0d556c5dc5419a12d367c5
    M: 5724fb03c4527389be0d556c5dc5419a12d367c5 127.0.0.1:7002
    slots:10923-16383 (5461 slots) master
    1 additional replica(s)
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    
    • redis-cluster简单集群示例图
    • 使用Redission构建redLock

    Redis集群使用分片的方式保存键值对,redis-cluster采用slot(槽)的概念,一共16384个槽位,分布在集群中的所有master实例上。保存数据时,直接对key值做CRC16校验后得到的校验值对16384取模,将键值对存储到对应的槽位所在的实例上。

    import org.redisson.Redisson;
    import org.redisson.api.RAtomicLong;
    import org.redisson.api.RedissonClient;
    import org.redisson.config.Config;/**
    * Created by Haiyoung on 2018/8/11.
    */
    public class RedissonManager {private static final String RAtomicName = "genId_";private static Config config = new Config();private static RedissonClient redisson = null;public static void init(){try{config.useClusterServers().setScanInterval(200000)//设置集群状态扫描间隔.setMasterConnectionPoolSize(10000)//设置对于master节点的连接池中连接数最大为10000.setSlaveConnectionPoolSize(10000)//设置对于slave节点的连接池中连接数最大为500.setIdleConnectionTimeout(10000)//如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。.setConnectTimeout(30000)//同任何节点建立连接时的等待超时。时间单位是毫秒。.setTimeout(3000)//等待节点回复命令的时间。该时间从命令发送成功时开始计时。.setRetryInterval(3000)//当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。.addNodeAddress("redis://127.0.0.1:7000","redis://127.0.0.1:7001","redis://127.0.0.1:7002","redis://127.0.0.1:7003","redis://127.0.0.1:7004","redis://127.0.0.1:7005");redisson = Redisson.create(config);RAtomicLong atomicLong = redisson.getAtomicLong(RAtomicName);atomicLong.set(1);//自增设置为从1开始}catch (Exception e){e.printStackTrace();}}public static RedissonClient getRedisson(){if(redisson == null){RedissonManager.init(); //初始化}return redisson;}/** 获取redis中的原子ID */public static Long nextID(){RAtomicLong atomicLong = getRedisson().getAtomicLong(RAtomicName);atomicLong.incrementAndGet();return atomicLong.get();}
    }
    
    import org.redisson.api.RLock;
    import org.redisson.api.RedissonClient;import java.util.concurrent.TimeUnit;/**
    * Created by Haiyoung on 2018/8/11.
    */
    public class DistributedRedisLock {private static RedissonClient redisson = RedissonManager.getRedisson();private static final String LOCK_TITLE = "redisLock_";public static void acquire(String lockName){String key = LOCK_TITLE + lockName;RLock mylock = redisson.getLock(key);mylock.lock(2, TimeUnit.MINUTES); //lock提供带timeout参数,timeout结束强制解锁,防止死锁System.err.println("======lock======"+Thread.currentThread().getName());}public static void release(String lockName){String key = LOCK_TITLE + lockName;RLock mylock = redisson.getLock(key);mylock.unlock();System.err.println("======unlock======"+Thread.currentThread().getName());}public static void main(String[] args){for (int i = 0; i < 3; i++) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {try {String key = "test123";DistributedRedisLock.acquire(key);Thread.sleep(1000); //获得锁之后可以进行相应的处理System.err.println("======获得锁后进行相应的操作======");DistributedRedisLock.release(key);System.err.println("=============================");} catch (Exception e) {e.printStackTrace();}}});t.start();}}
    }
    

    执行main函数,进行测试:

    //建立的集群关系如下所示:
    //可以看到集群关系以及槽位分配信息
    12:41:14.749 [redisson-netty-1-7] DEBUG org.redisson.cluster.ClusterConnectionManager - cluster nodes state from 127.0.0.1/127.0.0.1:7001:
    d0e3588845a839052d9e611853740edd3b348966 127.0.0.1:7000 master - 0 1539319273461 1 connected 0-5460
    d94710251235efde7da4073cc4ff104d9298bd0f 127.0.0.1:7005 slave 5724fb03c4527389be0d556c5dc5419a12d367c5 0 1539319273963 6 connected
    5724fb03c4527389be0d556c5dc5419a12d367c5 127.0.0.1:7002 master - 0 1539319274465 3 connected 10923-16383
    8f421f529c86cefbf033e1e3a1687a9767802bd2 127.0.0.1:7004 slave 4f5518e78c1ea1c25bab0d0147f12c0281fd5f96 0 1539319272458 5 connected
    1206f7a76b8050b10e2e602fad422faee95efdb5 127.0.0.1:7003 slave d0e3588845a839052d9e611853740edd3b348966 0 1539319272961 4 connected
    4f5518e78c1ea1c25bab0d0147f12c0281fd5f96 127.0.0.1:7001 myself,master - 0 0 2 connected 5461-10922
    
    //加锁解锁过程
    ======lock======Thread-2
    10:27:50.086 [redisson-netty-1-6] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=1, freeSubscribeConnectionsCounter=50, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@788625756 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x9109c84f, L:/127.0.0.1:49276 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:50.096 [Thread-1] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:50.102 [redisson-netty-1-6] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=32, freeConnectionsCounter=10000, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@615544583 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x088086f4, L:/127.0.0.1:49194 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:50.120 [Thread-1] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:50.120 [Thread-3] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:50.121 [Thread-1] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@1475932758 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x37cce38a, L:/127.0.0.1:49230 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:50.121 [Thread-3] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=30, freeConnectionsCounter=9998, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@1231431314 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0xea1b90d2, L:/127.0.0.1:49286 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:50.126 [redisson-netty-1-1] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@1475932758 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x37cce38a, L:/127.0.0.1:49230 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:50.127 [redisson-netty-1-1] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=32, freeConnectionsCounter=10000, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@1231431314 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0xea1b90d2, L:/127.0.0.1:49286 - R:127.0.0.1/127.0.0.1:7002]]
    ======获得锁后进行相应的操作======
    10:27:51.081 [Thread-2] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:51.082 [Thread-2] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;, 2, redisLock_test123, redisson_lock__channel:{redisLock_test123}, 0, 30000, 20e96666-d967-4d3c-ac94-abeb14493160:21] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@697105324 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x3b2eb2ff, L:/127.0.0.1:49244 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:51.086 [redisson-netty-1-5] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;, 2, redisLock_test123, redisson_lock__channel:{redisLock_test123}, 0, 30000, 20e96666-d967-4d3c-ac94-abeb14493160:21] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=32, freeConnectionsCounter=10000, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@697105324 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x3b2eb2ff, L:/127.0.0.1:49244 - R:127.0.0.1/127.0.0.1:7002]]
    ======unlock======Thread-2
    =============================
    10:27:51.090 [Thread-1] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:51.090 [Thread-3] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:51.091 [Thread-1] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=30, freeConnectionsCounter=9998, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@489743733 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0xc2cb57a1, L:/127.0.0.1:49204 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:51.091 [Thread-3] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=30, freeConnectionsCounter=9998, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@562253068 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x69c6d83a, L:/127.0.0.1:49260 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:51.095 [redisson-netty-1-1] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@562253068 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x69c6d83a, L:/127.0.0.1:49260 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:51.096 [redisson-netty-1-6] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=32, freeConnectionsCounter=10000, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@489743733 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0xc2cb57a1, L:/127.0.0.1:49204 - R:127.0.0.1/127.0.0.1:7002]]
    ======lock======Thread-1
    ======获得锁后进行相应的操作======
    10:27:52.102 [Thread-1] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:52.103 [Thread-1] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;, 2, redisLock_test123, redisson_lock__channel:{redisLock_test123}, 0, 30000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@2085319794 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x7b0b77c0, L:/127.0.0.1:49250 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:52.107 [redisson-netty-1-5] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;, 2, redisLock_test123, redisson_lock__channel:{redisLock_test123}, 0, 30000, 20e96666-d967-4d3c-ac94-abeb14493160:20] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=32, freeConnectionsCounter=10000, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@2085319794 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x7b0b77c0, L:/127.0.0.1:49250 - R:127.0.0.1/127.0.0.1:7002]]
    ======unlock======Thread-1
    =============================
    10:27:52.111 [Thread-3] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    10:27:52.112 [Thread-3] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@1360268292 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0xe28d264d, L:/127.0.0.1:49406 - R:127.0.0.1/127.0.0.1:7002]]
    10:27:52.115 [redisson-netty-1-7] DEBUG org.redisson.command.CommandAsyncService - connection released for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);, 1, redisLock_test123, 120000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=32, freeConnectionsCounter=10000, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using connection RedisConnection@1360268292 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0xe28d264d, L:/127.0.0.1:49406 - R:127.0.0.1/127.0.0.1:7002]]
    ======lock======Thread-3
    10:27:53.120 [Thread-3] DEBUG org.redisson.cluster.ClusterConnectionManager - slot 12809 for redisLock_test123
    ======获得锁后进行相应的操作======
    10:27:53.121 [Thread-3] DEBUG org.redisson.command.CommandAsyncService - acquired connection for command (EVAL) and params [if (redis.call('exists', KEYS[1]) == 0) then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;, 2, redisLock_test123, redisson_lock__channel:{redisLock_test123}, 0, 30000, 20e96666-d967-4d3c-ac94-abeb14493160:22] from slot NodeSource [slot=null, addr=null, redisClient=null, redirect=null, entry=MasterSlaveEntry [masterEntry=[freeSubscribeConnectionsAmount=0, freeSubscribeConnectionsCounter=49, freeConnectionsAmount=31, freeConnectionsCounter=9999, freezed=false, freezeReason=null, client=[addr=redis://127.0.0.1:7002], nodeType=MASTER, firstFail=0]]] using node 127.0.0.1/127.0.0.1:7002... RedisConnection@1735465853 [redisClient=[addr=redis://127.0.0.1:7002], channel=[id: 0x669d66fa, L:/127.0.0.1:49254 - R:127.0.0.1/127.0.0.1:7002]]
    ======unlock======Thread-3
    =============================
    

Redis入门(七):Redis分布式锁(单机模式/集群模式)相关推荐

  1. Redis(七)分布式锁

    前面学习了Redis的数据结构以及命令.Redis中的事务和Redis对Lua脚本的支持. 这一章就对Redis这些特性做一下实战性应用--基于Redis的分布式锁实现. Lock和Distribut ...

  2. hadoop历史背景hdfs分布式文件系统hadoop的集群模式单机模式伪分布

    hadoop历史背景&hdfs分布式文件系统&hadoop的集群模式&单机模式&伪分布 1.hadoop的历史背景 lucense ---->nutch----& ...

  3. Kafka单机、集群模式安装详解(二)

    本文环境如下: 操作系统:CentOS 6 32位 JDK版本:1.8.0_77 32位 Kafka版本:0.9.0.1(Scala 2.11) 接上篇 Kafka单机.集群模式安装详解(一) 6. ...

  4. Zookeeper命令操作(初始Zookeeper、JavaAPI操作、分布式锁实现、模拟12306售票分布式锁、Zookeeper集群搭建、选举投票)

    Zookeeper命令操作(初始Zookeeper.JavaAPI操作.分布式锁实现.模拟12306售票分布式锁.Zookeeper集群搭建.选举投票) 1.初始Zookeeper Zookeeper ...

  5. Redis单机模式主从模式哨兵模式集群模式搭建

    文章目录 一.Redis下载及安装 1.1.下载 1.2.环境安装 1.3.编译安装 1.4.修改配置 1.5.启动Redis 1.6.验证Redis是否启动 1.7.进入到Redis客户端 1.8. ...

  6. Kafka单机、集群模式安装详解(一)

    本文环境如下: 操作系统:CentOS 6 32位 JDK版本:1.8.0_77 32位 Kafka版本:0.9.0.1(Scala 2.11) 1. 所需要的环境 Kafka需要以下运行环境: Ja ...

  7. java基础巩固-宇宙第一AiYWM:为了维持生计,Redis基础Part7(Redis常见使用(部署)方式:单机模式、主从模式、哨兵模式、集群模式)~整起

    Redis持久化:RDB.AOF是针对存储在一台服务器上的数据由于存储过程被打断而发生丢失的情况的.此时,咱们肯定要考虑到,所有鸡蛋都放在一个篮子里是会出问题的. 如果服务器发生了宕机,由于数据恢复是 ...

  8. Redis 单机模式,主从模式,哨兵模式(sentinel),集群模式(cluster),第三方模式优缺点分析

    Redis 的几种常见使用方式包括: 单机模式 主从模式 哨兵模式(sentinel) 集群模式(cluster) 第三方模式 单机模式 Redis 单副本,采用单个 Redis 节点部署架构,没有备 ...

  9. Redis系列---集群模式

    目录 1. 数据分片 1.1. 哈希算法 1.1.1. 优点 1.1.2. 缺点 1.2. 一致性哈希算法 1.2.1. 优点 1.2.2. 缺点 1.3. 范围算法 1.3.1. 优点 1.3.2. ...

最新文章

  1. 余额宝技术架构读后感
  2. 看漫画还是学数学?小孩子才做选择,大人全都要!
  3. spss多元非线性曲线拟合_快速掌握SPSS数据分析
  4. Option键用的好,鼠标用的少(这6个你绝对不知道的...)
  5. mqtt安装使用教程。(基于rabbitmq插件,docker部署,k8s部署,python教程)
  6. C/C++ 笔试、面试题目大汇总收藏(上)
  7. 苍南二职计算机专业分数线,苍南第二职业中专2021年招生录取分数线
  8. 坐标系转换--筛选高于RMS的强源-------ska暑期训练
  9. 安全测试SQL注入与XSS攻击
  10. JSON对象和JSON数组
  11. vs 2010 专业版 密钥
  12. ps界面为啥突然变大了_PS如何用快速蒙版抠图,超实用的技巧!!!
  13. 英语作文计算机国际会议开幕词,国际学术会议英文主持词
  14. 已知四边形的四个点,求一个点是否在四边形之内的解决方法
  15. android+cortana+语音唤醒,为什么语音唤醒Cortana咒语是“你好,小娜”?
  16. (附源码)php柘城农产品销售系统 毕业设计020832
  17. 数字ic设计流程以及相关工具
  18. 接口获取行政区划代码_全国省市县行政区划分
  19. TFTP服务器与客户端的安装
  20. 修改计算机中文用户名,Win10电脑将中文登录用户名更改为英文名的方法

热门文章

  1. 2020-07-03:有1亿个数字,其中有2个是重复的,快速找到它,时间和空间要最优
  2. terraform_Kubernetes初学者的Terraform指南
  3. 贪心算法 田忌赛马问题
  4. HDMI接口ESD设计及硬件布线注意事项
  5. PIM-SM原理(ASM)
  6. 转载: 房贷的两种还款方式介绍
  7. 为什么有人说富坚义博有着殿堂级的画功?他的画功体现在哪儿呢?
  8. vba调用mysql随机出题软件_题库需要随机进行出题
  9. python做乘法运算定律_四年级乘法运算定律-
  10. 外呼系统《OpenSIPS2.4代理FreeSwitch》(2022版)