JedisLock基于Redis实现分布式锁

JedisLock基于Redis实现分布式锁

一、 背景

实际的项目开发过程中我们常常遇到高并发访问,容易导致数据不同步,例如:库存的增加, 故此我们可以通过Redis提供的特性实现分布式锁,以达到数据的同步性。本文主要通过客户端JedisLock来实现分布式锁。

注:该文是本博主记录学习之用,没有太多详细的讲解,敬请谅解!

二、 JedisLock实现分布式锁的原理

1、实现思想:

(1)获取锁的时候,使用setnx加锁,锁的value值为一个超时时间,通过超时时间进行判断锁的占有与释放。

(2)释放锁的时候,判断是不是占有锁,若是占有锁,则执行delete进行锁释放。

三、添加Maven依赖

com.github.jedis-lockjedis-lock1.0.0

四、代码示例

package com.lance.net.server;import com.github.jedis.lock.JedisLock;
import redis.clients.jedis.Jedis;public class JedisLockTest {public static void main(String[] args) throws InterruptedException {for (int i=0;i<10;i++){int num = i;new Thread(new Runnable() {@Overridepublic void run() {Jedis jedis=new Jedis("127.0.0.1",6379);lock(jedis,"key", num);}}).start();}}public static void lock(Jedis jedis, String key,int i){JedisLock jedisLock=new JedisLock(jedis,key,2000,2000);try {//获得锁jedisLock.acquire();System.out.println(i+"获得锁");if(i==2){//该代码块是为了验证效果System.out.println(i+"睡眠2秒....");Thread.sleep(2000);}}catch (Exception e){e.printStackTrace();}finally {System.out.println(i+"释放锁");if(jedisLock!=null){//释放锁jedisLock.release();}if(jedis!=null){jedis.close();}}}}

效果图:
在这里插入图片描述

对于JedisLock如何基于Redis来实现锁的效果,本文就不一一描述,各位可自行看源码理解!

以下贴上源码以供学习:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.github.jedis.lock;import redis.clients.jedis.Jedis;public class JedisLock {Jedis jedis;String lockKey;int expireMsecs;int timeoutMsecs;boolean locked;public JedisLock(Jedis jedis, String lockKey) {this.expireMsecs = 60000;this.timeoutMsecs = 10000;this.locked = false;this.jedis = jedis;this.lockKey = lockKey;}public JedisLock(Jedis jedis, String lockKey, int timeoutMsecs) {this(jedis, lockKey);this.timeoutMsecs = timeoutMsecs;}public JedisLock(Jedis jedis, String lockKey, int timeoutMsecs, int expireMsecs) {this(jedis, lockKey, timeoutMsecs);this.expireMsecs = expireMsecs;}public JedisLock(String lockKey) {this((Jedis)null, lockKey);}public JedisLock(String lockKey, int timeoutMsecs) {this((Jedis)null, lockKey, timeoutMsecs);}public JedisLock(String lockKey, int timeoutMsecs, int expireMsecs) {this((Jedis)null, lockKey, timeoutMsecs, expireMsecs);}public String getLockKey() {return this.lockKey;}public synchronized boolean acquire() throws InterruptedException {return this.acquire(this.jedis);}/*** 获得 lock.* 实现思路: 主要是使用了redis 的setnx命令,缓存了锁.* reids缓存的key是锁的key,所有的共享, value是锁的到期时间(注意:这里把过期时间放在value了,没有时间上设置其超时时间)* 执行过程:* 1.通过setnx尝试设置某个key的值,成功(当前没有这个锁)则返回,成功获得锁* 2.锁已经存在则获取锁的到期时间,和当前时间比较,超时的话,则设置新的值**/public synchronized boolean acquire(Jedis jedis) throws InterruptedException {int timeout = this.timeoutMsecs;while(timeout >= 0) {long expires = System.currentTimeMillis() + (long)this.expireMsecs + 1L;String expiresStr = String.valueOf(expires);  //锁到期时间if (jedis.setnx(this.lockKey, expiresStr) == 1L) {this.locked = true;return true;}//判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的//获取上一个锁到期时间,并设置现在的锁到期时间,//只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的String currentValueStr = jedis.get(this.lockKey);if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {String oldValueStr = jedis.getSet(this.lockKey, expiresStr);if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {this.locked = true;return true;}}timeout -= 100;Thread.sleep(100L);}return false;}public synchronized void release() {this.release(this.jedis);}public synchronized void release(Jedis jedis) {if (this.locked) {jedis.del(new String[]{this.lockKey});this.locked = false;}}
}

五、注意点

  1. 查看源码发现jedis.setnx(this.lockKey, expiresStr)设置值的时候value是超时时间,是通过value为超时时间计算出锁的到期时间,但是并没有设置key的过期时间,如果运行过程中Redis怠机,失去连接,就无法删除key,该key就会永久存在Redis中,直到下次运行命中该key。
  2. 由于是通过当前服务器时间来判断,故对于多台服务器时间需要强一致。

1、Redission实现分布式锁(官网推荐)
https://blog.csdn.net/weixin_43947588/article/details/90064064
2、Curator基于zookeeper实现分布式锁
https://blog.csdn.net/weixin_43947588/article/details/84893777
3、Jedis实现分布式锁
https://blog.csdn.net/weixin_43947588/article/details/98631392


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部