java redisson 分布式锁,java使用redis实现分布式锁

  java redisson 分布式锁,java使用redis实现分布式锁

  分布式锁可以通过多种方式实现,如zookeeper、redis.无论哪种方式,他的基本原理都是一样的:锁用一个状态值来表示,锁的占用和释放用状态值来标识。

  如何解决写爬虫IP受阻的问题?立即使用。

  一、为什么Redis可以方便地实现分布式锁

  1.Redis是单进程单线程模式,采用队列模式将并发访问改为串行访问,多个客户端之间不存在连接Redis的竞争。

  2.Redis的SETNX命令可以方便地实现分布式锁。

  setNX(不存在时设置)

  语法:SETNX键值

  返回值:设置成功,返回1;设置失败,返回0。

  并仅在键不存在时将键的值设置为value,返回1;如果给定的键已经存在,SETNX不做任何事情并返回0。

  综上所述,你可以通过setnx的返回值来判断锁是否被获取,不用担心并发访问。因为Redis是单线程的,如果返回1,就获取锁,如果返回0,就不获取锁。当业务操作完成时,锁必须被释放。释放锁的逻辑很简单,就是把之前设置的setnx键删除就可以了,这样下次设置nx这个键就可以获得锁了。

  二、分布式锁实现

  我们已经知道分布式锁可以通过Redis自己的函数setNX来实现。具体步骤如下。

  我在CentOS7的一个linux虚拟机上安装了Redis服务,ip地址:192.168.246.130,服务端口:6379。

  下面是一个java通过redis实现分布式锁的例子:

  导入redis . clients . jedis . jedis;

  公共类RedisLock {

  //锁的钥匙

  private static final String key= DistributedRedisLock ;

  私有静态整数计数=0;

  公共静态void main(String[] args) {

  for(int I=0;i1000i ){

  新线程(新Runnable() {

  @覆盖

  公共无效运行(){

  //获取Redis连接

  Jedis jedis=新Jedis(192.168.246.130 ,6379);

  尝试{

  while(true){

  //获取锁

  if(jedis.setnx(key,Thread.currentThread()。getName())==1){

  尝试{

  system . out . println( Thread( Thread . current Thread()。getName())获取锁并开始操作);

  数数;

  system . out . println(count);

  打破;

  }最后{

  System.out.println(操作完成,释放锁);

  //操作执行后必须释放锁,所以在finally块中执行。

  jedis.del(键);

  }

  }否则{

  //返回的不是1,表示某个线程已经获得了锁。

  尝试{

  //等待100毫秒,然后重试

  thread . sleep(100 l);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  }

  }

  }catch(异常e){

  e . printstacktrace();

  }最后{

  //释放Redis连接

  jedis . disconnect();

  }

  }

  }).start();

  }

  }

  }上面代码的输出结果是:

  线程(Thread-320)获得锁并开始执行操作。

  一个

  操作完成,解除锁定。

  线程(Thread-463)获得锁并开始执行操作。

  2

  操作完成,解除锁定。

  线程(Thread-997)获得锁并开始执行操作。

  三

  操作完成,解除锁定。

  .

  线程(Thread-409)获得锁并开始执行操作。

  998

  操作完成,解除锁定。

  线程(Thread-742)获得锁并开始执行操作。

  紧急服务电话

  操作完成,解除锁定。

  线程(Thread-286)获得锁并开始执行操作。

  1000

  操作完成后,锁被释放。虽然上面的代码是在单个应用程序和多线程的条件下测试的,但是即使在分布式环境下使用多个应用程序和多线程来获取锁,结果仍然是正确的。

  三、解决死锁问题

  前面的示例代码只是一个测试代码,只是为了解释原理。例子本身很简单,所以有些欠考虑。例如,当一个业务操作在获得锁后执行过程中出现环境问题,与Redis的连接断开,锁无法在finally块中释放,导致其他等待锁的线程无限期等待,即发生死锁。

  解决方式:

  您可以在Redis中为锁设置一个到期时间,这样即使锁不能被释放,也可以在一段时间后自动释放锁。

  代码只需要在获取锁后在try语句块中添加以下代码:

  jedis.expire(key,10);//在这里,为锁更妥善的解决方式:设置10秒的到期时间。

  第一种解决方案不太好,因为当业务操作处理时间较长,超过设定的到期时间时,锁会自动解除。然后,在finally块中执行释放锁的操作时,锁可能已经被其他线程持有,这将导致其他线程持有的锁被释放,从而产生并发问题。所以更好的方法是在释放锁的时候判断锁是否过期。如果已经过期,就不用再放了。

  代码上把获取到锁之后的操作改为如下代码:

  long start=system . current time millis();//获取以毫秒为单位的开始时间

  尝试{

  jedis.expire(key,10);

  .

  }最后{

  .

  if(system . current time millis()start 10 * 1000){

  //如果先前设置的锁尚未过期,则释放它

  jedis.del(键);

  }

  }以上是Java基于Redis实现分布式锁的细节。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 关于redis数据库入门详细介绍图片,redis数据库的使用,关于Redis数据库入门详细介绍
  • redis队列操作命令,redis 循环队列
  • redis队列操作命令,redis 循环队列,redis实现简单队列
  • redis部署应用服务器上,redis如何启动服务器
  • redis部署应用服务器上,redis如何启动服务器,搭建Redis服务器步骤详细介绍
  • redis缓存穿透和击穿解决方案,redis缓存穿透,缓存雪崩解决
  • redis缓存穿透和击穿解决方案,redis缓存穿透,缓存雪崩解决,redis缓存穿透解决方法
  • Redis缓存,redis和缓存
  • Redis缓存,redis和缓存,Redis缓存详解
  • redis的配置,启动,操作和关闭方法有哪些,关闭redis的命令,Redis的配置、启动、操作和关闭方法
  • redis的主从配置方法详解图,Redis主从配置
  • redis的主从配置方法详解图,Redis主从配置,redis的主从配置方法详解
  • redis界面工具,mac安装redis可视化工具
  • redis界面工具,mac安装redis可视化工具,推荐几款 Redis 可视化工具(太厉害了)
  • redis正确使用的十个技巧是什么,redis正确使用的十个技巧有哪些
  • 留言与评论(共有 条评论)
       
    验证码: