2017-01-17 5 views
4

Ich speichere neue Einträge mit einem Spring Data Repository. Ich habe eine TTL von 10 Sekunden für jeden Eintrag.Spring Redis - Indizes nicht gelöscht nach Haupteintrag verfällt

Wenn ich einen Eintrag mit Indizes speichern, hier ist das, was ich

127.0.0.1:6379> keys * 1) "job:campaignId:aa" 2) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be" 3) "job:recipient:dd" 4) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:phantom" 5) "job:listId:cc" 6) "job:accountId:bb" 7) "job" 8) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:idx"

Nach Ablauf in redis, ich habe immer noch Daten:

127.0.0.1:6379> keys * 1) "job:campaignId:aa" 2) "job:recipient:dd" 3) "job:listId:cc" 4) "job:accountId:bb" 5) "job" 6) "job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:idx"

Ohne TTL. Warum löschen sie sich nicht selbst? Wie könnte ich das tun?

Danke

Antwort

7

Spring Data Redis Repositorys verwenden mehrere Redis Domänenobjekte beharren Funktionen in Redis.

Domänenobjekte werden hauptsächlich in einem Hash gespeichert (job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be). Jeder Ablauf wird direkt auf den Hash angewendet, sodass Redis den Schlüssel ablaufen lässt. Spring Data Redis verwaltet auch sekundäre Indizes (job:campaignId:aa, job:recipient:dd), um Nachschlagevorgänge nach bestimmten Feldwerten zu ermöglichen. Einzelne Elemente innerhalb eines Sets können nicht abgelaufen sein. Nur die gesamte Datenstruktur kann ablaufen, aber das ist nicht das, was Sie tun möchten, weil alle nicht abgelaufenen Elemente auf diese Weise verschwinden würden.

So Spring Data Redis hält eine Kopie des ursprünglichen Hash als Phantom-Hash (job:a6d6e491-5d75-4fd0-bd8e-71692f6d18be:phantom) mit einer etwas längeren TTL.

Spring Data Redis abonniert Schlüsselereignisse (mit der Einstellung @EnableRedisRepositories(enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP), um Ablaufereignisse anzuhören. Sobald der ursprüngliche Hash abläuft, lädt Spring Data Redis den Phantom-Hash, um Bereinigungen durchzuführen (Referenzen aus sekundären Indizes entfernen).

Der Grund, warum die Bereinigung Ihrer Daten nicht durchgeführt wurde, mehrere Gründe haben:

  1. Wenn Sie nur eine Konsolenanwendung ausführen, um Daten einzufügen und zu beenden, dann entfernt der Ablauf die Hashes führt aber nicht die Indexbereinigung, da Ihre Anwendung nicht mehr ausgeführt wird. Alle von Redis veröffentlichten Ereignisse sind vorübergehend und wenn Ihre Anwendung nicht abhört, sind diese Ereignisse verloren
  2. Wenn Sie die Repository-Unterstützung nur mit @EnableRedisRepositories aktiviert haben (ohne keypace-events zu aktivieren), ist der Keyspace-Ereignis-Listener nicht aktiv. und Spring Data Redis hat keine Ablaufereignisse abonniert.
+0

Vielen Dank! Das ist die Erklärung, die ich brauchte. Habe ich etwas in der Dokumentation verpasst? Eine weitere verwandte Frage: Wie kann ich den Wert des abgelaufenen Schlüssels abrufen, bevor Spring Data ihn löscht? – BkSouX

+0

Beobachten Sie 'RedisKeyExpiredEvent' in Ihrer Anwendung. Es enthält den Schlüssel (Bytes) und das abgelaufene Domänenobjekt. Einzelheiten zum Ablauf finden Sie unter http://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis.repositories.expirations. – mp911de

+0

Nach dem Testen ein bisschen mit @EnableRedisRepositories (enableKeyspaceEvents = EnableKeyspaceEvents.ON_STARTUP), sehe ich, dass das Phantom in der gleichen Zeit wie der echte Schlüssel gelöscht wird, aber in der Dokumentation heißt es, dass es 5 Minuten später gelöscht wird. Vielleicht gibt es eine Eigenschaft oder etwas? – BkSouX

0

Keine Schlüssel/Wert wird automatisch gelöscht, wenn Sie Ablaufzeitpunkt nicht festgelegt haben.

Um Daten automatisch zu löschen, müssen Sie die Ablaufzeit einstellen.

redis> SET mykey "Hello" 
"OK" 
redis> EXPIRE mykey 10 
(integer) 1 

Ref: https://redis.io/commands/expire

Unten ist der Frühling Codefragment eine Daten hinzufügen Redis und setzen Ablaufzeit

@Component 
public class RedisUtil { 
    @Autowired 
    private RedisTemplate<String, String> template; 

    @Resource(name = "redisTemplate") 
    ValueOperations<String, String> ops; 

    public boolean addValue(String key, String value) { 

     if (template.hasKey(Constants.REDIS_KEY_PREFIX + key)) { 
      // key is already there 
      return false; 
     } else { 
      ops.set(Constants.REDIS_KEY_PREFIX + key, value); 
      template.expireAt(Constants.REDIS_KEY_PREFIX + key, 10); 
     } 
     return true; 
    } 
} 
+0

ok also muss ich es manuell tun?Ich verwende Spring Data Redis mit Repositories und der Schlüssel/Wert, der für die Indizes (@Indexed im Modell) erstellt wurde, wird nicht gelöscht, wenn der Hauptschlüssel für den Job gut abgelaufen ist und gelöscht wurde. – BkSouX

+0

Ja, Sie müssen die Ablaufzeit einstellen durch Ihren Code für jede Daten. – Avinash

+0

gut, ich dachte, es wäre einfacher mit Frühling .. Just tun ein Repo.Save (Eintrag) – BkSouX

Verwandte Themen