Einführung
Eine Preisänderung durch Mitarbeitende sollte die maßgebliche Datenbank aktualisieren und den alten Cache-Wert für genau diesen Preis entfernen. Alle gecachten Produkte zu löschen, würde nützliche Arbeit verwerfen. Einen Cache-Eintrag vor einem fehlgeschlagenen Quellschreibzugriff zu entfernen, würde dessen Ergebnis ebenfalls falsch darstellen.
Dieses unabhängige Lab bereitet einen neuen Cache-Arbeitsplatz und eine korrekte Lesepolicy mit vollständiger Identität und 15 Sekunden Lebensdauer vor. Du benötigst die Konzepte zu Cache-aside, Identität, TTL und kurzen Python-Vorlagen aus dem vorherigen Lab. Du vervollständigst change_price, beobachtest einen abgelehnten Primärschreibzugriff und vergleichst ausdrückliche Invalidierung mit einer externen Aktualisierung, die nach natürlichem Ablauf sichtbar wird. Nur Terminal wird benötigt; keine Dateien oder Prozesse werden aus der vorherigen VM übernommen.
Bearbeite nur /home/labex/project/cache-desk/policy.py unter Verwendung der drei dokumentierten Funktionen und der Quell-/Cache-API. Bewahre alle Werkzeuge, Quelltabellenidentitäten, unbeteiligten Preise und die Katalognotiz. Die erlaubten Primäränderungen sind North MUG USD von 1200 auf 1350 über deine Policy, ein abgelehnter Versuch mit negativem Preis und die vorbereitete externe Änderung auf 1450. Anfragen laufen im Lernablauf sequenziell mit funktionierenden Diensten; dies ist keine starke Konsistenz, verteilte Cache-Invalidierung oder Zusage, dass zwei Datenbanken atomar bestätigen. Die geschätzte Zeit ist der vom Autor vorgesehene Aufwand für Lesen und Fehler, ohne Zeitdaten von Anfängern.
Den exakten Preis nach dem Commit invalidieren
In diesem Schritt lässt du einen erfolgreichen Quellschreibzugriff seinen veralteten Cache-Preis entfernen und bewahrst dabei den Cache nach einem abgelehnten Schreibzugriff.
Beginne in Terminal. Wechsle in den vorbereiteten Arbeitsbereich dieser unabhängigen Einheit:
cd /home/labex/project/cache-desk
./desk status
./desk policy
Die drei Identitätsfelder sind Geschäft, SKU und Währung. North MUG USD beginnt bei 1200 Cent. South MUG USD ist 1500, North MUG EUR 1100 und North FREE USD 0. Befülle den Cache mit einem normalen Preis und übermittle dann eine berechtigte Änderung:
./desk view north MUG USD
./desk view north MUG USD
./desk change north MUG USD 1350
./desk status
./desk view north MUG USD
Status zeigt nun den per Commit bestätigten Primärpreis 1350, während eine zeitnahe Ansicht weiterhin gecachte 1200 zurückgeben kann. Sind dessen 15 Sekunden bereits verstrichen, kann die Ansicht korrekt einen Miss ergeben und 1350 zeigen; die fehlende Invalidierung bleibt ein Policy-Fehler, auch wenn der Ablauf ihn verbirgt. Die Erfolgsmeldung besagt nur, dass die übermittelte Policy zurückkehrte; tatsächliche Primär- und Cache-Beobachtungen entscheiden, was geschehen ist.
change_price ruft bereits source.write(identity, cents) auf. Diese vorbereitete Methode aktualisiert eine bekannte Primärzeile in einer nativen SQLite-Transaktion. Sie kehrt erst nach dem Commit zurück. Ein negativer Preis verletzt die CHECK-Bedingung der Quelle und löst einen Fehler aus; eine unbekannte Identität löst einen Nachschlagefehler aus. Python führt die nächste Zeile nur aus, wenn der vorherige Aufruf erfolgreich zurückkehrt. Platziere daher das exakte Redis-Löschen nach diesem Aufruf. cache_key(prefix, identity) verwendet dieselbe Identitätsabbildung wie die Lesefunktion erneut. Lösche nicht nur nach SKU und verwende weder FLUSHDB noch FLUSHALL.
Wie im vorherigen Lab ersetzt das Here-Dokument in Anführungszeichen nur policy.py; bewahre die Einrückung. Die vollständige Lesefunktion wird wiederholt, damit die Ersetzung vollständig ist:
cat > policy.py <<'POLICY'
def cache_key(prefix, identity):
return f"{prefix}:{identity[0]}:{identity[1]}:{identity[2]}"
def read_price(source, cache, prefix, identity):
key = cache_key(prefix, identity)
value = cache.command("GET", key)
if value is not None:
return int(value), "cache"
cents = source.read(identity)
cache.command("SET", key, cents, "EX", 15)
return cents, "source"
def change_price(source, cache, prefix, identity, cents):
source.write(identity, cents)
cache.command("DEL", cache_key(prefix, identity))
POLICY
Befülle zwei unbeteiligte Preise und wiederhole dann den erlaubten Schreibzugriff. Dieselben 1350 erneut zu schreiben, führt weiterhin einen tatsächlichen Commit für eine bekannte Zeile aus und erprobt die Invalidierung:
./desk view south MUG USD
./desk view north MUG EUR
./desk change north MUG USD 1350
./desk inspect north MUG USD
./desk view north MUG USD
./desk view north MUG USD
Inspect muss unmittelbar nach dem Schreiben den Zielschlüssel als fehlend zeigen. Die nächste Ansicht gibt source/1 und 1350 zurück; ihre nächste Ansicht ist cache/0. Andere Schlüssel werden nicht absichtlich invalidiert; sie können weiterhin natürlich ablaufen. Verwende status, um bewahrte Primärwerte von Cache-Anwesenheit zu unterscheiden.
Fordere nun absichtlich einen ungültigen negativen Preis an. Der folgende Befehl soll mit einem Status ungleich null enden und IntegrityError mit dem nativen CHECK-Fehler ausgeben. Es ist weder eine erfolgreiche Aktualisierung noch ein Cache-Miss oder ein Verbindungsproblem:
./desk change north MUG USD -1
./desk status
./desk inspect north MUG USD
./desk view north MUG USD
Der maßgebliche Preis bleibt 1350. Ist der befüllte Eintrag nicht natürlich abgelaufen, bleiben sein Wert und seine ursprüngliche Ablaufzeit erhalten, und die Ansicht ist cache/0. Wer langsam liest, sieht möglicherweise stattdessen einen normalen Ablauf; die isolierte Prüfung testet den Erhalt nach fehlgeschlagenem Schreiben ohne Wettlauf gegen die Lesezeit. Python hält vor DEL an, wenn source.write einen Fehler auslöst. Fange den Fehler nicht ab, um einen falschen Erfolg auszugeben.
Meldet die Shell ./deskk als fehlend, führe ls aus und korrigiere den Namen. Hat deine Policy einen Syntax- oder Einrückungsfehler, prüfe sie mit ./desk policy und ersetze sie erneut durch den vollständigen Block. Ein fehlgeschlagener Negativpreisbefehl benötigt kein Zurücksetzen: Die vorbereitete Quelltransaktion hat diesen Versuch bereits zurückgerollt. Lass einen Lesezugriff folgen, keine direkte Datenbankbearbeitung.
Eine externe Aktualisierung zur nächsten Befüllung gelangen lassen
In diesem Schritt beobachtest du eine tatsächliche externe Quelländerung und die begrenzte Lebensdauer eines alten Cache-Werts.
Fahre in Terminal unter /home/labex/project/cache-desk fort. Wende den erlaubten bestätigten Preis erneut an, um einen vorhandenen Zielcache zu entfernen, und befülle dann 1350. Dies macht den Ausgangspunkt klar, ohne ein anderes Produkt zu verändern:
./desk change north MUG USD 1350
./desk view north MUG USD
./desk inspect north MUG USD
Der externe Befehl stellt einen absichtlich kontrollierten Schreiber dar, der den Invalidierungshook dieser Anwendung umgeht. Er führt einen tatsächlichen Primär-Commit aus, keine timergetriebene Anzeigeänderung. Diese Einheit erlaubt nur das folgende externe Ziel und den neuen Preis:
./desk external north MUG USD 1450
./desk status
./desk view north MUG USD
./desk inspect north MUG USD
Status zeigt sofort 1450. Eine Ansicht vor Ablauf des vorhandenen Schlüssels kann weiterhin gecachte 1350 ohne Primärlesezugriff zurückgeben. Seine Ablaufzeit zählt weiter herunter; sie startet beim Treffer nicht neu. Hat die Lesezeit die Lebensdauer bereits überschritten, sind 1450 aus einem Miss zu erwarten. Du kannst die anfängliche Änderungs-/Befüllungs-/Extern-Sequenz dieses Schritts zügig wiederholen, um das veraltete Intervall zu beobachten.
Warte vor dem letzten Lesezugriff länger als die vollständige konfigurierte Befüllungslebensdauer:
sleep 16
./desk inspect north MUG USD
./desk view north MUG USD
./desk view north MUG USD
./desk status
Inspect zeigt den fehlenden Schlüssel. Die nächste Ansicht liest die bestätigten 1450 aus der Primärquelle und befüllt Redis; die folgende Ansicht kann diese tatsächlich gecachten 1450 verwenden. Bewahre diesen abschließenden Primärzustand. Alle anderen maßgeblichen Preise bleiben 1500, 1100 und 0. ./redis GET catalog:admin:note kann die bewahrte unbeteiligte Notiz prüfen, ohne eine Primäranfrage auszuführen.
Dies ist eine sequenzielle Cache-aside-Policy. Eine externe Aktualisierung nach einer Befüllung kann deren alten Wert bis zu ihrer bestehenden Ablaufzeit nach 15 Sekunden sichtbar lassen. Diese Beobachtung beweist keine globale Veraltungsgrenze bei gleichzeitigen Lese-/Schreibzugriffen, langsamen Befüllungen oder einem gestoppten Dienst. Ein gleichzeitig lesender Client könnte einen alten Quellwert vor einem Schreibzugriff abrufen und ihn nach der Invalidierung einfüllen; dieser Kurs löst weder diesen Wettlauf noch eine Flut gleichzeitiger Misses.
Primär-Commit und Redis-Löschen sind separate Operationen. Verweigert Redis das Löschen nach einem erfolgreichen Commit, ist die Primärquelle bereits geändert. Der Fehler muss als Cache-Operationsfehler weitergegeben werden; er darf nicht als Primär-Rollback oder abgeschlossene Invalidierung beschrieben werden. Die isolierte Bewertung testet diesen nativen Fehler, ohne deinen laufenden Dienst zu beschädigen. Wiederholungsversuche im Produktivbetrieb, dauerhafte Invalidierung und Wiederherstellung nach Ausfällen benötigen zusätzliche Gestaltung außerhalb dieser Übung.
Zusammenfassung
Du hast einen tatsächlichen Primär-Commit mit exakter Cache-Invalidierung verknüpft, Cache-Daten nach einem abgelehnten Quellschreibzugriff bewahrt und eine externe Änderung durch natürlichen Ablauf beobachtet. Deine Policy unterscheidet einen Fehler beim Schreiben der Quelle von einem späteren Redis-Fehler und macht ihre sequenzielle Konsistenzgrenze ausdrücklich.



