Maison Java javaDidacticiel Pour implémenter le cache local Java, commencez par ces points

Pour implémenter le cache local Java, commencez par ces points

Oct 11, 2019 pm 04:25 PM
java

La mise en cache, je crois que tout le monde la connaît. Dans le projet, la mise en cache est définitivement indispensable. Il existe de nombreux outils de mise en cache sur le marché, comme Redis, Guava Cache ou encore EHcache.

Pour implémenter le cache local Java, commencez par ces points

Je pense que tout le monde doit être très familier avec ces outils, nous n'en parlerons donc pas aujourd'hui. Parlons de la façon de mettre en œuvre la mise en cache locale. Se référant aux outils ci-dessus, pour obtenir un meilleur cache local, frère Pingtou estime que nous devrions partir des trois aspects suivants.

1. Sélection des collections de stockage

Pour implémenter la mise en cache locale, le conteneur de stockage doit être une structure de données sous forme de clé/valeur. notre collecte de cartes couramment utilisée. Il existe HashMap, Hashtable et ConcurrentHashMap dans Map parmi lesquels choisir. Si nous ne considérons pas les problèmes de sécurité des données en cas de concurrence élevée, nous pouvons choisir HashMap. Si nous considérons les problèmes de sécurité des données en cas de concurrence élevée, nous pouvons choisir l'un des Hashtable et. ConcurrentHashMap. Collection, mais nous préférons ConcurrentHashMap car les performances de ConcurrentHashMap sont meilleures que celles de Hashtable.

2. Traitement du cache expiré

Le cache étant stocké directement dans la mémoire, si nous ne gérons pas le cache expiré, la mémoire sera occupée par une grande nombre de caches invalides, ce qui n'est pas ce que nous voulons Oui, nous devons donc nettoyer ces caches invalides. Le traitement du cache expiré peut être implémenté en se référant à la stratégie Redis. Redis adopte une stratégie de suppression régulière + élimination paresseuse.

Stratégie de suppression périodique

La stratégie de suppression périodique consiste à détecter les caches expirés à intervalles réguliers et à les supprimer. L'avantage de cette stratégie est qu'elle garantit la suppression des caches expirés. Il existe également des inconvénients. Les caches expirés peuvent ne pas être supprimés à temps. Cela est lié à la fréquence de synchronisation que nous définissons. Un autre inconvénient est que s'il y a beaucoup de données en cache, chaque détection mettra également beaucoup de pression sur la tasse. .

Stratégie d'élimination paresseuse

La stratégie d'élimination paresseuse consiste à déterminer d'abord si le cache a expiré lors de l'utilisation du cache. S'il expire, supprimez-le et revenez vide. L'avantage de cette stratégie est qu'elle ne peut déterminer si le produit a expiré que lors de la recherche, ce qui a moins d'impact sur le CUP. En même temps, cette stratégie présente un inconvénient fatal. Lorsqu'un grand nombre de caches sont stockés, ces caches ne sont pas utilisés et ont expiré, et ils deviendront des caches invalides. Ces caches invalides occuperont une grande partie de votre espace mémoire. et éventuellement provoquer un débordement de la mémoire du serveur.

Nous avons brièvement examiné les deux stratégies de traitement du cache d'expiration de Redis. Chaque stratégie a ses propres avantages et inconvénients. Par conséquent, lors de l’utilisation, nous pouvons combiner les deux stratégies, et l’effet combiné est toujours très idéal.

3. Stratégie d'élimination du cache

L'élimination du cache doit être distinguée du traitement de l'élimination du cache expiré lorsque le nombre de nos caches atteint le nombre de caches que nous avons spécifié. Après tout, notre mémoire n’est pas infinie. Si nous devons continuer à ajouter des caches, nous devons éliminer certains caches des caches existants selon une certaine stratégie pour faire de la place aux caches nouvellement ajoutés. Découvrons plusieurs stratégies d'élimination de cache couramment utilisées.

Politique du premier entré, premier sorti

Lorsque l'espace du cache est insuffisant, les données qui entrent dans le cache en premier seront d'abord effacées pour libérer un nouvel espace pour accepter de nouveaux données. Cette stratégie compare principalement le temps de création des éléments mis en cache. Dans certains scénarios qui nécessitent une efficacité des données relativement élevée, ce type de stratégie peut être considéré comme donnant la priorité à la garantie que les données les plus récentes sont disponibles.

Stratégie la moins utilisée

Qu'il soit expiré ou non, en fonction du nombre de fois que l'élément a été utilisé, les éléments avec moins d'utilisations seront effacés pour libérer de l'espace. Cette stratégie compare principalement le hitCount (nombre de hits) des éléments. Ce type de stratégie peut être sélectionné dans des scénarios où la validité des données haute fréquence est assurée.

Stratégie la moins récemment utilisée

Qu'elle soit expirée ou non, en fonction du dernier horodatage utilisé de l'élément, effacez l'élément avec l'horodatage le plus utilisé pour libérer de l'espace. Cette stratégie compare principalement l'heure à laquelle le cache a été utilisé pour la dernière fois par get. Il est plus applicable dans les scénarios de données chaudes, et la priorité est donnée à garantir la validité des données chaudes.

Stratégie d'élimination aléatoire

Éliminez de manière aléatoire un cache, qu'il soit expiré ou non. S'il n'y a aucune exigence concernant les données mises en cache, vous pouvez envisager d'utiliser cette stratégie.

Stratégie de non-élimination

Lorsque le cache atteint la valeur spécifiée, aucun cache ne sera éliminé, mais aucun nouveau cache ne sera ajouté. Aucun autre cache ne pourra être ajouté. jusqu'à ce qu'un cache soit éliminé.

Les trois points ci-dessus doivent être pris en compte pour implémenter un cache local. Après avoir lu ceci, nous devrions savoir comment implémenter un cache local.

Implémenter le cache local

Dans cette démo, nous utilisons ConcurrentHashMap comme collection de stockage, afin de pouvoir garantir la sécurité du cache même dans des situations de forte concurrence. Pour le traitement du cache expiré, j'ai utilisé ici uniquement la stratégie de suppression planifiée et je n'ai pas utilisé la stratégie de suppression planifiée + élimination paresseuse. Vous pouvez l'essayer vous-même et utiliser ces deux stratégies pour le traitement du cache expiré. En termes d'expulsion du cache, j'utilise ici une stratégie de moindre utilisation. Bon, maintenant que nous connaissons la sélection technique, jetons un œil à l'implémentation du code.

Classe d'objet Cache

public class Cache implements Comparable<Cache>{
    // 键
    private Object key;
    // 缓存值
    private Object value;
    // 最后一次访问时间
    private long accessTime;
    // 创建时间
    private long writeTime;
    // 存活时间
    private long expireTime;
    // 命中次数
    private Integer hitCount;
    ...getter/setter()...
Copier après la connexion

Ajouter un cache

/**
 * 添加缓存
 *
 * @param key
 * @param value
 */
public void put(K key, V value,long expire) {
    checkNotNull(key);
    checkNotNull(value);
    // 当缓存存在时,更新缓存
    if (concurrentHashMap.containsKey(key)){
        Cache cache = concurrentHashMap.get(key);
        cache.setHitCount(cache.getHitCount()+1);
        cache.setWriteTime(System.currentTimeMillis());
        cache.setAccessTime(System.currentTimeMillis());
        cache.setExpireTime(expire);
        cache.setValue(value);
        return;
    }
    // 已经达到最大缓存
    if (isFull()) {
        Object kickedKey = getKickedKey();
        if (kickedKey !=null){
            // 移除最少使用的缓存
            concurrentHashMap.remove(kickedKey);
        }else {
            return;
        }
    }
    Cache cache = new Cache();
    cache.setKey(key);
    cache.setValue(value);
    cache.setWriteTime(System.currentTimeMillis());
    cache.setAccessTime(System.currentTimeMillis());
    cache.setHitCount(1);
    cache.setExpireTime(expire);
    concurrentHashMap.put(key, cache);
}
Copier après la connexion

Obtenir le cache

/**
 * 获取缓存
 *
 * @param key
 * @return
 */
public Object get(K key) {
    checkNotNull(key);
    if (concurrentHashMap.isEmpty()) return null;
    if (!concurrentHashMap.containsKey(key)) return null;
    Cache cache = concurrentHashMap.get(key);
    if (cache == null) return null;
    cache.setHitCount(cache.getHitCount()+1);
    cache.setAccessTime(System.currentTimeMillis());
    return cache.getValue();
}
Copier après la connexion

Obtenir le cache le moins utilisé

/**
     * 获取最少使用的缓存
     * @return
     */
    private Object getKickedKey() {
        Cache min = Collections.min(concurrentHashMap.values());
        return min.getKey();
    }
Copier après la connexion

Méthode de détection du cache expiré

/**
 * 处理过期缓存
 */
class TimeoutTimerThread implements Runnable {
    public void run() {
        while (true) {
            try {
                TimeUnit.SECONDS.sleep(60);
                expireCache();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建多久后,缓存失效
     *
     * @throws Exception
     */
    private void expireCache() throws Exception {
        System.out.println("检测缓存是否过期缓存");
        for (Object key : concurrentHashMap.keySet()) {
            Cache cache = concurrentHashMap.get(key);
            long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()
                    - cache.getWriteTime());
            if (cache.getExpireTime() > timoutTime) {
                continue;
            }
            System.out.println(" 清除过期缓存 : " + key);
            //清除过期缓存
            concurrentHashMap.remove(key);
        }
    }
}
Copier après la connexion

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 de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Où trouver la courte de la grue à atomide atomique
1 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Racine carrée en Java Racine carrée en Java Aug 30, 2024 pm 04:26 PM

Guide de la racine carrée en Java. Nous discutons ici du fonctionnement de Square Root en Java avec un exemple et son implémentation de code respectivement.

Nombre parfait en Java Nombre parfait en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Générateur de nombres aléatoires en Java Générateur de nombres aléatoires en Java Aug 30, 2024 pm 04:27 PM

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Numéro Armstrong en Java Numéro Armstrong en Java Aug 30, 2024 pm 04:26 PM

Guide du numéro Armstrong en Java. Nous discutons ici d'une introduction au numéro d'Armstrong en Java ainsi que d'une partie du code.

Weka en Java Weka en Java Aug 30, 2024 pm 04:28 PM

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Numéro de Smith en Java Numéro de Smith en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Questions d'entretien chez Java Spring Questions d'entretien chez Java Spring Aug 30, 2024 pm 04:29 PM

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

See all articles