Redis.setIfAbsent分布式锁

1.问题简介:当三台机器使用Spring定时器,会同时给消费者发送支付成功的通知。而且会发三次,对商户的影响很大。例如:客户在使用商户的平台去购买票的时候,支付成功发了三次通知,那么就会出票三次。

2.问题解决:使用redis分布式锁,并设置超时时间。当消费者发送通知失败的时候去删除锁,然后重新推送.

3.技术:使用Redis的Spring-data-redis依赖,  TimeUnit的介绍.    

一:Redis简介

      Redis是一款开源的Key-Value数据库,运行在内存中,由C语言编写。企业开发通常采用Redid来实现缓存。同类的产品还有memcache、memcached等。

二:Jedis

       Jedis是Redis官方推出的一款面向Javad的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis、SRP等等,推荐使用Jedis。

三:Spring-data-redis

        Spring-data-redis是Spring大家族的一部分,提供了在spring应用中通过简单的配置访问redis服务,对redis底层开发包(Jedis,JRedis,an RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

四:TimeUnit的介绍

        TimeUnit是JDK封装好的java.uitl.concurrent包下面的一个类,表示给定单元粒度的时间段

五:TimeUnit的作用

       1.时间颗粒度转换
        2.线程延时

六:TimeUnit讲解

        TimeUnit.DAYS //天
        TimeUnit.HOURS //小时
        TimeUnit.MINUTES //分钟
        TimeUnit.SECONDS //秒
        TimeUnit.MILLISECONDS //毫秒
        TimeUnit.MICROSSECONDS //微妙
        TimeUnit.NANOSSECONDS //纳秒

七:TimeUnit中有最全面的转换颗粒度方法,基本所有的都能转换,具体要用的话可以查看他的源码,下面这个方法是把10分钟转换为多少毫米

TimeUnit.MILLISECONDS.convert(10L,TimeUnit.MINUTES);

2.问题解决:

        (1):Spring-data-redis针对Jedis提供了如下功能:

        (2):RedisTemplate中API使用

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.8.4.RELEASE</version>
</dependency>

        (3):RedisTemplate的直接方法 

@Autowired
private StringRedisTemplate redisTemplate;
#注释:setIfAbsent 分布式锁 true加锁成 false 失败
Boolean temp = redisTemplate.opsForValue().setIfAbsent(Key, plain);
#注释Key:唯一标识
#注释Plian:存入redis的内容
if (!temp) {
    log.info("加锁失败");
    return false;
}
#注释Expire 过期时间
Boolean expire = redisTemplate.expire(Key, 5, TimeUnit.MINUTES);
#注释删除单个key
redisTemplate.delete(Key);
#注释根据Key获取过期时间
redisTemplate.getExpire(Key);
#注释判断key是否存在
redisTemplate.hasKey(Key);
注:建议使用spring-data-redis 2.1.0版本 举例说明,只需要一行代码,加锁已经设置失效时间(需要和Jedis版本匹配,要不会报错)
Boolean  temp = redisTemplate.opsForValue().setIfAbsent(Key, plain,5, TimeUnit.MINUTES);

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,setIfAbsent命令在Redis中可以用来实现分布式锁,它可以确保只有一个客户端能够成功地获取锁。当多个客户端同时尝试获取锁时,只有其中一个客户端会成功地将键设置为不存在的状态,即获取到锁。 如果你遇到了setIfAbsent分布式锁失败的情况,可能有以下几个原因: 1. 网络延迟:由于网络延迟的存在,在一个客户端尝试获取锁操作后,可能有一段时间内其他客户端还无法感知到该键已经被设置为存在。这样就可能导致多个客户端同时认为自己获取到了锁,造成冲突。 2. 客户端执行时间过长:如果一个客户端在获取到锁之后执行时间过长,超过了锁的有效期,那么其他客户端就可以再次获取到该锁。这会导致之前获取锁的客户端在执行完后释放锁时,实际上释放的是其他客户端获取到的锁。 3. 锁的有效时间设置不合理:如果锁的有效时间设置得过长,可能会导致其他客户端长时间等待锁的释放。这可能会影响系统的性能和并发能力。 解决这个问题的一种方式是在获取锁时添加一个唯一标识符,确保每个客户端持有独一无二的锁。另外,可以根据具体业务需求,适当调整锁的有效时间,避免锁过早释放或过长占用。 需要注意的是,Redis自身并不提供完全可靠的分布式锁,因为它在面对网络分区等异常情况时可能出现问题。如果对于分布式锁要求高的场景,可以考虑使用基于Redis的第三方分布式锁实现,例如Redlock或基于ZooKeeper的Curator库等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值