Java实现Redis过期数据清除

1 过期策略

1.0 定期删除

  • 主动删除
  • 定期删除设置一个时间间隔,每个时间段都会检测是否有键过期,定期随机抽取键检查和删除.

1.2 惰性删除

  • 被动删除
  • 惰性删除不会在键过期是立即删除,而是当外部获取这个键时删除.

1.3 定时删除

  • 主动删除
  • 创建键时设置过期时间,创建一个定时器,当键达到过期时间阈值时,立即删除键,删除该时刻过期的所有键,不会考虑此时机器所处状态.

2 内存淘汰

序号策略描述
1noeviction当内存不足以存储新数据写入时,新写入操作报错
2allkeys-lru当内存不足以存储新数据写入时,在键空间中移除最近最少使用的key
3allkeys-random当内存不足以存储新数据写入时,在键空间中随机移除某个key
4volatile-lru当内存不足以存储新数据写入时,在设置了过期时间的键中,移除最近最少使用的key
5volatile-random当内存不足以存储新数据写入时,在设置了过期时间的键中,随机移除某个key
6volatile-ttl当内存不足以存储新数据写入时,在设置了过期时间的键中,优先移除有更早过期时间的key

3 数据过期提醒

3.1 配置过期提醒

sudo vim /etc/redis/redis.conf
notify-keyspace-events Ex

3.2 配置监听

package com.sb.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;


import java.io.Serializable;
import java.time.Duration;
import java.lang.reflect.Method;

@Configuration 
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport{
    @Autowired 
    private RedisConnectionFactory redisConnectionFactory;
    @Bean 
    public KeyGenerator wiselyKeyGenerator(){
        return new KeyGenerator(){
            @Override 
            public Object generate(Object target, Method method, Object... params){
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for(Object obj:params){
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

   
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
                                                            .defaultCacheConfig()
                                                            .entryTtl(Duration.ofSeconds(60));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();

    }

    @Bean 
    public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory){
        RedisTemplate<String, Serializable> template = new RedisTemplate<>();
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
    
    @Bean 
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}

3.3 配置事件处理

package com.sb.util;

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component 
public class RedisKeyExpirationListenerUtil extends KeyExpirationEventMessageListener{
    static Logger logger = LoggerFactory.getLogger(RedisKeyExpirationListenerUtil.class);
    public RedisKeyExpirationListenerUtil(RedisMessageListenerContainer listenerContainer){
        super(listenerContainer);
    }

    @Override 
    public void onMessage(Message message, byte[] pattern){
        String expiredKey = message.toString();
        // TODO
        logger.info("data expired:{}", expiredKey);
    }
}

4 小结

序号描述
1Redis过期清除策略有三种,定期清除,定时清除,惰性清除,其中惰性清除为被动清除,定时和定期为主动清除,定期为定期随机清除,定时为清除所有过期数据
2数据过期事件提醒配置Redis提醒,设定监听容器及监听事件,监听事件中执行清除数据时的逻辑,同时可获取删除的key,通过key和持久化的数据库同步数据
3缓存过期数据和硬盘数据同步存储,过期时同步删除,保证服务宕机数据不丢失

【参考文献】
[1]https://www.cnblogs.com/mengchunchen/p/10039467.html
[2]https://blog.csdn.net/qq_35981283/article/details/70156422
[3]https://www.jianshu.com/p/c37ad337146f
[4]https://www.jianshu.com/p/106f0eae07c8
[5]https://blog.csdn.net/m0_37367413/article/details/84320562

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值