Redis
 sql >> база данни >  >> NoSQL >> Redis

Скрипт за изтриване на заместващи символи на Redis с помощта на EVAL, SCAN и DEL връща команди за запис, които не са разрешени след недетерминирани команди

АКТУАЛИЗИРАНЕ: по-долу се отнася за версии на Redis до 3.2. От тази версия репликацията, базирана на ефект, премахва забраната за недетерминизъм, така че всички залози са изключени (или по-скоро включени).

Не можете (и не трябва) да смесвате SCAN семейство от команди с всяка команда за запис в скрипт, тъй като отговорът на първата зависи от вътрешните структури от данни на Redis, които от своя страна са уникални за сървърния процес. Казано по друг начин, два процеса на Redis (напр. главен и подчинен) не са гарантирани, че ще върнат едни и същи отговори (така че в контекста на репликация на Redis [който не е базиран на операция, а на оператор], това би го нарушило).

Redis се опитва да се защити от такива случаи, като блокира всяка команда за запис (като DEL ), ако се изпълнява след произволна команда (напр. SCAN но също и TIME , SRANDMEMBER и подобни). Сигурен съм, че има начини да заобиколите това, но бихте ли искали да го направите? Не забравяйте, че ще отидете в неизвестна територия, където поведението на системата не е дефинирано.

Вместо това приемете факта, че не трябва да смесвате произволно четене и запис, и се опитайте да измислите различен подход за решаване на проблема си, а именно изтриване на куп ключове според модел по атомен начин.

Първо се запитайте дали можете да облекчите някое от изискванията. Трябва ли да е атомен? Атомарността означава, че Redis ще бъде блокиран за продължителността на изтриването (независимо от окончателното изпълнение) и че продължителността на операцията зависи от размера на заданието (т.е. броя на ключовете, които се изтриват и тяхното съдържание [изтриването на голям набор е по-скъпо от изтриването на кратък низ например]).

Ако атомарността не е задължителна, периодично/лениво SCAN и изтрийте на малки партиди. Ако е задължително, разберете, че по същество се опитвате да подражавате на злите KEYS команда :) Но можете да се справите по-добре, ако имате предварителни познания за шаблона.

Ако приемем, че моделът е известен по време на изпълнение на вашето приложение, можете да съберете съответните ключове (например в набор) и след това да използвате тази колекция, за да актуализирате изтриването по атомен и безопасен за репликация начин, който е по-ефективен в сравнение с преминаването през цялото ключово пространство .

Въпреки това, най-трудният проблем е, ако трябва да стартирате ad-hoc съпоставяне на шаблони, като същевременно гарантирате атомарност. Ако е така, проблемът се свежда до получаването на филтрирана по модел моментна снимка на ключовото пространство, веднага последвана от поредица от изтривания (подчертавайки отново:докато базата данни е блокирана). В този случай можете много добре да използвате KEYS в рамките на вашия Lua скрипт и се надявайте на най-доброто... (но като знаете много добре, че можете да прибягвате до SHUTDOWN NOSAVE доста бързо :P).

Последната оптимизация е да индексира самото ключово пространство. И двете SCAN и KEYS по същество са пълни сканирания на таблицата, така че какво ще стане, ако трябва да индексираме тази таблица? Представете си, че поддържате индекс на имената на ключове, които могат да бъдат запитани по време на транзакция - вероятно можете да използвате сортиран набор и лексикографски диапазони (HT @TwBert ), за да премахне повечето от нуждите за съвпадение на шаблона. Но на значителна цена... не само ще правите двойно счетоводство (съхранявайки разходите за името на всеки ключ в RAM и CPU), ще бъдете принудени да добавите сложност към приложението си. Защо добавяне на сложност? Тъй като за да приложите такъв индекс, ще трябва да го поддържате сами в слоя на приложението (и вероятно всичките ви други скриптове на Lua), като внимателно обвивате всяка операция на запис в Redis в транзакция, която също актуализира индекса.

Ако приемем, че сте направили всичко това (и като вземете предвид очевидните клопки като потенциала на допълнителната сложност за грешки, поне удвоено натоварване при запис на Redis, RAM и CPU, ограничения за мащабиране и така нататък...), можете да се потупате по рамото и се поздравете, че използвате Redis по начин, за който не е предназначен. Докато предстоящите версии на Redis може (или може да не) включват по-добри решения за това предизвикателство (@TwBert – искате да направите съвместен RCP/принос и отново да хакнете малко Redis? ), преди да опитате това, наистина ви призовавам да преосмислите първоначалните изисквания и да се уверите, че използвате Redis правилно (т.е. проектирате вашата „схема“ според нуждите си за достъп до данни).




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Пуснете redis в маратон (mesos) под един URL адрес

  2. Как да накарам клиента да изтегли много голям файл, който се генерира в движение

  3. Redis с Resque и Rails:командата ERR не е разрешена, когато се използва памет> 'maxmemory'

  4. StackExchange.Redis - Използване на LockTake / LockRelease

  5. Възможно ли е да има Linux VFS кеш с FUSE файлова система?