【Redission】Redission sort_set自动清理过期value源码解析

一、技术

  1. spring-boot
  2. redission

二、实现

在发送邮件过程中,先校验,当前key中值的数量,如果超过配置的数量,则切换,每次发送成功则向redis中的sort_set新增一个值

代码实现

  public void add(String key) {
    RSetCache<Long> set = redissonClient.getSetCache(key);// 根据key查找sort_set,如果存在则获取,不存在则新增
    Random random = new Random();
    set.add(new Date().getTime() +  random.nextInt(100), expire, TimeUnit.HOURS);//向sort_set添加记录,并且设置超时时间为expire个小时
    set.expire(expire, TimeUnit.HOURS);//设置当前key的超时时间
  }
RSetCache<String> set = redissonClient.getSetCache(key);
    if (set.size() < upperLimit) {
      return;
    }

三、原理

项目启动初始化RedissonClient过程时

public RedissionClient createRedissionClient(){
      Config config = new Config();
      config.useSentinelServers()
          .setMasterName(masterName)
          .addSentinelAddress(address)
          .setConnectTimeout(30000)
          .setTimeout(10000)
          .setRetryAttempts(5)
          .setRetryInterval(3000);
      s = Redisson.create(config); //1
}

会先创建Redission对象

    public static RedissonClient create(Config config) {
        Redisson redisson = new Redisson(config);
        if (config.isReferenceEnabled()) {
            redisson.enableRedissonReferenceSupport();
        }
        return redisson;
    }

Redission初始化过程时

    protected Redisson(Config config) {
        this.config = config;
        Config configCopy = new Config(config);

        connectionManager = ConfigSupport.createConnectionManager(configCopy);//连接redis
        evictionScheduler = new EvictionScheduler(connectionManager.getCommandExecutor());//创建定时器
        writeBehindService = new WriteBehindService(connectionManager.getCommandExecutor());
    }

当我们调用redissonClient.getSetCache时

    @Override
    public <V> RSetCache<V> getSetCache(String name) {
        return new RedissonSetCache<V>(evictionScheduler, connectionManager.getCommandExecutor(), name, this);
    }

创建RedissonSetCache对象

    public RedissonSetCache(EvictionScheduler evictionScheduler, CommandAsyncExecutor commandExecutor, String name, RedissonClient redisson) {
        super(commandExecutor, name);
        if (evictionScheduler != null) { //判断定时器是不是为空
            evictionScheduler.schedule(getName(), 0);//如果不为空则执行
        }
        this.evictionScheduler = evictionScheduler;
        this.redisson = redisson;
    }

org.redisson.eviction.EvictionScheduler#schedule(java.lang.String, long)

    public void schedule(String name, long shiftInMilliseconds) {
        EvictionTask task = new ScoredSetEvictionTask(name, executor, shiftInMilliseconds);
        EvictionTask prevTask = tasks.putIfAbsent(name, task); // 添加到任务池中
        if (prevTask == null) {//如果不存在,则第一次执行下任务
            task.schedule();
        }
    }

org.redisson.eviction.EvictionTask#schedule,每5秒执行一次。

    public void schedule() {
        scheduledFuture = executor.getConnectionManager().getGroup().schedule(this, delay, TimeUnit.SECONDS);//设置定时器 5秒执行1次
    }

定时器会执行org.redisson.eviction.ScoredSetEvictionTask#execute方法,删除score >0 and score < 当前时间戳的数据

    @Override
    RFuture<Integer> execute() {
        return executor.writeAsync(name, LongCodec.INSTANCE, RedisCommands.ZREMRANGEBYSCORE, name, 0, System.currentTimeMillis() - shiftInMilliseconds);
    }

总结:Reidssion是通过定时器定时删除sort_set中过期的value,其中插入的时候,score为当前时间戳 + 过期时间,所以vaule的score都是为未来的时间。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值