Redis
 sql >> Teknologi Basis Data >  >> NoSQL >> Redis

Pengantar Struktur Data Redis:Hash

Hash redis adalah (cukup intuitif!) hash yang memetakan nama string ke nilai string. Mereka pada dasarnya bernama wadah bidang unik dan nilainya. Mereka adalah cara sempurna untuk merepresentasikan objek sebagai struktur data Redis. Seperti yang diharapkan, mereka menyediakan operasi dasar waktu konstan seperti mendapatkan, mengatur, ada, dll. Banyak operasi lanjutan juga disediakan. Daftar lengkap perintah hash ada di sini.

Mari kita mulai dari redis-cli .

# hmset key field value [field value ...] :  Insert elements in a hash. O(N), N is # of field being set
127.0.0.1:6379> hmset std:101 name "John Smith" dob "01-01-2000" gender M active 0 cgpa 2.9
OK

# hgetall key : key all keys and values in the hash. O(N), N is size of hash
127.0.0.1:6379> hgetall std:101
 1) "name"
 2) "John Smith"
 3) "dob"
 4) "01-01-2000"
 5) "gender"
 6) "M"
 7) "active"
 8) "0"
 9) "cgpa"
10) "2.9"
127.0.0.1:6379> hmset std:102 name "Jane" name "Ann"
OK
# If duplicates are found, only the last set is valid
127.0.0.1:6379> hgetall std:102
1) "name"
2) "Ann"

# hexists key field: does field exist in the hash with key. O(1)
127.0.0.1:6379> hexists std:102 cgpa
(integer) 0

# hincrby key field increment: Increment the integer field by increment. O(1)
127.0.0.1:6379> hincrby std:101 active 1
(integer) 1

# hget key field : the value for field in the hash stored at key. O(1)
127.0.0.1:6379> hget std:101 active
1) "1"
# If field doesn't exist, hincrby sets it to 0 and then applies increment
127.0.0.1:6379> hincrby std:102 active 2
(integer) 2

# hmget key field [field ...]: the values of the fields requested for the hash with key. O(N), N is # of keys requested
127.0.0.1:6379> hmget std:102 active
1) "2"

# hincrbyfloat key field increment: Increment the float value in field by increment. O(1) 
127.0.0.1:6379> HINCRBYFLOAT std:101 cgpa 1.0
"3.9"

# HSETNX key field value: set field to value if not alread set. O(1)
127.0.0.1:6379> hsetnx std:102 cgpa 4.0
(integer) 1
127.0.0.1:6379> hget std:102 cgpa
"4.0"

# hlen key: number of fields in the hash. O(1)
127.0.0.1:6379> hlen std:101
(integer) 5

# hkeys key : all fields in the hash. O(N), N is size of hash
127.0.0.1:6379> hkeys std:101
1) "name"
2) "dob"
3) "gender"
4) "active"
5) "cgpa"

Seperti yang kami harapkan dari hosting kami untuk Redis™* sebagai server struktur data, kami melihat bahwa Redis menyediakan operasi yang cukup berguna dan canggih pada hash.

Internal

Seperti Kumpulan Redis, hash Redis juga diimplementasikan sebagai  kamus. Kamus di Redis diimplementasikan sebagai tabel hash yang menggunakan fungsi hash MurmurHash2 dan berkembang melalui pengubahan ukuran tambahan. Tabrakan hash ditangani dengan chaining. Detail lebih lanjut dapat ditemukan dalam implementasi Redis dari kamus di dict.c.
Seperti halnya Set, ada pengoptimalan penyimpanan yang dibuat untuk hash yang lebih kecil. Struktur data ini disebut ziplist (Hash dioptimasi menggunakan struktur data berbeda yang disebut zipmap sebelum Redis 2.6) dalam implementasi Redis. Ini pada dasarnya adalah daftar tertaut ganda yang dikodekan secara khusus yang dioptimalkan untuk penghematan memori. Data, serta pointer disimpan inline. Ziplist juga digunakan untuk mengoptimalkan penyimpanan kumpulan dan daftar terurut yang lebih kecil. Sebuah hash ketika diratakan ke dalam daftar seperti itu terlihat seperti, [key1, value1, key2, value2, ...]. Bagaimana ini lebih efisien daripada kunci biasa? Hash dengan beberapa kunci dapat dikemas dengan cerdik ke dalam struktur seperti array linier ini (yaitu daftar zip) sambil tetap menjamin kinerja O(1) yang diamortisasi untuk mendapatkan dan mengatur. Jelas ini tidak dapat mengikuti karena bidang hash meningkat. Seiring pertumbuhan hash, hash diubah menjadi struktur kamus standar untuk mempertahankan kinerja O(1) dan penghematan ruang hilang. Parameter konfigurasi redis yang mengontrol transformasi ini adalah:

  • list-max-ziplist-entries default (512):Ubah ke representasi standar jika hash tumbuh lebih besar dari batas ini.
  • list-max-ziplist-value default (64):Ubah ke representasi standar jika elemen terbesar dalam hash menjadi lebih besar dari batas ini.

Detail lebih lanjut dapat dipahami dari kode dan komentar dalam implementasi yang ditemukan di sini. Penghematan memori dari penggunaan pengoptimalan khusus ini sangat signifikan. Kami akan membicarakannya lebih detail di bagian berikutnya.

Optimalisasi Memori

Salah satu rekomendasi terkenal untuk penghematan memori saat menggunakan Redis adalah menggunakan hash alih-alih string biasa. Ini adalah kasus penggunaan yang penting untuk memanfaatkan kekuatan hash Redis dalam aplikasi dunia nyata. Dari dokumentasi Redis resmi tentang pengoptimalan memori:

Gunakan hash jika memungkinkan

Hash kecil dikodekan dalam ruang yang sangat kecil, jadi Anda harus mencoba merepresentasikan data Anda menggunakan hash setiap kali memungkinkan. Misalnya jika Anda memiliki objek yang mewakili pengguna dalam aplikasi web, daripada menggunakan kunci yang berbeda untuk nama, nama keluarga, email, kata sandi, gunakan hash tunggal dengan semua bidang yang diperlukan.

Pos tersebut kemudian mengusulkan satu cara untuk memetakan berbagai objek ke dalam kumpulan hash untuk memanfaatkan penghematan memori. Instagram, dalam posting blog yang sangat populer, menjelaskan penggunaan teknik serupa yang membantu mereka mencapai urutan besarnya potensi penghematan. Blog lain yang mencoba mengukur manfaat pengoptimalan adalah ini.

Aplikasi

  • Haha Redis secara alami cocok untuk menyimpan objek:sesi, pengguna, pengunjung, dll. Ini menjadikannya salah satu struktur data utama yang disediakan oleh Redis.
  • Dalam bentuk memori yang dioptimalkan, ini adalah pilihan yang sangat baik untuk menyimpan data dalam jumlah besar.

Toko Alamat Objek

Karena, pengoptimalan memori adalah kasus penggunaan penting untuk hash, mari kita bahas contoh yang mirip dengan penerapan Instagram untuk menunjukkan cara memanfaatkan fitur hemat memori dari hash Redis. Katakanlah, kami memiliki penyebaran Content-addressable storage (CAS) yang sangat besar dengan ratusan juta objek yang disimpan. Lokasi setiap objek adalah string hash. Kami bermaksud mengembangkan sistem pencarian untuk mengetahui lokasi objek yang diberikan ID-nya. Cara umum untuk melakukan ini di Redis adalah dengan menggunakan string.

set object:14590860 "007f80f0a62408..."
set object:11678 "009f80abcd0a60..."
...

Pendekatan ini bekerja dengan baik. Namun karena jumlah objek yang kita miliki sangat banyak, pada akhirnya kita akan membutuhkan banyak memori untuk Redis. Kami ingin melakukan yang lebih baik. Mari kita ambil pendekatan hash yang dioptimalkan memori untuk masalah ini. Kita harus memilih nilai yang tepat untuk list-max-ziplist-entries dan list-max-ziplist-value . Nilai yang benar untuk list-max-ziplist-value adalah berapa pun panjang maksimal string hash alamat penyimpanan. Nilai list-max-ziplist-entries harus dijaga cukup rendah dan akan tergantung pada jumlah total hash bucket yang ingin kita buat. Ini akan lebih baik diketahui secara empiris. Untuk misalnya untuk 100 juta objek kita bisa memilih untuk menggunakan 100k hash. Entri maksimum dalam kasus itu adalah 100m / 100k =1000. Logika aplikasi untuk memutuskan hash mana yang digunakan untuk alamat penyimpanan objek adalah:bagi ID objek dengan 100k dan buang sisanya. Dengan demikian ID objek 14590860 akan masuk ke hash (14590860/100k) =145 yaitu


hset object:145 14590860 "007f80f0a62408..."
hget object:145 14590860
> "007f80f0a62408..."

Implementasi ini tidak hanya akan lebih ringan pada memori tetapi juga harus menyediakan lokalitas cache yang baik.

Berikut adalah postingan kami yang lain dalam rangkaian struktur data Redis.

  • Set Redis
  • Redis bitmap
  • Mengubah kumpulan yang diurutkan

  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Bagaimana saya bisa menjalankan perintah di redis tanpa mendapat respons sama sekali?

  2. Redis AOF fsync (SELALU) vs. pohon LSM

  3. Menerapkan ScaleGrid DBaaS untuk Redis™ di AWS Virtual Private Cloud (VPC)

  4. ServiceStack.Redis Tidak dapat membaca transport - BasicRedisClientManager

  5. redis cluster terus mencetak log WSA_IO_PENDING