当对接第三方接口时,往往会碰到同一时间发送了大量相同的请求,这个时候或许就是第三方发送接口的失误了。而我们需要做的就是针对这个情况来强化我们的系统。这个时候就需要用到分布式锁。让这些请求只有一个能发送进来。
分布式锁的实现一般有三种:
- 基于数据库的乐观锁;
- 基于redis的分布式锁;
- 基于zookeeper的分布式锁。
这里我们讲的是第二种:基于redis的分布式锁的原理以及实现。
下面是代码的实现:
public class DistributeLock { /** * setnx(key,value):如果key-value存在,缓存成功并返回1,否则返回0. * getset(key,value):返回旧的value,然后更新旧的value为新的value. * expire(key,seconds):设置key的过期时间为seconds秒. * get(key):获取key对应的value,不存在返回nil. */ private final static long expire = 1000; // 设置锁的过期时间 public static boolean getLockByRedis(Jedis jedis,String lock){ boolean success = false; long flag = jedis.setnx(lock, String.valueOf(System.currentTimeMillis() + expire + 1)); // 获取分布式锁成功 if (flag == 1) { success = true; }else{ // 可能其他线程持有锁,也有可能是锁超时 long getVale = Long.valueOf(jedis.get(lock)); if (getVale < System.currentTimeMillis()) { //超时 String oldValue = jedis.getSet(lock,String.valueOf(System.currentTimeMillis() + expire + 1)); if (oldValue != null) { // 被其他线程抢占 if (Long.valueOf(oldValue) == getVale) { success = false; }else{ success = true; } } }else{ success = false; } } return success; } /** * 谁上锁,谁释放 * @param jedis * @param lock */ public static void releaseLock(Jedis jedis,String lock) { if (System.currentTimeMillis() < Long.valueOf(jedis.get(lock))) { jedis.del(lock); } } }