Standardschlüssel- / Wertdatenspeicher für Unix


16

Ich weiß , über den Schlüssel / Wert - Bibliotheken für Unix ( BerkeleyDB , gdbm , redis ...). Bevor ich jedoch mit dem Codieren beginne, frage ich mich, ob es ein Standardtool für Unix gibt, mit dem ich die folgenden Vorgänge ausführen kann:

$ tool -f datastore.db put "KEY" "VALUE"
$ tool -f datastore.db put -f file_key_values.txt
$ tool -f datastore.db get "KEY"
$ tool -f datastore.db get -f file_keys.txt
$ tool -f datastore.db remove "KEY"
$ etc...

Vielen Dank

Antworten:


10

Ich glaube nicht, dass es dafür ein Standardwerkzeug gibt. Mit Ausnahme von grep/ awk/ sedusw. Bei dieser Einstellung müssen Sie sich jedoch mit vielen anderen Problemen wie Sperren, Formatieren, Sonderzeichen usw. befassen.

Ich schlage vor, zu verwenden sqlite. Definieren Sie eine einfache Tabelle und erstellen tool_get()und tool_put()schälen Sie dann Funktionen. sqliteist portabel, schnell.

Sie erhalten zusätzliche Flexibilität kostenlos. Sie können Einschränkungen definieren, einen Index erstellen, um Ihr Skript zu optimieren, oder diese Datenbank eines Tages in anderen Sprachen verwenden.


Vielen Dank . Ich habe schnell ein Tool mit der SQLite-API geschrieben. Es funktioniert gut.
Pierre

9

Wenn Ihre Datenbank klein genug ist, können Sie das Dateisystem verwenden. Der Vorteil dieses Ansatzes besteht darin, dass er sehr technisch ist und überall mit sehr wenig Code funktioniert. Wenn die Schlüssel aus druckbaren Zeichen bestehen und keine enthalten /, können Sie sie als Dateinamen verwenden:

put () { key=$1; value=$2; printf %s "$value" >"datastore.db/$key"; }
get () { key=$1; cat "datastore.db/$key"; }
remove () { key=$1; rm "datastore.db/$key"; }

Um beliebige Schlüssel aufzunehmen, verwenden Sie eine Prüfsumme des Schlüssels als Dateinamen und speichern optional eine Kopie des Schlüssels (es sei denn, Sie können die Schlüssel nicht auflisten oder den Schlüssel für einen bestimmten Eintrag angeben).

put () {
  key=$1; value=$2; set $(printf %s "$key" | sha1sum); sum=$1
  printf %s "$key" >"datastore.db/$sum.key"
  printf %s "$value" >"datastore.db/$sum.value"
}
get () {
  key=$1; set $(printf %s "$key" | sha1sum); sum=$1
  cat "datastore.db/$1.value"
}
remove () {
  key=$1; set $(printf %s "$key" | sha1sum); sum=$1
  rm "datastore.db/$1.key" "datastore.db/$1.value"
}

Beachten Sie, dass die obigen Spielzeugimplementierungen nicht die ganze Geschichte darstellen: Sie haben keine nützlichen Transaktionseigenschaften wie Atomizität. Die grundlegenden Dateisystemoperationen wie das Erstellen und Umbenennen von Dateien sind jedoch atomar und es ist möglich, atomare Versionen der obigen Funktionen zu erstellen.

Diese Direkt-zu-Dateisystem-Implementierungen eignen sich mit typischen Dateisystemen nur für kleine Datenbanken mit bis zu einigen tausend Dateien. Darüber hinaus haben die meisten Dateisysteme Schwierigkeiten, mit großen Verzeichnissen umzugehen. Sie können das Schema an größere Datenbanken anpassen, indem Sie ein mehrschichtiges Layout verwenden. Anstatt beispielsweise alle Dateien in einem Verzeichnis zu speichern, speichern Sie sie in separaten Unterverzeichnissen, basierend auf den ersten Zeichen ihres Namens. Dies ist zum Beispiel die Aufgabe von git : Die durch SHA-1-Hashes indizierten Objekte werden in Dateien mit dem Namen gespeichert .git/objects/01/2345679abcdef0123456789abcdef01234567. Andere Beispiele für Programme, die eine semantische Schichtung verwenden, sind die Web-Caching-Proxys Wwwoffle und polipo ; Beide speichern die zwischengespeicherte Kopie einer Seite, die unter einer URL gefunden wurde, in einer Datei mit dem Namenwww.example.com/HASH wobei HASH eine Codierung eines Hash der URL ist.¹

Eine weitere Ursache für Ineffizienz ist, dass die meisten Dateisysteme beim Speichern kleiner Dateien viel Speicherplatz verschwenden. Auf typischen Dateisystemen wird unabhängig von der Größe der Datei eine Verschwendung von bis zu 2 KB pro Datei verursacht.

Wenn Sie sich für eine echte Datenbank entscheiden, müssen Sie nicht auf den Komfort eines transparenten Dateisystemzugriffs verzichten. Es gibt verschiedene FUSE- Dateisysteme für den Zugriff auf Datenbanken, darunter Berkeley DB (mit Jeff Garziks Datenbank ), Oracle (mit Oracle DBFS ), MySQL (mit mysqlfs ) usw.

¹ Bei einer URL wie der von http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unixPolipo wird die Datei unix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==mit einem zusätzlichen Header in der Datei verwendet, der die tatsächliche URL in Klartext angibt. Der Dateiname ist die Base64-Codierung des MD5-Hash (in Binärform) der URL. Wwwoffle benutzt die Datei http/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhw; Der Name der Datei ist eine selbst erstellte Codierung des MD5-Hashs, und eine Begleitdatei http/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhwenthält die URL.


7

dbmutilVielleicht bekommst du was du willst. Es verfügt über Shell-Dienstprogramme für die Operationen, die Sie in der Frage beschreiben. Ich würde nicht sagen, dass es genau Standard ist, aber es hat die Einrichtungen, die Sie wollen.


5

Seit Sie es benannt haben, verfügt der Standard-Redis-Client über eine Befehlszeilenschnittstelle redis-cli. Einige Beispiele aus redis-cli -h:

 cat /etc/passwd | redis-cli -x set mypasswd
 redis-cli get mypasswd
 redis-cli -r 100 lpush mylist x

(Und wenn Sie über das Dateisystem auf die Datenbank zugreifen möchten, können Sie Sockets verwenden -s. Ein Tool, das den Datenbankindex direkt bei jedem Aufruf liest, wäre sehr ineffizient.)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.