请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

请老师帮忙看看,在RedisShardedPoolUtil中设置带有效期的锁的方法实现

请老师帮忙看看,在RedisShardedPoolUtil.java 中这样实现有没有问题?谢谢~~

/**
 * 带过期时间的分布式锁
 *
 * @param key
 * @param seconds 有效期时间(秒)
 * @return
 */
public static Long setnxEx(String key, int seconds) {
    try {
        try (ShardedJedis jedis = RedisShardedPool.getJedis()) {
            // 尝试获取锁
            Long setnxResult = jedis.setnx(key, String.valueOf(System.currentTimeMillis() + seconds * 1000));
            if (setnxResult == null || setnxResult.intValue() != 1) {
                // 未获取到锁,继续判断时间戳,看是否可以重置并获取到锁
                String lockValueStr = jedis.get(key);
                if (lockValueStr != null && System.currentTimeMillis() < Long.parseLong(lockValueStr)) {
                    // key存在且时间戳未过,获取锁失败
                    return 0L;
                }

                // key不存在(已经过期或被删除)或者时间戳已过,利用getset原子操作尝试获取
                String getsetResult = jedis.getSet(key, String.valueOf(System.currentTimeMillis() + seconds * 1000));
                if (getsetResult != null && !StringUtils.equals(lockValueStr, getsetResult)) {
                    // key已经被其他请求重置并获取锁,本次请求获取锁失败(负面后果:少量延长了该锁的时间戳)
                    return 0L;
                }

                // key不存在(已经过期或被删除)或者key的原值与前面获取的相同(表示没有其他请求重置key并获取到锁),获取锁成功
                setnxResult = 1L;
            }
            // 获取锁成功,设置超时
            Long expireResult = jedis.expire(key, seconds);
            if (expireResult == null || expireResult.intValue() != 1) {
                throw new Exception("set key: " + key + " expire error. return: " + expireResult);
            }
            return setnxResult;
        }
    } catch (Exception e) {
        log.error("setnxEx key: {}  error", key, e);
    }
    return null;
}

正在回答

2回答

同学,可以写一个多线程并发的测试代码测试一下。

0 回复 有任何疑惑可以回复我~
  • 提问者 慕慕8288485 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2020-03-11 11:35:18
提问者 慕慕8288485 2020-03-11 11:40:40

简单测试通过,基本上是实现课程中的逻辑。

redis2.6.x之后已经支持 SET 带 nx 和 ex的参数,作为一个原子操作,就不需要这么麻烦了吧。另外,Redisson通过eval一段lua代码来实现RedLock,还能实现可重入锁。看来,自己还得快点更新知识啊。

0 回复 有任何疑惑可以回复我~
  • 对的,Redisson已经实现了这个
    回复 有任何疑惑可以回复我~ 2020-03-14 22:50:18
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信