Administrator
发布于 2024-09-05 / 20 阅读
0
0

redission加锁 脚本

tryLockInnerAsync

 waitTime :指定等待时间

leaseTime:指定租约时间,即资源被持有的时间。

unit:时间单位

threadId:通常用于指定请求资源的线程的唯一标识符。

command: redis执行脚本命令:EVAL

<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) 

evalWriteAsync

key:通常用于指定Redis中的键

codec:这是一个编解码器对象,用于序列化和反序列化Redis的值。

evalCommandType:指定了要执行的Redis命令的类型

script: 通常用于指定要执行的Lua脚本。

keys:通常用于指定Lua脚本中要使用的键。 (该处是因为扩展性和兼容性,主要用于多个key同时操作)

params:传递任意数量的参数

protected <T> RFuture<T> evalWriteAsync(String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {

script:

  
return evalWriteAsync(getRawName(), LongCodec.INSTANCE, command,
                "if (redis.call('exists', KEYS[1]) == 0) then " +
                        "redis.call('hincrby', 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.singletonList(getRawName()), unit.toMillis(leaseTime), getLockName(threadId));


    KEYS[1]: keys参数
    ARGV[2]:  getLockName(threadId))
    ARGV[1]: unit.toMillis(leaseTime)
       "if (redis.call('exists', KEYS[1]) == 0) then " + //判断key 不存在 
          "redis.call('hincrby', KEYS[1], ARGV[2], 1); " + //hash中增加 key =  ARGV[2] value =1
          "redis.call('pexpire', KEYS[1], ARGV[1]); " + // 设置key 超时时间 
          "return nil; " +
        "end; " +
        "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " + //如果存在
          "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +//将线程value加1 
          "redis.call('pexpire', KEYS[1], ARGV[1]); " +// 每次都将超时时间重新设置想要的值 
          "return nil; " +
        "end; " +
        "return redis.call('pttl', KEYS[1]);",

问题

  1. 如果单线程循环去锁,则锁的时间会重置,value会一直加1

  2. 对于多线程的常见下,一个线程id会不会一直被锁定


评论