Maison  >  Article  >  base de données  >  Quelle est la solution permettant à Java d'exploiter Redis et de définir l'expiration tôt le matin du lendemain ?

Quelle est la solution permettant à Java d'exploiter Redis et de définir l'expiration tôt le matin du lendemain ?

WBOY
WBOYavant
2023-05-26 15:40:591290parcourir

Java utilise Redis pour définir l'expiration tôt le matin du lendemain

Scénario

Lors de l'interrogation des données, j'ai rencontré le problème de devoir configurer les données pour qu'elles expirent le lendemain dans Redis, mais Redis n'avait pas d'API correspondante , j'ai donc dû le résoudre moi-même

L'idée

Calculer le décalage horaire entre le petit matin du lendemain et l'heure actuelle, et définir le décalage horaire comme heure d'expiration de redis pour obtenir l'effet souhaité

Code

/**
     * 计算第二天凌晨与当前时间的时间差秒数
     * @param
     * @return java.lang.Long
     * @author shy
     * @date 2021/3/12 18:10
     */
    public static Long getNowToNextDaySeconds() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }

Après avoir obtenu le décalage horaire, le reste est en gros Il n'y aura aucun problème.

Ci-joint la classe d'outils Redis :

/**
 * 操作redis
 * @author shy
 * @date 2020/12/10 10:01
 */
@Service
public class RedisService {
	
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@Autowired
    private RedisTemplate<String, Object> redisTemplate;
	
	/**
	 * 判断String类型key是否存在
	 *
	 * @param key
	 * @return 
	 * @author shy
	 * @date 2018年11月13日 下午1:40:37
	 */
	public boolean hasStringKey(String key) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		return stringRedisTemplate.opsForValue().getOperations().hasKey(key);
	}
	
	/**
	 * 判断String类型key是否存在
	 *
	 * @param key
	 * @return 
	 * @author shy
	 * @date 2018年11月13日 下午1:43:51
	 */
	public boolean nonStringKey(String key) {
		return !hasStringKey(key);
	}
	/**
	 * 设置String类型key,String类型value,过期时间timeout,TimeUnit
	 *
	 * @param key
	 * @param value
	 * @param timeout
	 * @param timeUnit
	 * @author shy
	 * @date 2018年12月10日13:53:38
	 */
	public void setStringKey(String key, String value, Long timeout, TimeUnit timeUnit) {
		if (StringUtils.isBlank(key) || Objects.isNull(timeout)) {
			throw new EmptyParameterException();
		}
		stringRedisTemplate.opsForValue().set(key, value, timeout, timeUnit);
	}
	
	public void setStringKey(String key, String value) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		stringRedisTemplate.opsForValue().set(key, value);
	}
	/**
	 * 获取String类型value
	 *
	 * @param key
	 * @return
	 * @author shy
	 * @date 2018年11月12日 下午7:09:31
	 */
	public String getStringValue(String key) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		return stringRedisTemplate.opsForValue().get(key);
	}
	
	/**
	 *	获取Key的过期时间
	 *
	 * @param key
	 * @return
	 * @author shy
	 * @date 2019年4月25日17:28:36
	 */
	public Long getExpire(String key) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		return stringRedisTemplate.getExpire(key);
	}
	
	/**
	 *	设置Key的过期时间
	 *
	 * @param key
	 * @return
	 * @author shy
	 * @date 2019年4月25日17:28:36
	 */
	public Boolean setExpire(String key,Long timeout, TimeUnit timeUnit) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		return stringRedisTemplate.expire(key, timeout, timeUnit);
	}	
	
	/**
	 * value自增+n
	 * @param key
	 * @return
	 * @author shy
	 * @date 2019年4月8日15:54:30
	 */
	public Long setIncrementValue(String key) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		return stringRedisTemplate.opsForValue().increment(key, 1L);
	}
	/**
	 * 设置String类型key,Object类型value,过期时间timeout
	 *
	 * @param key
	 * @param value
	 * @param timeout
	 * @author shy
	 * @date 2018年12月10日13:54:07
	 */
	public void setObjectKey(String key, Object value, Long timeout,TimeUnit time) {
		if (StringUtils.isBlank(key) || Objects.isNull(timeout)) {
			throw new EmptyParameterException();
		}
		redisTemplate.opsForValue().set(key, value, timeout, time);
	}
	
	public void setObjectKey(String key, Object value) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		redisTemplate.opsForValue().set(key, value);
	}
	
	/**
	 * 获取Object类型value
	 *
	 * @param key
	 * @param clazz
	 * @return 
	 * @author shy
	 * @date 2019年11月6日10:01:30
	 */
	@SuppressWarnings("unchecked")
	public <T> T getObjectValue(String key, Class<T> clazz) {
		if (StringUtils.isBlank(key)) {
			return null;
		}
		return (T) redisTemplate.opsForValue().get(key);
	}
	
	/**
	 * 移除单个String类型key
	 *
	 * @param key 
	 * @author shy
	 * @date 2018年11月13日 上午10:42:01
	 */
	public void removeSingleStringKey(String key) {
		if (StringUtils.isBlank(key)) {
			throw new EmptyParameterException();
		}
		stringRedisTemplate.opsForValue().getOperations().delete(key);
	}
	
	/**
	 * 移除Collection<String>类型keys
	 *
	 * @param keys 
	 * @author shy
	 * @date 2018年11月13日 下午3:15:16
	 */
	public void removeMultiStringKey(Collection<String> keys) {
		if (CollectionUtils.isNotEmpty(keys)) {
			stringRedisTemplate.opsForValue().getOperations().delete(keys);
		}
	}
	
	/**
	 * redis key 模糊查询
	 * @author shy
	 * @date 2021年1月4日 上午11:21:45
	 * @param key
	 * @return
	 */
	public Set<String> queryStringKeys(String key) {
		 return redisTemplate.keys(key + "*");
	}
}

Introduction à la fonction de politique d'expiration de Redis

Lorsque nous utilisons Redis, nous définissons généralement un délai d'expiration. Bien sûr, certains ne définissent pas de délai d'expiration, ce qui signifie qu'il n'expirera jamais. .

Lorsque nous définissons le délai d'expiration, comment Redis détermine-t-il s'il a expiré et quelle stratégie est utilisée pour le supprimer.

Définir le délai d'expiration

Lorsque nous définissons la clé, nous pouvons donner un délai d'expiration, qui est le délai d'expiration. Par exemple, spécifier que cette clé ne peut survivre qu'une heure. pendant une heure, puis après l'heure suivante, comment Redis supprime-t-il ce lot de clés ?

La réponse est : suppression régulière + suppression paresseuse.

La suppression dite régulière signifie que par défaut, redis sélectionne au hasard certaines clés avec un délai d'expiration défini toutes les 100 ms, vérifie si elles ont expiré et les supprime si elles expirent. Le parcours de toutes les clés avec des délais d'expiration toutes les 100 ms entraînera une baisse significative des performances, veuillez noter. Redis sélectionnera en fait au hasard certaines clés à vérifier et à supprimer toutes les 100 millisecondes.

Mais le problème est qu'une suppression régulière peut entraîner l'expiration de nombreuses clés qui n'ont pas été supprimées une fois le temps écoulé, elles doivent donc être supprimées paresseusement, c'est-à-dire que lorsque vous obtenez une clé, redis vérifiera si l'expiration est terminée. l'heure est définie pour cette clé. Expirée ? S'il expire, il sera supprimé.

En combinant les deux méthodes ci-dessus, il est garanti que les clés expirées seront supprimées. Toutes les clés expirées ne seront pas automatiquement supprimées lorsque le délai d'expiration est atteint, de sorte que l'utilisation de la mémoire ne sera pas réduite après l'expiration.

Mais en fait, cela reste un problème. Si un grand nombre de clés expirées sont manquées lors d'une suppression régulière, et qu'elles ne sont pas vérifiées à temps et qu'une suppression différée est effectuée, un grand nombre de clés expirées s'accumuleront dans la mémoire et consommer de la mémoire redis. Cette situation Comment y faire face ?

La réponse est : utilisez le mécanisme d'élimination de la mémoire.

Élimination de la mémoire

Si la mémoire de redis prend trop de place, une élimination sera effectuée à ce moment-là. Il existe quelques stratégies comme suit :

  • noeviction : lorsque la mémoire est épuisée. pas assez pour accueillir les données nouvellement écrites, une erreur sera signalée pour les données nouvellement écrites et ce scénario réel n'est généralement pas utilisé. noeviction:当内存不足以容纳新写入数据时,新写入数据会报错,这个实际场景一般不会使用。

  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最少使用的key(这个是最常用的)

  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般用的比较少。

  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。

  • volatile-ttl

allkeys-lru : Lorsque la mémoire n'est pas suffisante pour accueillir les données nouvellement écrites, dans l'espace clé, supprimez la clé la moins utilisée (c'est la plus couramment utilisée)

🎜🎜 allkeys-random : lorsque la mémoire n'est pas suffisante pour accueillir les données nouvellement écrites, une clé est supprimée de manière aléatoire de l'espace clé. Ceci est généralement moins utilisé. 🎜🎜🎜🎜volatile-lru : lorsque la mémoire n'est pas suffisante pour accueillir les données nouvellement écrites, dans l'espace clé avec un délai d'expiration défini, supprimez la clé la moins récemment utilisée. 🎜🎜🎜🎜volatile-random : lorsque la mémoire n'est pas suffisante pour accueillir les données nouvellement écrites, une clé est supprimée de manière aléatoire de l'espace clé avec un délai d'expiration défini. 🎜🎜🎜🎜volatile-ttl : lorsque la mémoire n'est pas suffisante pour accueillir les données nouvellement écrites, dans l'espace clé avec un délai d'expiration défini, les clés avec un délai d'expiration antérieur seront supprimées en premier. 🎜🎜🎜🎜L'élimination de la mémoire déclenchera la condition d'élimination pour supprimer certaines clés, ce qui est également la raison pour laquelle les clés sont perdues sans définir le délai d'expiration. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer