Стандартное хранилище данных ключ / значение для Unix

16

Я знаю о библиотеках ключ / значение для unix ( berkeleydb , gdbm , redis ...). Но прежде чем приступить к написанию кода, мне интересно, есть ли стандартный инструмент для Unix, который позволил бы мне выполнять следующие операции:

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

Благодарность

пьер
источник

Ответы:

10

Я не думаю, что есть стандартный инструмент для этого. За исключением grep/ awk/ sedи т. Д. Но при использовании этого вам нужно будет заботиться о многих других проблемах, таких как блокировка, форматирование, специальные символы и т. Д.

Я предлагаю использовать sqlite. Определите простую таблицу, а затем создайте tool_get()и tool_put()выполните функции оболочки. sqliteпортативный, быстрый

Вы получите дополнительную гибкость бесплатно. Вы можете определить ограничения, индексировать для настройки вашего скрипта или использовать эту БД на других языках когда-нибудь.

Михал Шрайер
источник
Спасибо . Я быстро написал инструмент с API sqlite. Работает нормально.
Пьер
9

Если ваша база данных достаточно мала, вы можете использовать файловую систему. Преимущество этого подхода состоит в том, что он очень низкотехнологичен и будет работать везде с очень небольшим количеством кода. Если ключи состоят из печатных символов и не содержат их /, вы можете использовать их в качестве имен файлов:

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

Чтобы приспособить произвольные ключи, используйте контрольную сумму ключа в качестве имени файла и при необходимости сохраните копию ключа (если вы не удовлетворены тем, что не можете перечислить ключи или сказать, что ключ для данной записи).

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

Обратите внимание, что реализации игрушек, описанные выше, не являются целой историей: они не имеют каких-либо полезных транзакционных свойств, таких как атомарность. Однако основные операции с файловой системой, такие как создание и переименование файлов, являются атомарными, и можно создавать атомарные версии функций, описанных выше.

Эти реализации непосредственно в файловую систему подходят для типичных файловых систем только для небольших баз данных, до нескольких тысяч файлов. Помимо этого, большинству файловых систем трудно справляться с большими каталогами. Вы можете адаптировать схему к более крупным базам данных, используя многоуровневую компоновку. Например, вместо того, чтобы хранить все файлы в одном каталоге, храните их в отдельных подкаталогах, основываясь на первых нескольких символах их имен. Вот что делает git , например: его объекты, проиндексированные хешами SHA-1, хранятся в именуемых файлах .git/objects/01/2345679abcdef0123456789abcdef01234567. Другими примерами программ, которые используют семантическое наслоение, являются прокси веб-кэширования Wwwoffle и polipo ; оба хранят кэшированную копию страницы, найденной по URL, в файле с именемwww.example.com/HASH где HASH - это некоторая кодировка некоторого хэша URL-адреса.

Еще одним источником неэффективности является то, что большинство файловых систем тратит много места при хранении небольших файлов - на типичных файловых системах тратится до 2 КБ на файл, независимо от размера файла.

Если вы решите использовать настоящую базу данных, вам не нужно отказываться от удобства прозрачного доступа к файловой системе. Есть несколько файловых систем FUSE для доступа к базам данных, включая Berkeley DB (с dbfs Джеффа Гарзика ), Oracle (с DBFS Oracle ), MySQL (с mysqlfs ) и т. Д.

¹ Для URL-адреса, например http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unix, Polipo использует файл unix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==с добавленным заголовком внутри файла, указывающим фактический URL-адрес в виде открытого текста; имя файла - это кодировка base64 хеша MD5 (в двоичном формате) URL. Wwwoffle использует файл http/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhw; имя файла является доморощенной кодировкой хэша MD5, а сопутствующий файл http/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhwсодержит URL-адрес.

Жиль "ТАК - перестань быть злым"
источник
7

dbmutilможет получить то, что вы хотите. Он имеет утилиты оболочки для операций, которые вы описываете в вопросе. Я бы не сказал, что это точно стандарт, но в нем есть все необходимое.

ConcernedOfTunbridgeWells
источник
5

Так как вы назвали его, стандартный клиент Redis имеет интерфейс командной строки через redis-cli. Некоторые примеры из redis-cli -h:

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

(И если вы хотите получить доступ к БД через файловую систему, вы можете использовать сокеты -s. Инструмент, который будет считывать индекс БД непосредственно при каждом вызове, будет очень неэффективным.)

Стефан Хименес
источник