Frage

Wir versuchen, Memcached -Objekte zu aktualisieren, wenn wir in die Datenbank schreiben, um zu vermeiden, dass sie nach Einfügen/Updates aus Datenbank lesen müssen.

Für unser Forum -Post -Objekt haben wir ein ViewCount -Feld, das die Anzahl der Ansichten eines Beitrags enthält.

Wir befürchten, dass wir eine Rennbedingung einführen, indem wir das Memcached -Objekt aktualisieren, da derselbe Beitrag gleichzeitig auf einem anderen Server in der Farm betrachtet werden kann.

Gibt es eine Idee, wie man mit solchen Problemen umgeht - es scheint, dass eine Art Sperre benötigt wird, aber wie man es zuverlässig auf Server auf einer Farm macht?

War es hilfreich?

Lösung

Wenn Sie mit Daten zu tun haben, die nicht unbedingt nicht unbedingt brauchen Um die Echtzeit zu aktualisieren, und für mich ist die Ansicht, dass die Ansicht einer von ihnen ist, dann können Sie den Objekten, die in Memcache gespeichert sind, ein Feld hinzufügen.

Sobald dieser Ablauf stattfindet, wird sie zur Datenbank zurückkehren und den neuen Wert lesen, aber bis dahin wird es in Ruhe gelassen.

Natürlich möchten Sie für neue Beiträge möglicherweise häufiger aktualisiert, aber Sie können dafür codieren.

Memcache speichert nur eine Kopie Ihres Objekts in einem seiner Instanzen, nicht in vielen von ihnen, daher würde ich mir keine Sorgen um Objektsperrung oder irgendetwas machen. Das ist für die Datenbank, nicht mit Ihrem Cache.

Bearbeiten:

Memcache bietet keine Garantie dafür, dass Ihre Daten beim Erhalten und Einstellen von verschiedenen Servern nicht gepackt werden.

Aus Memcache -Dokumenten:

  • Eine Reihe von Befehlen ist nicht atomar. Wenn Sie ein "Get" gegen einen Artikel ausstellen, die Daten betreiben und dann in Memcached "wieder einstellen" möchten, ist es nicht garantiert, dass Sie der einzige Prozess sind, der an diesem Wert arbeitet. Parallel dazu könnten Sie einen von etwas anderen festgelegten Wert überschreiben.

Rennbedingungen und abgestandene Daten

Eine Sache, die Sie berücksichtigen sollten, wenn Sie Ihre Anwendung zum Cache -Daten entwerfen, ist, wie Sie mit Rennbedingungen und gelegentlichen veralteten Daten umgehen können.

Angenommen, Sie zwischen den neuesten fünf Kommentaren für die Anzeige in einer Seitenleiste in Ihrer Anwendung. Sie entscheiden, dass die Daten nur einmal pro Minute aktualisiert werden müssen. Sie vernachlässigen jedoch daran, sich daran zu erinnern, dass diese Seitenleiste 50 Mal pro Sekunde wiedergegeben wird! Sobald 60 Sekunden herumrollen und der Cache abläuft, werden plötzlich 10+ Prozesse dieselbe SQL -Abfrage ausführen, um diesen Cache neu zu bevölkern. Jedes Mal, wenn der Cache abläuft, entsteht ein plötzlicher Ausbruch des SQL -Verkehrs.

Schlimmer noch, Sie haben mehrere Prozesse, die dieselben Daten aktualisieren, und das falsche Dating mit dem Cache. Dann haben Sie veraltete, veraltete Daten, die herumschweben.

Man sollte sich auf mögliche Probleme bei der Bevölkerung oder Wiederholung unseres Cache bewusst sein. Denken Sie daran, dass der Prozess der Überprüfung des Memcached, des Abrufens von SQL und der Aufbewahrung in Memcached überhaupt nicht atomar ist!

Andere Tipps

Ich denke - könnte eine Lösung sein, um ViewCount separat aus dem Postobjekt zu speichern und dann ein Inkret zu machen. Dies erfordert natürlich, dass 2 separate Werte von Memcached beim Anzeigen der Informationen lesen müssen.

Wir haben dies in unserem System begegnet. Wir haben so geändert

  • Wenn der Wert nicht festgelegt ist, wird er mit einem Flag ('G') und [8] Second TTL festgelegt und kehrt falsche zurück, sodass die Aufruffunktion sie generiert.
  • Wenn der Wert nicht markiert ist (! == 'g'), dann unverzweigend und senden Sie ihn zurück.
  • Wenn der Wert gekennzeichnet ist (=== 'g'), warten Sie 1 Sekunde und versuchen Sie es erneut, bis er nicht markiert ist. Es wird schließlich durch den anderen Prozess festgelegt oder vom TTL abgelaufen.

Unsere Datenbanklast wurde bei der Implementierung um den Faktor 100 gesunken.

function get($key) {
  $value=$m->get($key);
  if ($value===false) $m->set($key, 'g', $ttl=8);
  else while ($value==='g') {
    sleep(1);
    $value=$m->get($key);
  }
  return $value;
}

Memcached Operations sind atomar. Der Serverprozess stellt die Anforderungen an und serviert jeden vollständig, bevor sie zum nächsten gehen, sodass kein Sperren erforderlich ist.

bearbeiten: Memcached hat einen Inkrementbefehl, der ist Atomic. Sie müssen den Zähler nur als separater Wert im Cache speichern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top