sql >> Databasteknik >  >> NoSQL >> Redis

Redis raderingsskript med jokertecken med EVAL, SCAN och DEL returnerar Skrivkommandon är inte tillåtna efter icke-deterministiska kommandon

UPPDATERING: nedanstående gäller Redis-versioner upp till 3.2. Från den versionen upphäver effektbaserad replikering förbudet mot icke-determinism så alla spel är avstängda (eller snarare på).

Du kan inte (och bör inte) blanda SCAN familj av kommandon med vilket skrivkommando som helst i ett skript eftersom det förstnämndas svar är beroende av de interna Redis-datastrukturerna som i sin tur är unika för serverprocessen. Med andra ord är det inte garanterat att två Redis-processer (t.ex. master och slav) returnerar samma svar (så i Redis-replikeringskontext [som inte är operationsbaserad utan uttalande] skulle det bryta det).

Redis försöker skydda sig mot sådana fall genom att blockera alla skrivkommandon (som DEL). ) om det körs efter ett slumpmässigt kommando (t.ex. SCAN men också TIME , SRANDMEMBER och liknande). Jag är säker på att det finns sätt att komma runt det, men skulle du vilja göra det? Kom ihåg att du kommer in på okänt territorium där systemets beteende inte är definierat.

Acceptera istället det faktum att du inte ska blanda slumpmässiga läsningar och skrivningar och försök tänka ut ett annat tillvägagångssätt för att lösa ditt problem, nämligen att radera ett gäng nycklar enligt ett mönster på ett atomärt sätt.

Fråga dig själv först om du kan släppa på något av kraven. Måste det vara atomärt? Atomicity innebär att Redis kommer att blockeras under raderingens varaktighet (oavsett den slutliga implementeringen) och att längden på operationen beror på jobbets storlek (dvs. antalet nycklar som raderas och deras innehåll [ta bort en stor uppsättning är dyrare än att ta bort en kort sträng till exempel]).

Om atomicitet inte är ett måste, SCAN med jämna mellanrum och radera i små omgångar. Om det är ett måste, förstå att du i princip försöker efterlikna de onda KEYS kommando :) Men du kan bättre om du har förkunskaper om mönstret.

Förutsatt att mönstret är känt under körning av din applikation, kan du samla in relevanta nycklar (t.ex. i en uppsättning) och sedan använda den samlingen för att aktualisera borttagningen på ett atomärt och replikeringssäkert sätt som är mer effektivt jämfört med att gå över hela tangentutrymmet .

Det "svåraste" problemet är dock om du behöver köra ad-hoc-mönstermatchning samtidigt som du säkerställer atomicitet. Om så är fallet, handlar problemet om att erhålla en filtrerad ögonblicksbild av tangentutrymmet omedelbart följt av en rad raderingar (återbetonat:medan databasen är blockerad). I så fall kan du mycket väl använda KEYS inom ditt Lua-manus och hoppas på det bästa... (men du vet väl att du kan ta till SHUTDOWN NOSAVE ganska snabbt :P).

Den senaste optimeringen är att indexera själva tangentutrymmet. Båda SCAN och KEYS är i princip fullbordsskanningar, så tänk om vi skulle indexera den tabellen? Föreställ dig att hålla ett index över nycklarnamn som kan frågas under en transaktion - du kan förmodligen använda en sorterad uppsättning och lexikografiska intervall (HT @TwBert ) för att undanröja de flesta mönstermatchningsbehoven. Men till en betydande kostnad... kommer du inte bara att göra dubbel bokföring (lagra varje nyckels namnkostnader i RAM och CPU), du skulle bli tvungen att lägga till komplexitet i din applikation. Varför lägga till komplexitet? För att implementera ett sådant index måste du underhålla det själv i applikationslagret (och möjligen alla dina andra Lua-skript), och noggrant packa in varje skrivoperation till Redis i en transaktion som också uppdaterar indexet.

Förutsatt att du gjorde allt det (och med hänsyn till de uppenbara fallgroparna som den ökade komplexitetens potential för buggar, åtminstone fördubblad skrivbelastning på Redis, RAM &CPU, restriktioner för skalning och så vidare...) kan du klappa dig själv på axla och gratulera dig själv för att du använder Redis på ett sätt som det inte var designat för. Även om kommande versioner av Redis kanske (eller kanske inte) innehåller bättre lösningar för denna utmaning (@TwBert - vill du göra en gemensam RCP/bidrag och återigen hacka Redis lite? ), innan du försöker detta uppmanar jag dig verkligen att tänka om de ursprungliga kraven och verifiera att du använder Redis korrekt (dvs. designa ditt "schema" enligt dina dataåtkomstbehov).




  1. Ta bort dubbletter av poster med MapReduce

  2. Varför kan inte mitt Redis Lua-skript atomiskt uppdatera nycklar på olika Redis Cluster-noder?

  3. gke kan inte inaktivera Transparent Huge Pages... behörighet nekad

  4. Hur man distribuerar ML-modeller till produktion