Kunci standar / nilai datastore untuk unix

16

Aku tahu tentang kunci / nilai perpustakaan untuk unix ( BerkeleyDB , gdbm , Redis ...). Tetapi sebelum saya mulai coding, saya bertanya-tanya apakah ada alat standar untuk unix yang memungkinkan saya untuk melakukan operasi berikut:

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

Terima kasih

Pierre
sumber

Jawaban:

10

Saya tidak berpikir ada alat standar untuk itu. Kecuali untuk grep/ awk/ seddll. Tetapi menggunakan ini Anda harus peduli tentang banyak masalah lain seperti penguncian, format, karakter khusus, dll.

Saya sarankan untuk digunakan sqlite. Tentukan tabel sederhana lalu buat tool_get()dan tool_put()fungsi shell. sqliteportabel, cepat.

Anda akan mendapatkan fleksibilitas ekstra secara gratis. Anda dapat mendefinisikan batasan, mengindeks untuk mengubah skrip Anda atau menggunakan DB itu dalam bahasa lain suatu hari nanti.

Michał Šrajer
sumber
Terima kasih . Saya dengan cepat menulis alat dengan API sqlite. Ini bekerja dengan baik.
Pierre
9

Jika basis data Anda cukup kecil, maka Anda dapat menggunakan sistem file. Keuntungan dari pendekatan ini adalah sangat berteknologi rendah, dan akan bekerja di mana-mana dengan kode yang sangat sedikit. Jika kunci terdiri dari karakter yang dapat dicetak dan tidak mengandung /, maka Anda dapat menggunakannya sebagai nama file:

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

Untuk mengakomodasi kunci yang berubah-ubah, gunakan checksum kunci sebagai nama file, dan secara opsional menyimpan salinan kunci (kecuali jika Anda senang tidak dapat membuat daftar kunci atau memberi tahu apa kunci untuk entri yang diberikan).

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

Perhatikan bahwa implementasi mainan di atas bukanlah keseluruhan cerita: mereka tidak memiliki properti transaksional yang berguna seperti atomicity. Namun, operasi sistem file dasar seperti pembuatan dan penggantian nama file bersifat atomik, dan dimungkinkan untuk membuat versi atom dari fungsi-fungsi di atas.

Implementasi direct-to-filesystem ini cocok dengan filesystem biasa hanya untuk database kecil, hingga beberapa ribu file. Di luar titik ini, sebagian besar sistem file mengalami kesulitan mengatasi direktori besar. Anda bisa mengadaptasi skema ke database yang lebih besar dengan menggunakan tata letak berlapis. Misalnya, alih-alih menyimpan semua file dalam satu direktori, simpan di subdirektori terpisah berdasarkan beberapa karakter pertama dari namanya. Inilah yang dilakukan git , misalnya: objeknya, yang diindeks oleh hash SHA-1, disimpan dalam file yang disebut .git/objects/01/2345679abcdef0123456789abcdef01234567. Contoh lain dari program yang menggunakan layering semantik adalah proxy caching web Wwwoffle dan polipo ; keduanya menyimpan salinan cache dari halaman yang ditemukan di URL dalam file bernamawww.example.com/HASH di mana HASH adalah penyandian dari beberapa hash URL.¹

Sumber lain dari inefisiensi adalah kebanyakan sistem file membuang banyak ruang ketika menyimpan file kecil - ada pemborosan hingga 2 kB per file pada sistem file biasa, terlepas dari ukuran file.

Jika Anda memilih untuk pergi dengan database nyata, Anda tidak perlu melepaskan kenyamanan akses sistem file transparan. Ada beberapa filesystem FUSE untuk mengakses database termasuk Berkeley DB (dengan dbfs Jeff Garzik ), Oracle (dengan Oracle DBFS ), MySQL (dengan mysqlfs ), dll.

¹ Untuk URL seperti http://unix.stackexchange.com/questions/21943/standard-key-value-datastore-for-unix, Polipo menggunakan file tersebut unix.stackexchange.com/M0pPbpRufiErf4DLFcWlhw==, dengan header tambahan di dalam file yang menunjukkan URL aktual dalam teks yang jelas; nama file adalah pengkodean base64 dari hash MD5 (dalam biner) dari URL. Wwwoffle menggunakan file http/unix.stackexchange.com/DM0pPbpRufiErf4DLFcWlhw; nama file adalah penyandian buatan sendiri dari hash MD5, dan file pendamping http/unix.stackexchange.com/UM0pPbpRufiErf4DLFcWlhwberisi URL.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
7

dbmutilmungkin mendapatkan apa yang Anda inginkan. Ini memiliki utilitas shell untuk operasi yang Anda gambarkan dalam pertanyaan. Saya tidak akan mengatakan itu persis standar, tetapi memiliki fasilitas yang Anda inginkan.

ConcernedOfTunbridgeWells
sumber
5

Karena Anda menamainya, klien redis standar memiliki antarmuka baris perintah melalui redis-cli. Beberapa contoh dari redis-cli -h:

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

(Dan jika Anda ingin mengakses db melalui sistem file Anda dapat menggunakan soket dengan -s. Alat yang akan membaca indeks db langsung pada setiap permintaan akan menjadi sangat tidak efisien.)

Stéphane Gimenez
sumber