Heim  >  Artikel  >  Datenbank  >  So verwenden Sie caffeine_redis, um den Cache der zweiten Ebene anzupassen

So verwenden Sie caffeine_redis, um den Cache der zweiten Ebene anzupassen

WBOY
WBOYnach vorne
2023-05-27 10:08:241197Durchsuche

    Fragen

    Basierend auf den gestellten Anforderungen denke ich, dass es hauptsächlich die folgenden zwei Probleme gibt:

    • Wie kann die Datenkonsistenz sichergestellt werden, da ein lokaler Cache vorhanden ist? Wie werden die Daten anderer Knoten ungültig, wenn sich die Daten eines Knotens ändern?

    • Die Daten sind falsch und müssen neu synchronisiert werden. Wie kann der Cache ungültig gemacht werden?

    Flussdiagramm

    Der nächste Schritt besteht darin, mit dem Produkt und anderen Entwicklern zusammenzuarbeiten, um wie folgt ein Flussdiagramm zu zeichnen:

    • Verwenden Sie eine Konfigurationstabelle, um aufzuzeichnen, ob Caching erforderlich ist und ob Caching aktiviert ist, um eine Benachrichtigung zu erhalten Cache-Fehler.

    • Da die Projektanforderungen durchschnittlich sind, wird es keine großen Auswirkungen haben, selbst wenn die Nachricht verloren geht. Daher habe ich mich schließlich für die Abonnement- und Veröffentlichungsfunktionen in Redis entschieden, um andere Knoten über ungültigen lokalen Cache zu informieren.

    Entwicklung

    Die oben genannten Fragen sind klar und das Flussdiagramm ist ebenfalls klar. Dann machen Sie sich bereit, mit dem Schreiben von Fehlern zu beginnen. Die Gesamtidee besteht darin, die Aspekte der Annotationsimplementierung anzupassen und die Kopplung an den Geschäftscode zu minimieren.

    CacheConfig

    wird hauptsächlich im Code erläutert und definiert einen CacheManager zur Integration in das Unternehmen. Besonderes Augenmerk muss auf die maximale Anzahl zwischenspeicherbarer Elemente gelegt werden, um zu vermeiden, dass zu viel Programmspeicher belegt wird und der Speicher voll wird. Zu klein darf es natürlich nicht sein, denn auch die Trefferquote muss berücksichtigt werden. Daher muss die endgültige Größe anhand des tatsächlichen Geschäfts ermittelt werden.

    @Bean(name = JKDDCX)
    @Primary
    public CacheManager cacheManager() {
         CaffeineCacheManager cacheManager  = new CaffeineCacheManager();
            cacheManager.setCaffeine(Caffeine.newBuilder()
                    // 设置最后一次写入或访问后经过固定时间过期
                    .expireAfterAccess(EXPIRE, TIME_UNIT)
                    //设置本地缓存写入后过期时间
                    .expireAfterWrite(EXPIRE, TIME_UNIT)
                    // 初始的缓存空间大小
                    .initialCapacity(500)
                    // 缓存的最大条数
                    .maximumSize(1000));// 使用人数 * 5 (每个人不同的入参 5 条)\
      return cacheManager;
    }

    @CaffeineCache

    Benutzerdefinierte Anmerkung, alle verfügbaren Parameter hinzufügen.

    @Target({ ElementType.METHOD ,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CaffeineCache {
    
         public String moudleId() default "";
        
         //用于在数据库中配置参数
         public String methodId() default "";
         public String cachaName() default "";
        
         //动态切换实际的 CacheManager
         public String cacheManager() default "";
    
    }

    CacheMessageListener

    Der Cache-Listener ist hauptsächlich dafür verantwortlich, die Konsistenz von Daten mit mehreren Knoten sicherzustellen. Wenn ein Knoten-Cache aktualisiert wird, werden andere Knoten benachrichtigt, damit sie entsprechend damit umgehen können. Verwenden Sie die Veröffentlichungs- und Abonnementfunktion von Redis und implementieren Sie die MessageListener-Schnittstelle, um die Haupttechnologie zu implementieren.

    Ein weiteres Detail unten ist natürlich, dass der Befehl Redis#keys in allgemeinen Produktionsumgebungen deaktiviert ist, sodass Sie die entsprechenden Schlüssel auf andere Weise scannen müssen.

    public class CacheMessageListener implements MessageListener {
         @Override
        public void onMessage(Message message, byte[] pattern) {
            CacheMessage cacheMessage = (CacheMessage) redisTemplate.getValueSerializer().deserialize(message.getBody());
            logger.info("收到redis清除缓存消息, 开始清除本地缓存, the cacheName is {}, the key is {}", cacheMessage.getCacheName(), cacheMessage.getKey());
    //		redisCaffeineCacheManager.clearLocal(cacheMessage.getCacheName(), cacheMessage.getKey());
    
            /**
             * 如果是一个类上使用了 注解 @CaffeineCache ,那么所有接口都会缓存。
             * 下面的逻辑是:除了当前模块的接口访问的入参 key,其他的 redis 缓存都会被清除
             * (比如此模块的表更新了,但是当前调用此接口只是缓存了当前这个入参的redis,其他的数据删除)
             */
            String prefixKey = RedisConstant.WXYMG_DATA_CACHE + cacheMessage.getCacheName();
            Set<String> keys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
                Set<String> keysTmp = new HashSet<>();
                Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().
                        match(prefixKey + "*").
                        count(50).build());
                while (cursor.hasNext()) {
                    keysTmp.add(new String(cursor.next()));
                }
                return keysTmp;
            });
            Iterator iterator = keys.iterator();
            while (iterator.hasNext()) {
                if (iterator.next().toString().equals(cacheMessage.getKey())) {
                    iterator.remove();
                }
            }
            redisTemplate.delete(keys);
    
            cacheConfig.cacheManager().getCache(cacheMessage.getCacheName()).clear(); //cacheName 下的都删除
        }
    }

    CaffeineCacheAspect

    Dann gibt es noch die logische Verarbeitung des Aspekts. Der darin enthaltene Inhalt entspricht genau dem Flussdiagramm, der Code wird jedoch zur Implementierung der Anforderungen verwendet.

    Unter ihnen: Der folgende Code ist Redis, der Nachrichten veröffentlicht.

    redisTemplate.convertAndSend(CacheConfig.TOPIC, new CacheMessage(caffeineCache.cachaName(), redisKey));

    CacheMessage

    Dies ist ein Nachrichtentext, wenn Redis eine Nachricht veröffentlicht. Er ist ebenfalls anpassbar und kann weitere Parameterattribute hinzufügen

    public class CacheMessage implements Serializable {
    
    	private static final long serialVersionUID = -1L;
    
    	private String cacheName;
    
    	private Object key;
    
    	public CacheMessage(String cacheName, Object key) {
    		super();
    		this.cacheName = cacheName;
    		this.key = key;
    	}
    
    }

    Das obige ist der detaillierte Inhalt vonSo verwenden Sie caffeine_redis, um den Cache der zweiten Ebene anzupassen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen