1. 事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发,故需要订
阅 __keyevent@0__:expired 通道
0表示db0 根据自己的dbindex选择合适的数字
2. 修改 redis.conf 文件
执行客户端命令 config set notify-keyspace-events Ex
# K 键空间通知,以__keyspace@<db>__为前缀 # E 键事件通知,以__keysevent@<db>__为前缀 # g del , expipre , rename 等类型无关的通用命令的通知, ... # $ String命令 # l List命令 # s Set命令 # h Hash命令 # z 有序集合命令 # x 过期事件(每次key过期时生成) # e 驱逐事件(当key在内存满了被清除时生成) # A g$lshzxe的别名,因此”AKE”意味着所有的事件
package com.zjht.solar.listenter;
import com.zjht.solar.act.constant.TransTypeString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* 缓存监听。
* Created by gaosiling on 2017/11/24。
*/
public class KeyExpiredListener2 extends JedisPubSub
implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger logger = LoggerFactory.getLogger(KeyExpiredListener2.class);
@Autowired
private JedisConnectionFactory jedisConnectionFactory;
@Autowired
private RedisTemplate redisTemplate;
// 初始化订阅时候的处理
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
}
// 取得订阅的消息后的处理
@Override
public void onPMessage(String pattern, String channel, String message) {
try {
logger.info("缓存过期处理缓存key=============" + message);
if (message.indexOf(TransTypeString.ACTIVITYCODE) == -1) {
return;
}
String key = message.substring("activityCode_".length());
logger.info("缓存过期处理" + key);
//删除过期的缓存
deleteKey(key);
} catch (Exception ex) {
logger.info("活动解析异常" + ex);
}
}
//应用启动时只调用一次,并创建一个线程处理redis缓存过期
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
new Thread(new Runnable() {
@Override
public void run() {
//需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
logger.info("启动新线程调用redis缓存监听");
JedisConnection jedisConnection =
(JedisConnection) jedisConnectionFactory.getConnection();
Jedis jedis = jedisConnection.getNativeConnection();
jedis.psubscribe(new KeyExpiredListener2(), "__key*__:*");
}
}).start();
}
public void deleteKey(String key) {
List<String> redisActivity = new ArrayList<>();
if (redisActivity == null || redisActivity.size() == 0) {
return;
}
Iterator<String> it = redisActivity.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.equals(key)) {
it.remove();
}
}
setActivity(key, redisActivity);
}
private void setActivity(String key, List<String> list) {
delete(key);
if (list.size() == 0) {
return;
}
redisTemplate.opsForList().leftPushAll(key, list);
redisTemplate.expireAt(key, new Date());
JedisConnection jedisConnection =
(JedisConnection) jedisConnectionFactory.getConnection();
Jedis jedis = jedisConnection.getNativeConnection();
for (String vo : list) {
try {
long time = new Date().getTime() - System.currentTimeMillis();
if (time < 0) {
time = 0;
}
jedis.setex(TransTypeString.ACTIVITYCODE + new Date(),
(int) (time / 1000), "nx");
} catch (Exception ex) {
logger.info("保存活动缓存监听失败" + key + ex);
}
}
jedisConnection.close();
}
/**
* 删除活动。
*
* @param key key。
*/
private void delete(String key) {
redisTemplate.delete(key);
}
}