redis设置键的过期时间

redis设置键的过期时间,第1张

❑EXPIRE<key><ttl>命令用于将键key的生存时间设置为ttl秒。

❑PEXPIRE<key><ttl>命令用于将键key的生存时间设置为ttl毫秒。

❑EXPIREAT<key><timestamp>命令用于将键key的过期时间设置为timestamp所指定的秒数时间戳。

❑PEXPIREAT<key><timestamp>命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳。

例如

redis对存储值的过期处理实际上是针对该值的键(key)处理的,即时间的设置也是设置key的有效时间。Expires字典保存了所有键的过期时间,Expires也被称为过期字段。

四种处理策略

EXPIRE 将key的生存时间设置为ttl秒

PEXPIRE 将key的生成时间设置为ttl毫秒

EXPIREAT 将key的过期时间设置为timestamp所代表的的秒数的时间戳

PEXPIREAT 将key的过期时间设置为timestamp所代表的的毫秒数的时间戳

其实以上几种处理方式都是根据PEXPIREAT来实现的,设置生存时间的时候是redis内部计算好时间之后在内存处理的,最终的处理都会转向PEXPIREAT。

1、2两种方式是设置一个过期的时间段,就是咱们处理验证码最常用的策略,设置三分钟或五分钟后失效,把分钟数转换成秒或毫秒存储到redis中。

3、4两种方式是指定一个过期的时间 ,比如优惠券的过期时间是某年某月某日,只是单位不一样。

@Bean

public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {

// 配置序列化

// 统一默认配置,TTL为60秒

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()

.entryTtl(Duration.ofSeconds(60))

// 针对不同key可以个性化设置

Set<String>cacheNames = new HashSet<>()

cacheNames.add("account")

cacheNames.add("post")

// 对每个缓存空间应用不同的配置

Map<String, RedisCacheConfiguration>configMap = new HashMap<>()

configMap.put("account", config.entryTtl(Duration.ofSeconds(30)))

configMap.put("post", config)

return RedisCacheManager.builder(redisConnectionFactory)

.cacheDefaults(config)

.initialCacheNames(cacheNames)

.withInitialCacheConfigurations(configMap)

.build()

}

自定义每个缓存的TTL和自动刷新

上面的设置虽然可以提前设定每个cacheName的ttl,但是不够细,虽然Cacheable的sync可以防止缓存击穿,但是无法防止缓存雪崩。

我们可以使用AOP来完成自动刷新和自定义TTL。

代码写的比较糙,只是个例子,可以自己修改。

自己写TTL注解

import org.springframework.core.annotation.AliasFor

import java.lang.annotation.*

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Inherited

public @interface CacheTTL {

@AliasFor("ttl")

long value() default 60

@AliasFor("value")

long ttl() default 60

long preExpireRefresh() default 10

}

AOP实现

import org.aspectj.lang.JoinPoint

import org.aspectj.lang.annotation.After

import org.aspectj.lang.annotation.Aspect

import org.aspectj.lang.reflect.MethodSignature

import org.springframework.cache.annotation.Cacheable

import org.springframework.cache.interceptor.SimpleKeyGenerator

import org.springframework.core.annotation.AnnotationUtils

import org.springframework.core.annotation.Order

import org.springframework.data.redis.core.RedisTemplate

import org.springframework.stereotype.Component

import java.lang.reflect.Method

import java.util.Arrays

import java.util.concurrent.TimeUnit

import java.util.concurrent.atomic.AtomicInteger

//这里必须要比Cacheable的Aspect优先级要高

@Order(value=1)

@Aspect

@Component

public class CustomCacheAspect {

private final RedisTemplate<String,Object>redisTemplate

private final SimpleKeyGenerator keyGenerator = new SimpleKeyGenerator()

private final AtomicInteger asyncLock = new AtomicInteger(0)

public CustomCacheAspect(RedisTemplate<String, Object>redisTemplate) {

this.redisTemplate = redisTemplate

}

@After(value="execution(* *..*.*(..))")

public void after(JoinPoint point)

{

Object target = point.getTarget()

MethodSignature signature = (MethodSignature) point.getSignature()

Method method = signature.getMethod()

try {

if (method.isAnnotationPresent(CacheTTL.class) &&method.isAnnotationPresent(Cacheable.class)) {

CacheTTL ttlData = AnnotationUtils.getAnnotation(method, CacheTTL.class)

Cacheable cacheAbleData = AnnotationUtils.getAnnotation(method, Cacheable.class)

long ttl = ttlData.ttl()

long preExpireRefresh = ttlData.preExpireRefresh()

String[] cacheNames = cacheAbleData.cacheNames()

//默认的keyGenerator生成,如果自定义了自己改一下

Object key = keyGenerator.generate(target, method, point.getArgs())

updateExpire(cacheNames,key,preExpireRefresh,ttl)

}

} catch (Exception e) {

e.printStackTrace()

}

}

public void updateExpire(String[] cacheNames,Object key,long preExpireRefresh,long ttl){

if (asyncLock.compareAndSet(0,1)){

Arrays.stream(cacheNames).parallel().forEach(cacheName->{

cacheName = cacheName + "::" + key

long expire = redisTemplate.getExpire(cacheName,TimeUnit.SECONDS)

if (expire>0 &&expire<=preExpireRefresh || expire >ttl || expire == -1){

redisTemplate.expire(cacheName, ttl, TimeUnit.SECONDS)

}

})

asyncLock.set(0)

}

}

}

使用

@Cacheable(cacheNames = "account",key="#id",sync = true)

@CacheTTL(ttl = 60,preExpireRefresh = 10)

public Account findAccountByID(int id) {

return accountDao.findAccountByID(id)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11544576.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存