Saya ingin menyimpan muatan JSON ke redis. Sebenarnya ada 2 cara yang bisa saya lakukan ini:
Satu menggunakan kunci kunci dan nilai.
kunci: pengguna, nilai: payload (seluruh gumpalan JSON yang bisa 100-200 KB)SET user:1 payload
Menggunakan hash
HSET user:1 username "someone"
HSET user:1 location "NY"
HSET user:1 bio "STRING WITH OVER 100 lines"
Perlu diingat bahwa jika saya menggunakan hash, panjang nilainya tidak dapat diprediksi. Mereka tidak semuanya pendek seperti contoh bio di atas.
Mana yang lebih hemat memori? Menggunakan kunci dan nilai string, atau menggunakan hash?
Jawaban:
Itu tergantung pada bagaimana Anda mengakses data:
Pilih Opsi 1:
Pilih Opsi 2:
PS: Sebagai aturan praktis, pilih opsi yang membutuhkan lebih sedikit pertanyaan pada sebagian besar kasus penggunaan Anda.
sumber
JSON
payload diharapkan (masalah klasik non-atomread-modify-write
).Artikel ini dapat memberikan banyak wawasan di sini: http://redis.io/topics/memory-optimization
Ada banyak cara untuk menyimpan array Objek di Redis ( spoiler : Saya suka opsi 1 untuk kebanyakan kasus penggunaan):
Menyimpan seluruh objek sebagai string bersandi JSON dalam satu kunci dan melacak semua Objek menggunakan set (atau daftar, jika lebih tepat). Sebagai contoh:
Secara umum, ini mungkin metode terbaik dalam banyak kasus. Jika ada banyak bidang dalam Objek, Objek Anda tidak bersarang dengan Objek lain, dan Anda cenderung hanya mengakses sebagian kecil bidang pada satu waktu, mungkin lebih baik untuk pergi dengan opsi 2.
Keuntungan : dianggap sebagai "praktik yang baik." Setiap Objek adalah kunci Redis yang lengkap. Penguraian JSON cepat, terutama ketika Anda perlu mengakses banyak bidang untuk Obyek ini sekaligus. Kekurangan : lebih lambat saat Anda hanya perlu mengakses satu bidang.
Simpan setiap properti Object dalam hash Redis.
Keuntungan : dianggap sebagai "praktik yang baik." Setiap Objek adalah kunci Redis yang lengkap. Tidak perlu mengurai string JSON. Kekurangan : mungkin lebih lambat ketika Anda perlu mengakses semua / sebagian besar bidang dalam suatu Objek. Juga, Objek bersarang (Objek dalam Objek) tidak dapat dengan mudah disimpan.
Simpan setiap Objek sebagai string JSON dalam hash Redis.
Ini memungkinkan Anda untuk menggabungkan sedikit dan hanya menggunakan dua tombol, bukan banyak tombol. Kerugian yang jelas adalah bahwa Anda tidak dapat mengatur TTL (dan hal-hal lain) pada setiap objek pengguna, karena itu hanya bidang di hash Redis dan bukan kunci Redis yang penuh.
Keuntungan : Penguraian JSON cepat, terutama ketika Anda perlu mengakses banyak bidang untuk Obyek ini sekaligus. Kurang "mencemari" ruang nama kunci utama. Kekurangan : Tentang penggunaan memori yang sama dengan # 1 saat Anda memiliki banyak Objek. Lebih lambat dari # 2 saat Anda hanya perlu mengakses satu bidang. Mungkin tidak dianggap sebagai "praktik yang baik."
Simpan setiap properti dari setiap Objek dalam kunci khusus.
Menurut artikel di atas, opsi ini hampir tidak pernah disukai (kecuali jika properti Object perlu memiliki TTL tertentu atau sesuatu).
Keuntungan : Properti objek adalah kunci Redis yang penuh, yang mungkin tidak berlebihan bagi aplikasi Anda. Kekurangan : lambat, menggunakan lebih banyak memori, dan tidak dianggap "praktik terbaik." Banyak polusi dari namespace kunci utama.
Ringkasan Keseluruhan
Opsi 4 umumnya tidak disukai. Opsi 1 dan 2 sangat mirip, dan keduanya cukup umum. Saya lebih suka opsi 1 (secara umum) karena memungkinkan Anda untuk menyimpan Objek yang lebih rumit (dengan banyak lapisan sarang, dll.) Opsi 3 digunakan ketika Anda benar-benar peduli untuk tidak mencemari namespace kunci utama (yaitu Anda tidak ingin ada untuk menjadi banyak kunci dalam database Anda dan Anda tidak peduli tentang hal-hal seperti TTL, key sharding, atau apa pun).
Jika ada yang salah di sini, silakan tinggalkan komentar dan izinkan saya merevisi jawabannya sebelum membatalkan. Terima kasih! :)
sumber
obj
dan menyimpan bidang seperti tampilan, suara, dan pemilih dengan kunci terpisah? Dengan cara ini dengan satu permintaan BACA Anda mendapatkan seluruh objek dan masih dapat memperbarui bagian dinamis dari objek Anda dengan cepat? Pembaruan yang relatif jarang ke bidang dalam string JSON dapat dilakukan dengan membaca dan menulis seluruh objek kembali dalam transaksi.Beberapa tambahan pada serangkaian jawaban yang diberikan:
Pertama-tama, jika Anda akan menggunakan hash Redis secara efisien, Anda harus tahu kunci menghitung jumlah maksimum dan nilai ukuran maksimum - jika tidak, jika hash-max-ziplist-value atau hash-max-ziplist-entries Redis akan mengubahnya menjadi praktis pasangan kunci / nilai biasa di bawah tenda. (lihat hash-max-ziplist-value, hash-max-ziplist-entri) Dan melanggar di bawah tenda dari opsi hash BENAR-BENAR BURUK, karena setiap pasangan kunci / nilai biasa di dalam Redis menggunakan +90 byte per pasang.
Ini berarti bahwa jika Anda mulai dengan opsi dua dan tanpa sengaja keluar dari nilai max-hash-ziplist-Anda akan mendapatkan +90 byte per SETIAP ATTRIBUTE yang Anda miliki di dalam model pengguna! (sebenarnya bukan +90 tetapi +70 lihat output konsol di bawah)
Untuk jawaban TheHippo, komentar pada Opsi satu menyesatkan:
hgetall / hmset / hmget untuk menyelamatkan jika Anda membutuhkan semua bidang atau operasi beberapa get / set.
Untuk jawaban BMiner.
Pilihan ketiga sebenarnya sangat menyenangkan, untuk dataset dengan max (id) <memiliki-max-ziplist-value solusi ini memiliki kompleksitas O (N), karena, yang mengejutkan, Reddis menyimpan hash kecil sebagai wadah array seperti panjang / kunci / nilai benda!
Tetapi Anda tidak perlu khawatir, Anda akan memecahkan entri hash-max-ziplist-sangat cepat dan di sana Anda sekarang Anda benar-benar di solusi nomor 1.
Opsi kedua kemungkinan besar akan menuju solusi keempat di bawah tudung karena sebagai pertanyaan menyatakan:
Dan seperti yang sudah Anda katakan: solusi keempat adalah +70 byte paling mahal untuk setiap atribut.
Saran saya bagaimana mengoptimalkan dataset tersebut:
Anda punya dua opsi:
Jika Anda tidak dapat menjamin ukuran maksimal beberapa atribut pengguna daripada Anda mencari solusi pertama dan jika masalah memori sangat penting daripada kompres pengguna json sebelum disimpan dalam redis.
Jika Anda dapat memaksa ukuran maksimum semua atribut. Daripada Anda dapat mengatur hash-max-ziplist-entri / nilai dan menggunakan hash baik sebagai satu hash per representasi pengguna ATAU sebagai optimasi memori hash dari topik ini panduan Redis: https://redis.io/topics/memory-optimization dan menyimpan pengguna sebagai string json. Bagaimanapun Anda juga dapat mengompres atribut pengguna yang panjang.
sumber