# jedis 与 redission 实现分布式锁 (干货带源码)

JVM中提供了处理锁机制api(synchronize/Lock)等,这种是jvm层面的。到了分布式就没作用了。所以需要分布式锁

# 分布式锁要满足哪些要求呢?

  • 排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取

  • 避免死锁: 这把锁在一段有限的时间之后,一定会被释放(正常释放或异常释放)

  • 高可用:获取或释放锁的机制必须高可用且性能佳

# 目前主流的分布式锁实现方式

  • 基于数据库的实现方式

  • 基于redis的实现方式(推荐)

  • 基于Zookeeper的实现方式

# 基于Jedis的Redis分布式锁的实现

  • RedisLock Util
@Service
public class RedisLock {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    private String lock_key = "redis_lock"; //锁键

    protected long internalLockLeaseTime = 3000;//锁过期时间

    private long timeout = 999999; //获取锁的超时时间


    //SET命令的参数
    SetParams params = SetParams.setParams().nx().px(internalLockLeaseTime);

    @Autowired
    RedisCacheConfiguration redisCacheConfiguration;


    /**
     * 加锁
     * @param id
     * @return
     */
    public boolean lock(String id){
        Jedis jedis = redisCacheConfiguration.redisPoolFactory().getResource();
        try{
            String lock = jedis.set(lock_key, id, params);
            if("OK".equals(lock)){
                return true;
            }
            return false;
        }finally {
            jedis.close();
        }
    }

    /**
     * 解锁
     * @param id
     * @return
     */
    public boolean unlock(String id){
        Jedis jedis = redisCacheConfiguration.redisPoolFactory().getResource();
        String script =
                "if redis.call('get',KEYS[1]) == ARGV[1] then" +
                        "   return redis.call('del',KEYS[1]) " +
                        "else" +
                        "   return 0 " +
                        "end";
        try {
            Object result = jedis.eval(script, Collections.singletonList(lock_key),
                    Collections.singletonList(id));
            if("1".equals(result.toString())){
                return true;
            }
            return false;
        }finally {
            jedis.close();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

使用

  boolean lock = redisLock.lock(likeLock);
  if (Objects.equals(false, lock)) {
      throw new BusinessException("等待操作,请勿多次频繁操作");
  }
  try {
    //业务代码
  } finally {
      redisLock.unlock(likeLock);
  }
1
2
3
4
5
6
7
8
9

# 基于Redission的Redis分布式锁的实现

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

String key = SystemConstants.LOYALTY_MEMBER_POINT_LOCK_PRE + cusId;
RLock lock = redissonClient.getLock(key);
try {
    lock.lock();
    // 排他性檢查
    // 业务
}
finally {
    lock.unlock();
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 相关资料

Java分布式锁,搞懂分布式锁实现看这篇文章就对了 (opens new window)

基于Jedis的Redis分布式锁实现 (opens new window)

全量分析

评 论:

上次更新时间: 6/1/2022, 4:47:27 PM