适用于 UNIX 的标准键/值数据存储

适用于 UNIX 的标准键/值数据存储

我知道关于核心价值UNIX 的库(伯克利数据库,数据库管理系统,雷迪斯...)。但在开始编码之前,我想知道是否有一个适用于 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...

谢谢

答案1

我认为没有一个标准工具可以做到这一点。除了grep/ awk/sed等。但是使用这个你需要关心很多其他问题,比如锁定、格式、特殊字符等。

我建议使用sqlite。定义一个简单的表,然后创建tool_get()tool_put()shell 函数。sqlite便携、快速。

您将免费获得额外的灵活性。您可以定义约束、索引来调整脚本或有一天以其他语言使用该数据库。

答案2

如果您的数据库足够小,那么您可以使用文件系统。这种方法的优点是技术含量很低,并且只需很少的代码就可以在任何地方工作。如果键由可打印字符组成且不包含/,则可以将它们用作文件名:

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.使用语义分层的程序的其他示例是 Web 缓存代理沃夫勒波利波;两者都将在 URL 处找到的页面的缓存副本存储在名为的文件中,www.example.com/HASH其中 HASH 是 URL 的某些哈希值的某种编码。

效率低下的另一个原因是,大多数文件系统在存储小文件时会浪费大量空间——在典型的文件系统上,每个文件最多浪费 2kB,与文件的大小无关。

如果您选择使用真正的数据库,则无需放弃透明文件系统访问的便利。有几个保险丝文件系统到访问数据库包括伯克利数据库(与Jeff Garzik 的 dbfs)、甲骨文(与甲骨文数据库文件系统)、MySQL(与mysqlfs), ETC。

1 对于类似 的 URL http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unix,Polipo 使用文件unix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==,并在文件内添加一个标头,以明文形式指示实际 URL;文件名是 URL 的 MD5 哈希值(二进制)的 Base64 编码。 Wwwoffle 使用该文件http/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhw;文件名是 MD5 散列的本地编码,并且伴随文件http/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhw包含 URL。

答案3

dbmutil可能会得到你想要的。它具有用于您在问题中描述的操作的 shell 实用程序。我不会说它完全是标准的,但它确实有你想要的设施。

答案4

如果你想使用GBBM GNU 数据库

在基于 Debian 的操作系统(buster)上测试:

apt install gdbmtool

使用 bash gdbmtool 从标准输入读取命令:

$ gdbmtool -s datastore.gdbm <<<"store KEY VALUE"
  # load from file (rows format "key: value")
$ gdbmtool -s datastore.gdbm < <(awk -F: '{print "store "$1" "$2}'  file_key_values.txt)
$ gdbmtool -s datastore.gdbm <<< "fetch KEY"
  # fetch many keys (only values outputed in order)
$ gdbmtool -s datastore.gdbm < <(awk '{print "fetch "$1}' file_keys.txt)
$ gdbmtool -s datastore.gdbm <<<"delete KEY"
$ gdbmtool -s datastore.gdbm list

更多内容请参见man gdbmtool

倾倒

$ gdbm_dump datastore.gdbm > mydump.txt

负载突降

$ gdbm_load mydump.txt datastore.gdbm

相关内容