Almacén de datos clave / valor estándar para Unix

16

Sé sobre las bibliotecas de clave / valor para Unix ( berkeleydb , gdbm , redis ...). Pero antes de comenzar a codificar, me pregunto si existe una herramienta estándar para Unix que me permita realizar las siguientes operaciones:

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

Gracias

Pierre
fuente

Respuestas:

10

No creo que haya una herramienta estándar para eso. Excepto por grep/ awk/ sedetc. Pero al usar esto deberá preocuparse por muchos otros problemas como bloqueo, formato, caracteres especiales, etc.

Sugiero usar sqlite. Defina una tabla simple y luego cree tool_get()y tool_put()funciones de shell. sqliteEs portátil, rápido.

Obtendrá flexibilidad adicional de forma gratuita. Puede definir restricciones, indexar para modificar su script o usar esa base de datos en otros idiomas algún día.

Michał Šrajer
fuente
Gracias . Rápidamente escribí una herramienta con la API sqlite. Funciona bien.
Pierre
9

Si su base de datos es lo suficientemente pequeña, puede usar el sistema de archivos. La ventaja de este enfoque es que es de muy baja tecnología y funcionará en todas partes con muy poco código. Si las claves están compuestas de caracteres imprimibles y no contienen /, puede usarlas como nombres de archivo:

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

Para acomodar claves arbitrarias, use una suma de verificación de la clave como el nombre del archivo y, opcionalmente, almacene una copia de la clave (a menos que esté satisfecho con no poder enumerar las claves o decir cuál es la clave para una entrada determinada).

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

Tenga en cuenta que las implementaciones de juguetes anteriores no son la historia completa: no tienen ninguna propiedad transaccional útil como la atomicidad. Sin embargo, las operaciones básicas del sistema de archivos, como la creación y el cambio de nombre de archivos, son atómicas, y es posible construir versiones atómicas de las funciones anteriores.

Estas implementaciones directas al sistema de archivos son adecuadas con los sistemas de archivos típicos solo para bases de datos pequeñas, hasta unos pocos miles de archivos. Más allá de este punto, la mayoría de los sistemas de archivos tienen dificultades para hacer frente a directorios grandes. Puede adaptar el esquema a bases de datos más grandes utilizando un diseño en capas. Por ejemplo, en lugar de almacenar todos los archivos en un directorio, guárdelos en subdirectorios separados basados ​​en los primeros caracteres de sus nombres. Esto es lo que hace git , por ejemplo: sus objetos, indexados por hash SHA-1, se almacenan en archivos llamados .git/objects/01/2345679abcdef0123456789abcdef01234567. Otros ejemplos de programas que utilizan una estratificación semántica son los servidores proxy de almacenamiento en caché web Wwwoffle y polipo ; ambos almacenan la copia en caché de una página encontrada en una URL en un archivo llamadowww.example.com/HASH donde HASH es una codificación de algún hash de la URL.

Otra fuente de ineficiencia es que la mayoría de los sistemas de archivos desperdician mucho espacio al almacenar archivos pequeños: se desperdicia hasta 2kB por archivo en sistemas de archivos típicos, independientemente del tamaño del archivo.

Si elige usar una base de datos real, no necesita renunciar a la comodidad del acceso transparente al sistema de archivos. Hay varios sistemas de archivos FUSE para acceder a bases de datos, incluidos Berkeley DB (con dbfs de Jeff Garzik ), Oracle (con Oracle DBFS ), MySQL (con mysqlfs ), etc.

¹ Para una URL como http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unix, Polipo usa el archivo unix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==, con un encabezado agregado dentro del archivo que indica la URL real en texto claro; el nombre del archivo es la codificación base64 del hash MD5 (en binario) de la URL. Wwwoffle usa el archivo http/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhw; el nombre del archivo es una codificación local del hash MD5, y un archivo complementario http/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhwcontiene la URL.

Gilles 'SO- deja de ser malvado'
fuente
7

dbmutilpodría conseguirte lo que quieres. Tiene utilidades de shell para las operaciones que describe en la pregunta. No diría que es exactamente estándar, pero tiene las instalaciones que desea.

Preocupado por TunbridgeWells
fuente
5

Desde que lo nombró, el cliente redis estándar tiene una interfaz de línea de comando a través redis-cli. Algunos ejemplos de redis-cli -h:

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

(Y si desea acceder a la base de datos a través del sistema de archivos, puede usar sockets -s. Una herramienta que leería el índice de base de datos directamente en cada invocación sería muy ineficiente).

Stéphane Gimenez
fuente