Banque de données de clés / valeurs standard pour Unix

16

Je connais le bibliothèques clé / valeur pour unix ( berkeleydb , gdbm , redis ...). Mais avant de commencer à coder, je me demande s'il existe un outil standard pour unix qui me permettrait d'effectuer les opérations suivantes:

$ 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...

Merci

Pierre
la source

Réponses:

10

Je ne pense pas qu'il existe un outil standard pour cela. À l'exception degrep / awk/ sedetc. Mais en utilisant cela, vous devrez vous soucier de beaucoup d'autres problèmes comme le verrouillage, le format, les caractères spéciaux, etc.

Je suggère d'utiliser sqlite. Définissez une table simple, puis créez tool_get()ettool_put() interprétez des fonctions. sqliteest portable, rapide.

Vous bénéficierez d'une flexibilité supplémentaire gratuite. Vous pouvez définir des contraintes, indexer pour modifier votre script ou utiliser cette base de données dans d'autres langues un jour.

Michał Šrajer
la source
Merci . J'ai rapidement écrit un outil avec l'API sqlite. Ça fonctionne bien.
Pierre
9

Si votre base de données est suffisamment petite, vous pouvez utiliser le système de fichiers. L'avantage de cette approche est qu'elle est très low-tech et fonctionnera partout avec très peu de code. Si les clés sont composées de caractères imprimables et ne contiennent pas /, vous pouvez les utiliser comme noms de fichiers:

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"; }

Pour prendre en charge des clés arbitraires, utilisez une somme de contrôle de la clé comme nom de fichier et stockez éventuellement une copie de la clé (sauf si vous n'êtes pas satisfait de ne pas pouvoir répertorier les clés ou dire quelle est la clé pour une entrée donnée).

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"
}

Notez que les implémentations de jouets ci-dessus ne sont pas toute l'histoire: elles n'ont aucune utilité propriété transactionnelle comme l'atomicité. Les opérations de base du système de fichiers telles que la création et le renommage de fichiers sont atomiques cependant, et il est possible de construire des versions atomiques des fonctions ci-dessus.

Ces implémentations du système de fichiers direct ne conviennent aux systèmes de fichiers typiques que pour les petites bases de données, jusqu'à quelques milliers de fichiers. Au-delà de ce point, la plupart des systèmes de fichiers ont du mal à gérer de gros répertoires. Vous pouvez adapter le schéma à des bases de données plus importantes en utilisant une disposition en couches. Par exemple, au lieu de stocker tous les fichiers dans un seul répertoire, stockez-les dans des sous-répertoires distincts en fonction des premiers caractères de leurs noms. C'est ce que fait git , par exemple: ses objets, indexés par les hachages SHA-1, sont stockés dans des fichiers appelés .git/objects/01/2345679abcdef0123456789abcdef01234567. D'autres exemples de programmes qui utilisent une couche sémantique sont les proxies de mise en cache Web Wwwoffle et polipo ; les deux stockent la copie en cache d'une page trouvée à une URL dans un fichier appeléwww.example.com/HASH où HASH est un encodage d'un hachage de l'URL.¹

Une autre source d'inefficacité est que la plupart des systèmes de fichiers gaspillent beaucoup d'espace lors du stockage de petits fichiers - il y a un gaspillage allant jusqu'à 2 Ko par fichier sur les systèmes de fichiers typiques, indépendamment de la taille du fichier.

Si vous choisissez d'utiliser une vraie base de données, vous n'avez pas besoin de renoncer à la commodité d'un accès transparent au système de fichiers. Il existe plusieurs systèmes de fichiers FUSE pour accéder aux bases de données, notamment Berkeley DB (avec les dbfs de Jeff Garzik ), Oracle (avec Oracle DBFS ), MySQL (avec mysqlfs ), etc.

¹ Pour une URL comme http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unix, Polipo utilise le fichier unix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==, avec un en-tête ajouté à l'intérieur du fichier indiquant l'URL réelle en texte clair; le nom du fichier est l'encodage base64 du hachage MD5 (en binaire) de l'URL. Wwwoffle utilise le fichier http/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhw; le nom du fichier est un encodage local du hachage MD5, et un fichier compagnon http/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhwcontient l'URL.

Gilles 'SO- arrête d'être méchant'
la source
7

dbmutilpourrait vous obtenir ce que vous voulez. Il a des utilitaires shell pour les opérations que vous décrivez dans la question. Je ne dirais pas que c'est exactement standard, mais il a les installations que vous voulez.

ConcernedOfTunbridgeWells
la source
5

Depuis que vous l'avez nommé, le client redis standard dispose d'une interface de ligne de commande redis-cli. Quelques exemples de redis-cli -h:

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

(Et si vous souhaitez accéder à la base de données via le système de fichiers, vous pouvez utiliser des sockets avec -s. Un outil qui lirait l'index de la base de données directement à chaque appel serait très inefficace.)

Stéphane Gimenez
la source