利用redis结合springboot实现一些基础功能

本文介绍了如何使用Redission框架中的分布式锁功能,以查询用户为例,防止用户两次快速点击。文章详细讲解了如何配置Redisson,获取和释放锁的过程,并提到了看门狗机制在无锁超时情况下的作用。
摘要由CSDN通过智能技术生成

二.通过redission这一开源框架的分布式锁,实现两次重复点击不允许
(以查询用户为例)

  1. Redission是一个在redis的基础上实现的Java驻内存数据网格,它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务
  2. Redission提供了使用Redis最简单和便捷的方法。它的宗旨就是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
  3. Redission的Github地址:https://github.com/redisson/redisson
  4. Redission 其实跟Jedis差不多,都是用来操作Redis的框架。提供了很多封装,其中分布式锁就是其中之一。

Redis 分布式锁使用

Rlock =redisson.getLock("anyLock");
//最常见的使用方法 lock.lock();
//支持过期解锁功能
//10秒钟以后自动解锁
//无须调用unlock方法手动解锁
lock.lock(10,TimeUnit.SECONDS);
//第二种
//尝试加锁,最多等待100秒,上锁以后10秒自动解锁
//boolean res =lock.tryLock(100,10,TimeUnit.SECONDS);
...
lock.unlock();一般放在finally 中,实现解锁。因为程序执行速率可快可慢,最好是加一个手动解锁

重点是下面这一脚本,基于redis的底层原理

-- 若锁不存在:则新增锁,并设置锁重入计数为1、设置锁过期时间
if (redis.call('exists', KEYS[1]) == 0) then
    redis.call('hset', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
 
-- 若锁存在,且唯一标识也匹配:则表明当前加锁请求为锁重入请求,故锁重入计数+1,并再次设置锁过期时间
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
    redis.call('hincrby', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
 
-- 若锁存在,但唯一标识不匹配:表明锁是被其他线程占用,当前线程无权解他人的锁,直接返回锁剩余过期时间
return redis.call('pttl', KEYS[1]);

附加我使用redission加锁解锁的代码

在这里插入代码片段

老生常谈,先加依赖

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.7.0</version>
</dependency>

配置Redisson

public class RedissonManager {
  private static Config config = new Config();
  //声明redisso对象
  private static Redisson redisson = null;
  
   //实例化redisson
	static{
	  config.useClusterServers()
	  // 集群状态扫描间隔时间,单位是毫秒
	 .setScanInterval(2000)
	  //cluster方式至少6个节点(3主3从,3主做sharding,3从用来保证主宕机后可以高可用)
	 .addNodeAddress("redis://127.0.0.1:6379" )
	 .addNodeAddress("redis://127.0.0.1:6380")
	 .addNodeAddress("redis://127.0.0.1:6381")
	 .addNodeAddress("redis://127.0.0.1:6382")
	 .addNodeAddress("redis://127.0.0.1:6383")
	 .addNodeAddress("redis://127.0.0.1:6384");
	 
	  //得到redisson对象
	  redisson = (Redisson) Redisson.create(config);
	}
	
	  //获取redisson对象的方法
	  public static Redisson getRedisson(){
	    return redisson;
	 }
}

锁的获取和释放(以查询用户为例)

    
    private RedisTemplate<String, Object> redisTemplate;
    
    private RedissonClient redissonClient;
。。。
        String key = "account:" + cardId;
        RLock lock = redissonClient.getLock("account_lock:" + cardId);

        try {
            log.info("----尝试加锁----" + "获取锁前的时间:" + LocalDateTime.now());
            //boolean locked = lock.tryLock(3, 8, TimeUnit.SECONDS);
            lock.lock(10, TimeUnit.SECONDS);
            if (lock.isLocked()) {
                Account account = (Account) redisTemplate.opsForValue().get(key);
                if (account == null) {
                    account = accountsMapper.findByAccountId(cardId);
                    if (account != null) {
                        redisTemplate.opsForValue().set(key, account, 30, TimeUnit.MINUTES);
                    }
                }
                TimeUnit.SECONDS.sleep(100);**//为了更直观看到加锁的变化**
                if (account != null) {
                    log.info("account: {}", account);
                } else {
                    log.warn("未能从数据库中找到对应的账户信息");
                }
                return account;
            } else {
                log.error("---尝试获取锁失败---");
                throw new InvalidCredentialsException("请求锁失败,点击过快,请重试");
            }
        } catch (InterruptedException e) {
            log.error("---请求锁中断异常---", e);
            throw new InvalidCredentialsException("请求锁失败,系统错误,请稍后重试");
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("----已释放锁----" + "释放锁的时间:" + LocalDateTime.now());
            }
        }
    }

补充一下:只有在未指定锁超时时间时才会使用看门狗!
然后这个看门都加锁机制就通了,很多大佬有一堆原理解析,就不献丑了,想深入了解的同志可以去自行研究

                     -----未完待续------
  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值