2016-06-04 19 views
1

Ich habe Rails App, in denen ich einen Hash pflegen muss, auf die mehrere Threads gleichzeitig zugreifen werden.Soll ich einen Redis-Hash oder einen Ruby-Hash verwenden?

Die meisten Zugriffe werden gelesen und es wird wenig Schreibvorgänge geben. Ich versuche, zwischen einem Ruby-Hash und Redis-Hash zu entscheiden.

Der Redis-Hash ist Thread-sicher und kann die Daten auf der Festplatte speichern. Aber die Beharrlichkeit ist nicht so notwendig.

Darüber hinaus sind die Schreibvorgänge auf den Hash-Wert selten und die zu schreibenden Daten sind im Grunde die Zeit selbst, zu der geschrieben wird. Selbst wenn es nicht threadsicher ist, ist der Genauigkeitsverlust aufgrund einer Racebedingung akzeptabel, da die Zeit zwischen gleichzeitigen Schreibvorgängen bei max. Nur einigen Sekunden variieren kann.

Meine einzige Sorge mit einem Singleton Ruby-Hash ist, dass Updates nicht Thread-sicher und nicht atomar sind. Führt ein simultanes nicht-atomares Schlüsselupdate zu einer Ausnahme?

Wenn nicht, wird es sinnvoll sein, den Ruby-Singleton-Hash ohne Sperren beizubehalten?

Meine Bedenken bei der Verwendung eines Redis-Hashes sind, dass die Größe des In-Memory-Hashs größer als der Ruby-Hash und der Overhead beim Aufrufen des Redisers sein könnte. Die Nebenläufigkeit und Ausdauer sind gut zu haben, aber nicht notwendig.

Bitte lassen Sie mich Ihre Gedanken wissen. Vielen Dank.

+0

Sobald Sie Ihre Anwendung in der Produktion ausführen, möchten Sie möglicherweise mehrere Worker ausführen oder sogar die Anwendung auf mehreren Servern ausführen. Das sagte: Redis könnte die bessere Idee sein. – spickermann

+0

Ich benutze die App auf Puma, die mehrere Arbeiter verwenden kann. Bedeutet das, dass, wenn ich einen Singleton-Hash verwende, wenn mehrere Worker involviert sind, unterschiedliche Worker unterschiedliche App-Instanzen haben und somit für jede Instanz ein anderer Hash? Wenn dies der Fall ist, wird Redis die einzige Option sein, um einen global verfügbaren Hash zu erstellen? – trans1st0r

+0

Das ist richtig: Puma Arbeiter laufen in einem anderen Prozess und teilen keinen Speicher. Sie können Puma jedoch auch so konfigurieren, dass es in mehreren Threads ausgeführt wird, die sich Speicher teilen. Die Antwort lautet also: Es hängt von Ihrer Konfiguration ab. Redis funktioniert in allen Konfigurationen - sogar mit mehreren Servern ... – spickermann

Antwort

3

(Dies ist eine Korrektur basierend auf Holger Just Kommentar Korrektur mir.)

Es gibt eine Bibliothek speziell für Ihren Bedarf concurrent-ruby genannt.

Überprüfen Sie es bei https://github.com/ruby-concurrency/concurrent-ruby.

Es hat eine Hash-Klasse (http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Hash.html) und auch eine Map-Klasse (http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Map.html), die sie sagen schneller ist aber nicht vollständig mit der Semantik von Ruby Hash (z. B. garantiert Reihenfolge in Reihenfolge der Schlüsseleinfügung nicht).

Beachten Sie, dass nach der Installation des Edelsteins, der require erforderlich ist, um es zu verwenden, sich vom Namen des Edelsteins unterscheidet; require concurrent Sie:

require 'concurrent' 
h = Concurrent::Hash.new 

Ich habe es allerdings nicht verwendet, so kann ich kein persönliches Feedback darüber geben.

+1

Das [thread_safe] (https://github.com/ruby-concurrency/thread_safe) Gem wurde mit dem [concurrent-ruby] zusammengeführt (https: // github .com/ruby-concurrency/concurrent-ruby) Gem, das viele zusätzliche Primitive enthält. Das thread_safe-Juwel ist daher veraltet und wird nur im Wartungsmodus betrachtet.Bei Neuentwicklungen sollten Sie daher wahrscheinlich stattdessen "concurrent-ruby" verwenden. Da ActiveSupport 5 von gleichzeitigem Ruby abhängig ist, sollte es auch ziemlich sicher zu verwenden sein. –

+0

@HolgerJust Danke, ich werde die Antwort aktualisieren. –

Verwandte Themen