当前位置: 移动技术网 > IT编程>数据库>Redis > Redis集群下过期key监听的实现代码

Redis集群下过期key监听的实现代码

2020年03月09日  | 移动技术网IT编程  | 我要评论

1. 前言

在使用redis集群时,发现过期key始终监听不到。网上也没有现成的解决方案。于是想,既然不能监听集群,那我可以建立多个redis连接,分别对每个redis的key过期进行监听。以上做法可能不尽人意,目前也没找到好的解决方案,如果有好的想法,请留言告知哦!不多说,直接贴我自己的代码!

2. 代码实现

关于redis集群配置代码此处不贴,直接贴配置监听类代码!

redis.host1: 10.113.56.68
redis.port1: 7030
redis.host2: 10.113.56.68
redis.port2: 7031
redis.host3: 10.113.56.68
redis.port3: 7032
redis.host4: 10.113.56.68
redis.port4: 7033
redis.host5: 10.113.56.68
redis.port5: 7034
redis.host6: 10.113.56.68
redis.port6: 7035
import org.springframework.beans.factory.annotation.value;
import org.springframework.cache.cachemanager;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.data.redis.cache.rediscachemanager;
import org.springframework.data.redis.connection.redisclusterconfiguration;
import org.springframework.data.redis.connection.jedis.jedisconnectionfactory;
import org.springframework.data.redis.core.redistemplate;
import org.springframework.data.redis.listener.redismessagelistenercontainer;
import org.springframework.data.redis.serializer.stringredisserializer;
import redis.clients.jedis.jedis;
import redis.clients.jedis.jedispoolconfig;

import java.util.arrays;

/**
 * @author xiabing5
 * @create 2019/8/6 14:46
 * @desc  监听redis中key过期事件
 **/
@configuration
public class redislistenerconfig {

  @value("${redis.host1}")
  private string host1;

  @value("${redis.host2}")
  private string host2;

  @value("${redis.host3}")
  private string host3;

  @value("${redis.host4}")
  private string host4;

  @value("${redis.host5}")
  private string host5;

  @value("${redis.host6}")
  private string host6;

  @value("${redis.port1}")
  private int port1;

  @value("${redis.port2}")
  private int port2;

  @value("${redis.port3}")
  private int port3;

  @value("${redis.port4}")
  private int port4;

  @value("${redis.port5}")
  private int port5;

  @value("${redis.port6}")
  private int port6;

  @bean
  jedispoolconfig jedispoolconfig(){
    jedispoolconfig jedispoolconfig = new jedispoolconfig();
    jedispoolconfig.setmaxidle(100);
    jedispoolconfig.setmaxwaitmillis(1000);
    return jedispoolconfig;
  }

  // redis-cluster不支持key过期监听,建立多个连接,对每个redis节点进行监听
  @bean
  redismessagelistenercontainer rediscontainer1() {
    final redismessagelistenercontainer container = new redismessagelistenercontainer();
    jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
    jedisconnectionfactory.sethostname(host1);
    jedisconnectionfactory.setport(port1);
    jedisconnectionfactory.setpoolconfig(jedispoolconfig());
    jedisconnectionfactory.afterpropertiesset();
    container.setconnectionfactory(jedisconnectionfactory);
    return container;
  }

  @bean
  redismessagelistenercontainer rediscontainer2() {
    final redismessagelistenercontainer container = new redismessagelistenercontainer();
    jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
    jedisconnectionfactory.sethostname(host2);
    jedisconnectionfactory.setport(port2);
    jedisconnectionfactory.setpoolconfig(jedispoolconfig());
    jedisconnectionfactory.afterpropertiesset();
    container.setconnectionfactory(jedisconnectionfactory);
    return container;
  }

  @bean
  redismessagelistenercontainer rediscontainer3() {
    final redismessagelistenercontainer container = new redismessagelistenercontainer();
    jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
    jedisconnectionfactory.sethostname(host3);
    jedisconnectionfactory.setport(port3);
    jedisconnectionfactory.setpoolconfig(jedispoolconfig());
    jedisconnectionfactory.afterpropertiesset();
    container.setconnectionfactory(jedisconnectionfactory);
    return container;
  }

  @bean
  redismessagelistenercontainer rediscontainer4() {
    final redismessagelistenercontainer container = new redismessagelistenercontainer();
    jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
    jedisconnectionfactory.sethostname(host4);
    jedisconnectionfactory.setport(port4);
    jedisconnectionfactory.setpoolconfig(jedispoolconfig());
    jedisconnectionfactory.afterpropertiesset();
    container.setconnectionfactory(jedisconnectionfactory);
    return container;
  }

  @bean
  redismessagelistenercontainer rediscontainer5() {
    final redismessagelistenercontainer container = new redismessagelistenercontainer();
    jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
    jedisconnectionfactory.sethostname(host5);
    jedisconnectionfactory.setport(port5);
    jedisconnectionfactory.setpoolconfig(jedispoolconfig());
    jedisconnectionfactory.afterpropertiesset();
    container.setconnectionfactory(jedisconnectionfactory);
    return container;
  }

  @bean
  redismessagelistenercontainer rediscontainer6() {
    final redismessagelistenercontainer container = new redismessagelistenercontainer();
    jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory();
    jedisconnectionfactory.sethostname(host6);
    jedisconnectionfactory.setport(port6);
    jedisconnectionfactory.setpoolconfig(jedispoolconfig());
    jedisconnectionfactory.afterpropertiesset();
    container.setconnectionfactory(jedisconnectionfactory);
    return container;
  }

  @bean
  rediskeyexpirationlistener rediskeyexpirationlistener1() {
    return new rediskeyexpirationlistener(rediscontainer1());
  }

  @bean
  rediskeyexpirationlistener rediskeyexpirationlistener2() {
    return new rediskeyexpirationlistener(rediscontainer2());
  }

  @bean
  rediskeyexpirationlistener rediskeyexpirationlistener3() {
    return new rediskeyexpirationlistener(rediscontainer3());
  }

  @bean
  rediskeyexpirationlistener rediskeyexpirationlistener4() {
    return new rediskeyexpirationlistener(rediscontainer4());
  }

  @bean
  rediskeyexpirationlistener rediskeyexpirationlistener5() {
    return new rediskeyexpirationlistener(rediscontainer5());
  }

  @bean
  rediskeyexpirationlistener rediskeyexpirationlistener6() {
    return new rediskeyexpirationlistener(rediscontainer6());
  }

}
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.data.redis.connection.message;
import org.springframework.data.redis.listener.keyexpirationeventmessagelistener;
import org.springframework.data.redis.listener.redismessagelistenercontainer;
import java.util.date;

/**
 * @author xiabing5
 * @create 2019/9/4 9:47
 * @desc  redis过期监听
 **/
public class rediskeyexpirationlistener extends keyexpirationeventmessagelistener {
  @autowired
  redisutil redisutil;
  @autowired
  loginuserstatisticsmapper loginuserstatisticsmapper;
  public rediskeyexpirationlistener(redismessagelistenercontainer listenercontainer) {
    super(listenercontainer);
  }
  @override
  public void onmessage(message message, byte[] pattern) {
    // 用户做自己的业务处理即可,message.tostring()可以获取失效的key
    string mesg = message.tostring();   
  }
}

3. redis防止过期key重复监听

对于项目集群情况下,部署多个服务后,容易出现redis过期被多个服务同时监听到,从而执行相同的业务逻辑,这不是我们期望的。单机部署下方法的同步可以采用synchronize关键字。但集群下,就得采用分布式锁。在需要加锁的地方,只要加锁和解锁即可。此处正好写到redis,那就贴一个自己用的redis分布式锁。

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.component;
import redis.clients.jedis.jedis;
import java.util.collections;
import java.util.uuid;
/**
 * @author xiabing5
 * @create 2019/9/6 15:54
 * @desc  redis分布式锁
 **/
@component
public class redislock {
  @autowired
  jedis jedis;
  private static final string set_if_not_exist = "nx"; // nx表示如果不存在key就设置value
  private static final string set_with_expire_time = "px"; // px表示毫秒
  // 加锁
  public string trylock(string key,long acquiretimeout) {
    // 生成随机value
    string identifiervalue = uuid.randomuuid().tostring();
    // 设置超时时间
    long endtime = system.currenttimemillis() + acquiretimeout;
    // 循环获取锁
    while (system.currenttimemillis() < endtime) {
      string result = jedis.set(key,identifiervalue, set_if_not_exist, set_with_expire_time, acquiretimeout);
      if("ok".equals(result)) {
        return identifiervalue;
      }
    }
    return null;
  }
  // 解锁
//  public void dellock(string key,string identifiervalue) {
//    // 判断是否是同一把锁
//    try{
//      if(jedis.get(key).equals(identifiervalue)){
//        // 此处操作非原子性,容易造成释放非自己的锁
//        jedis.del(key);
//      }
//    }catch(exception e) {
//      e.printstacktrace();
//    }
//  }
  // 使用lua代码解锁
  public void dellock(string key,string identifiervalue) {
    try{
      string script = "if redis.call('get', keys[1]) == argv[1] then return redis.call('del', keys[1]) else return 0 end";
      long result = (long) jedis.eval(script, collections.singletonlist(key), collections.singletonlist(identifiervalue));
      if (1 == result) {
        system.out.println(result+"释放锁成功");
      } if (0 == result) {
        system.out.println(result+"释放锁失败");
      }
    }catch (exception e) {
      e.printstacktrace();
    }
  }
}

4. 总结

自己实现的一个小demo,废话比较少。小白自己写的配置类,理解有问题请留言!自己实现的方案感觉不妥,只是基本完成需求,还得继续研究。

以上所述是小编给大家介绍的redis集群下过期key监听的实现代码,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网