当前位置:   article > 正文

Redis非阻塞式分布式锁和Redis事务_redis加锁,无阻塞代码

redis加锁,无阻塞代码

业务场景

秒杀抢购业务
redis中初始库存数量10,订单数量0
每抢购一单,库存数量-1,订单数量+1
不加锁会出现超卖现象
程序代码加锁可以防止。但如果有多个客户端分布式部署,加锁仍然会出现超卖。因为锁是依赖于当前程序的进程,启动多个进程实际上是多把锁。可以通过在redis加分布式锁,来实现在多个进程中来维护同一个锁对象redis是全局单线程的,可以保证同一时间只有一个客户端持有锁。没有抢到锁立即返回结果。

redis命令

SETNX lockName value
如果键不存在,则设置成功,返回true,也就是抢到锁。如果键已经存在,则返回false,说明其他客户端在占有锁
PEXPIRE lockName 1500
为键设置过期时间防止某一客户端得到锁突然宕掉,没来得及释放锁,后面其他客户端就不能得到锁

代码实现

Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockkName, value, 30, TimeUnit.SECONDS);
  if(lock) {
    //加锁成功... 
    // todo business
    redisTemplate.delete(lockName);   //删除key,释放锁
  } else {
   // 加锁失败
      return false
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

redis非阻塞式锁常见问题及解决方式

1.客户端拿到锁,程序执行异常没有释放锁,导致其他客户端无法拿到锁
解决方式:为锁设置过期时间。到达过期时间后锁自动释放

2.设置锁与设置过期时间不是原子性的。可能出现获取到锁但还没设置过期时间客户端就宕机了。
解决方式:在设置锁的同事设置过期时间

redisTemplate.opsForValue().setIfAbsent(lockkName, value, 30, TimeUnit.SECONDS);
  • 1

事务

MULTI 命令标志着事务的开始
会将redis命令按次序放入一个事务队列中,先不执行

EXEC 执行事务,依次执行事务队列中的命令,将结果一起返回给客户端

DISCARD 取消事务

WATCH 命令在EXEC命令执行之前监视一个键。在EXEC命令执行时,如果被监视的键被更改,服务器就会拒绝执行事务,向客户端返回执行失败的空回复

       try{
        jedis.watch("age");
        // 开启事务
        Transaction transaction = jedis.multi();
        
        transaction.set("key-1", "value-1");
        transaction.set("key-2", "value-2");
        transaction.set("key-3", "value-3");
        transaction.set("key-4", "value-4");
        // 提交事务         //放弃事务
        transaction.exec();//transaction.discard();
        }catch(Exception e){
        
        }
     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

要么全部执行,要么全部失败。exec执行后,取消对所有键的监视

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号