美文网首页
2022-05-06_Redisson分布式锁hash中key的

2022-05-06_Redisson分布式锁hash中key的

作者: kikop | 来源:发表于2022-05-06 19:39 被阅读0次

    20220506_Redisson分布式锁hash中key的创建分析

    1概述

    1.1时序分析

    // 将哈希表 key 中的域 field 的值设为 value 
    hset key field value
    

    1.1.1.Spring 自动装配Redisson

    Redisson对象依赖connectionManager,当构建Redisson对象,通过配置创建 connectionManager

    connectionManager里面有个id属性,由uuid生成。

    1.1.2.根据key名称,获取某个RedissonLock

    RLock rLock = redissonClient.getLock(LOCK_GOODS_ADD_PREFIX + goodsId);
    
    image-20220506192111362.png

    1.1.3.线程A来了, 开始加锁tryLock,即向Redis里面写入缓存数据和缓存失效时间,数据类型为:hash。

    boolean lockResult = rLock.tryLock(100, 30, TimeUnit.SECONDS);
    
    // 加锁的Lua脚本
    // keys:hash的key-->KEY[1]
    // args:
    // key的过期时间 -->ARGV[1]、
    // field(这里值redisson固定为1)-->ARGV[2](组成部分:当前RedissonLock的uuid:当前线程的值)
    return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,
                      "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]);",
                        Collections.<Object>singletonList(getName()), internalLockLeaseTime, getLockName(threadId));
    

    hash的key为:goods:add:00001

    field为:当前RedissonLock的uuid:当前线程的值,即1ea0b24e-e1f6-4a1b-88fc-f31f2a909bdc:51

    value为:默认为1(支持可重入,累加)

    image-20220506192041800.png

    1.1.4.线程B来了, 开始加锁tryLock,获得锁成功以后,,即向Redis里面写入缓存数据和缓存失效时间,数据类型为:hash。

    线程A如果已经释放锁,则线程加锁成功,否则等待指定的时间。

    boolean lockResult = rLock.tryLock(100, 30, TimeUnit.SECONDS);
    

    hash的key为:goods:add:00001

    field为:当前RedissonLock的uuid:当前线程的值,即1ea0b24e-e1f6-4a1b-88fc-f31f2a909bdc:52

    value为:默认为1(支持可重入,累加)

    image-20220506192058810.png

    2代码示例

    2.1testTryLock

    /**
         * testTryLock
         */
        private void testTryLock(String goodsId, String strThreadInfo) {
    
            // RLock关联某商品的锁
            RLock rLock = redissonClient.getLock(LOCK_GOODS_ADD_PREFIX + goodsId);
            try {
                log.info("当前线程[{}:{}]开始获取锁", Thread.currentThread().getName(), Thread.currentThread().getId());
    
    
                // 1.获取锁最多等待 100 s
                // wai30s后 key过期
                // key:b2b62744-3392-48ca-83a3-eff8ef638d55: 50
                // value:1
                boolean lockResult = rLock.tryLock(100, 30, TimeUnit.SECONDS);
    
                System.out.println("getName()"+rLock.getName());
    
                if (!lockResult) {
                    log.info("当前线程[{}:{}]获取锁失败", Thread.currentThread().getName(), Thread.currentThread().getId());
                    return;
                }
                log.info("当前线程[{}:{}]获取锁成功", Thread.currentThread().getName(), Thread.currentThread().getId());
    
                // 2.业务操作
                // 模拟较长时间 3<100,rLock.isHeldByCurrentThread()==>false
    //            TimeUnit.SECONDS.sleep(100);
    
                // 模拟较长耗时时间,10s
                // rLock.isHeldByCurrentThread()==>true
                TimeUnit.SECONDS.sleep(10);
    
            } catch (InterruptedException ex) {
                log.info("当前线程:[{}:{}]获取锁异常,异常原因:{}!",
                        Thread.currentThread().getName(),
                        Thread.currentThread().getId(),
                        ex);
            } finally {
                log.info("当前线程[{}:{}]准备释放锁", Thread.currentThread().getName(), Thread.currentThread().getId());
                // 释放锁的时候最好判断当前线程是否持有锁,否则会抛出异常
                if (rLock.isHeldByCurrentThread()) {
                    log.info("当前线程[{}:{}]释放锁成功", Thread.currentThread().getName(), Thread.currentThread().getId());
                    rLock.unlock();
                } else {
                    // 如锁可能已经过期,别的线程占有了,字段中key对应的value:为其他线程
                    log.info("锁非当前线程持有,不需要释放[{}:{}]", Thread.currentThread().getName(), Thread.currentThread().getId());
                }
    
            }
        }
    

    相关文章

      网友评论

          本文标题:2022-05-06_Redisson分布式锁hash中key的

          本文链接:https://www.haomeiwen.com/subject/ylpzyrtx.html