UNIX的标准键/值数据存储


16

我知道unix 的键/值库(berkeleydbgdbmredis ...)。但是在开始编码之前,我想知道是否存在用于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...

谢谢

Answers:


10

我认为没有为此的标准工具。grep/ awk/ 除外sed。但是使用此功能时,您需要注意很多其他问题,例如锁定,格式,特殊字符等。

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

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


谢谢 。我很快用sqlite API编写了一个工具。工作正常。
Pierre

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。使用语义分层的程序的其他例子是Web缓存代理Wwwofflepolipo ; 都将在URL处找到的页面的缓存副本存储在名为www.example.com/HASH 其中HASH是URL哈希的某种编码。¹

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

如果选择使用真实数据库,则无需放弃透明文件系统访问的便利。有几种FUSE文件系统可以访问数据库,包括Berkeley DB(使用Jeff Garzik的dbfs),Oracle(使用Oracle DBFS),MySQL(使用mysqlfs)等。

¹ 对于类似的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。


7

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


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

(而且,如果您想通过文件系统访问数据库,则可以将sockets与配合使用-s。在每次调用时直接读取数据库索引的工具效率会非常低下。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.