在线免费国产视频,亚洲无码成人免费在线,又黄又爽又无遮挡国产,日韩爆乳av少妇无码,国产福利精品98视频一区二区

Redis實(shí)現分布式鎖

Redis被經(jīng)常用來(lái)實(shí)現分布式鎖,本文主要講述redis如何實(shí)現一個(gè)分布式鎖的demo。

獲取鎖

redis分布式鎖的實(shí)現主要是通過(guò)redis的set命令實(shí)現:

SET key value nx PX milliseconds
  • nx : 當key存在的時(shí)候才將set對應的key,value寫(xiě)入到redis數據庫里面。如果設置成功之后,就返回OK,已經(jīng)存在就返回nil,當前set命令也是一個(gè)原子操作,可以作為分布式鎖。
  • px milliseconds: 為當前key設置過(guò)期時(shí)間,當時(shí)間過(guò)了之后會(huì )將當前key刪除。主要是方式獲取鎖之后未正常釋放,導致死鎖,一直無(wú)法獲取鎖。超時(shí)時(shí)間需要合理設置,需要保證當前業(yè)務(wù)能夠處理完。
private static final String LOCK_SUCCESS = "OK";

  private static final Long UNLOCK_SUCCESS = 1L;

  //
  private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

  private final JedisCluster cluster;

  private final long lockTimeout;

  private final String lockKey;

  public RedisDistributedLockImpl(JedisCluster cluster, String lockKey, long lockTimeout) {

    this.cluster = cluster;
    this.lockTimeout = lockTimeout;
    this.lockKey = lockKey;
  }

  @Override
  public String lock() {
    long end = System.currentTimeMillis() + lockTimeout;
    String requireToken = String.valueOf(System.currentTimeMillis());
    int expireTime = 300 * 1000;
    SetParams params = new SetParams().nx().px(expireTime);
    while (System.currentTimeMillis() < end) {
      try {
        String result = cluster.set(lockKey, requireToken, params);
        if (LOCK_SUCCESS.equals(result)) {
          System.out.println("lock success");
          return requireToken;
        }
        System.out.println("lock failed trying");
        Thread.sleep(100);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }
    return requireToken;
  }

釋放鎖

釋放鎖,主要是需要通過(guò)原子操作將鎖對應的key刪除,可以通過(guò)下面lua腳本刪除。

if redis.call('get', KEYS[1]) == ARGV[1] then 
   return redis.call('del', KEYS[1]) 
else 
    return 0 
end

釋放鎖的詳細代碼:

@Override
  public boolean unlock(String identify) {
    if (identify == null || identify.trim().length() == 0) {
      return false;
    }
    Object obj = new Object();
    try {
      obj = cluster.eval(UNLOCK_SCRIPT, Collections.singletonList(lockKey), Collections.singletonList(identify));
      if (UNLOCK_SUCCESS.equals(obj)) {
        System.out.println("release lock success, requestToken:" + identify);
        return true;
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("release lock failed, requestToken:" + identify + ", result:" + obj);
    return false;
  }

測試分布式鎖

使用下面代碼模擬秒殺場(chǎng)景:

public class RedisDistributedLockTest {

  static int n = 500;

  public static void secKill() {
    System.out.println("商品數量:" + --n);
  }

  public static void main(String[] args) {
    Runnable runnable = () -> {
      RedisDistributedLockImpl lock = null;
      String unLockIdentify = null;
      try {
        Set<HostAndPort> set = new HashSet<>();
        set.add(new HostAndPort("127.0.0.1", 30001));
        JedisPoolConfig config = new JedisPoolConfig();
        JedisCluster cluster = new JedisCluster(set, config);
        lock = new RedisDistributedLockImpl(cluster, "test1", 20000);
        unLockIdentify = lock.lock();
        System.out.println(Thread.currentThread().getName() + "正在運行");
        secKill();
      } finally {
        if (lock != null) {
          lock.unlock(unLockIdentify);
        }
      }
    };
    System.out.println("------------------開(kāi)始--------------");
    for (int i = 0; i < 100; i++) {
      Thread t = new Thread(runnable);
      t.start();
    }
  }

}

執行結果如下:

image.png



標 題:《Redis實(shí)現分布式鎖
作 者:zeekling
提 示:轉載請注明文章轉載自個(gè)人博客:浪浪山旁那個(gè)村

    評論
    0 評論
avatar

取消
在线免费国产视频,亚洲无码成人免费在线,又黄又爽又无遮挡国产,日韩爆乳av少妇无码,国产福利精品98视频一区二区