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

Redis wildcard menghapus skrip menggunakan EVAL, SCAN, dan DEL mengembalikan perintah Tulis tidak diizinkan setelah perintah non-deterministik

PERBARUI: di bawah ini berlaku untuk versi Redis hingga 3.2. Dari versi tersebut, replikasi berbasis efek mencabut larangan non-determinisme sehingga semua taruhan dibatalkan (atau lebih tepatnya, aktif).

Anda tidak dapat (dan tidak boleh) mencampur SCAN keluarga perintah dengan perintah tulis apa pun dalam skrip karena balasan yang pertama bergantung pada struktur data Redis internal yang, pada gilirannya, unik untuk proses server. Dengan kata lain, dua proses Redis (misalnya master dan slave) tidak dijamin untuk mengembalikan balasan yang sama (jadi dalam konteks replikasi Redis [yang bukan berbasis operasi tetapi berbasis pernyataan] yang akan merusaknya).

Redis mencoba melindungi dirinya dari kasus seperti itu dengan memblokir perintah tulis apa pun (seperti DEL ) jika dijalankan setelah perintah acak (mis. SCAN tetapi juga TIME , SRANDMEMBER dan serupa). Saya yakin ada cara untuk menyiasatinya, tetapi apakah Anda ingin melakukannya? Ingat, Anda akan masuk ke wilayah yang tidak diketahui di mana perilaku sistem tidak ditentukan.

Alih-alih, terimalah kenyataan bahwa Anda tidak boleh mencampuradukkan pembacaan dan penulisan acak dan coba pikirkan pendekatan lain untuk memecahkan masalah Anda, yaitu menghapus sekelompok kunci sesuai dengan pola secara atomik.

Pertama-tama tanyakan pada diri Anda apakah Anda dapat melonggarkan salah satu persyaratan. Apakah harus atomik? Atomicity berarti Redis akan diblokir selama durasi penghapusan (terlepas dari implementasi akhir) dan lamanya operasi tergantung pada ukuran pekerjaan (yaitu jumlah kunci yang dihapus dan isinya [menghapus kumpulan besar adalah lebih mahal daripada menghapus string pendek misalnya]).

Jika atomisitas bukanlah suatu keharusan, secara berkala/malas SCAN dan hapus dalam batch kecil. Jika itu suatu keharusan, pahami bahwa pada dasarnya Anda mencoba meniru KEYS yang jahat command :) Tetapi Anda dapat melakukan lebih baik jika Anda memiliki pengetahuan sebelumnya tentang pola tersebut.

Dengan asumsi pola diketahui selama runtime aplikasi Anda, Anda dapat mengumpulkan kunci yang relevan (misalnya dalam Set) dan kemudian menggunakan koleksi itu untuk mengaktualisasikan penghapusan dengan cara atom dan aman-replikasi yang lebih efisien dibandingkan dengan memeriksa seluruh ruang kunci .

Namun, masalah yang paling "sulit" adalah jika Anda perlu menjalankan pencocokan pola ad-hoc sambil memastikan atomisitas. Jika demikian, masalahnya bermuara pada memperoleh snapshot yang difilter menurut pola dari keyspace segera diikuti oleh serangkaian penghapusan (menekankan kembali:saat database diblokir). Dalam hal ini Anda dapat menggunakan KEYS dalam skrip Lua Anda dan berharap yang terbaik... (tetapi mengetahui sepenuhnya bahwa Anda dapat menggunakan SHUTDOWN NOSAVE cukup cepat :P).

Optimasi Terakhir adalah mengindeks keyspace itu sendiri. Keduanya SCAN dan KEYS pada dasarnya adalah pemindaian tabel penuh, jadi bagaimana jika kita mengindeks tabel itu? Bayangkan menyimpan indeks pada nama kunci yang dapat ditanyakan selama transaksi - Anda mungkin dapat menggunakan Kumpulan Terurut dan rentang leksikografis (HT @TwBert ) untuk menghilangkan sebagian besar kebutuhan pencocokan pola. Tetapi dengan biaya yang signifikan... Anda tidak hanya akan melakukan pembukuan ganda (menyimpan biaya nama setiap kunci dalam RAM dan CPU), Anda juga akan dipaksa untuk menambah kerumitan pada aplikasi Anda. Mengapa menambahkan kompleksitas? Karena untuk mengimplementasikan indeks seperti itu, Anda harus memeliharanya sendiri di lapisan aplikasi (dan mungkin semua skrip Lua Anda yang lain), dengan hati-hati membungkus setiap operasi tulis ke Redis dalam transaksi yang juga memperbarui indeks.

Dengan asumsi Anda melakukan semua itu (dan dengan mempertimbangkan jebakan yang jelas seperti potensi kompleksitas tambahan untuk bug, setidaknya dua kali lipat beban tulis pada Redis, RAM &CPU, pembatasan penskalaan, dan sebagainya ...) bahu dan ucapkan selamat kepada diri Anda sendiri karena menggunakan Redis dengan cara yang tidak dirancang untuk itu. Meskipun versi Redis yang akan datang mungkin (atau mungkin tidak) menyertakan solusi yang lebih baik untuk tantangan ini (@TwBert - ingin melakukan RCP/contrib bersama dan meretas Redis sedikit lagi? ), sebelum mencoba ini, saya sangat menyarankan Anda untuk memikirkan kembali persyaratan awal dan memverifikasi bahwa Anda menggunakan Redis dengan benar (yaitu merancang "skema" Anda sesuai dengan kebutuhan akses data Anda).




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Redis - Kesalahan:nilai bukan float yang valid

  2. Tidak dapat memulai server Redis karena kesalahan file konfigurasi

  3. ScaleGrid Hosting Untuk Redis™ Di Akun AWS Anda Sendiri

  4. Bagaimana memulai redis-server pada port yang berbeda dari port default 6379 di ubuntu

  5. Kesalahan saat menjalankan skrip Lua dari klien redis