Edit:Nu med den uppdaterade koden tror jag att din metod är fundamentalt felaktig förutom vad du rapporterar.
Så som du har implementerat det måste du köra KEYS
i produktion - det här är dåligt. När du skalar ut kommer du att orsaka en växande, och onödig, systemblockerande belastning på servern. Som varje bit av dokumentationen på den säger, gör inte använd keys
i produktion. Observera att kodning av utgångstiden i nyckelnamnet ger dig ingen fördel. Om du gjorde den delen av nyckelnamnet till skapandets tidsstämpel, eller till och med ett slumpmässigt nummer, skulle ingenting förändras. Ja, om du tog bort den biten skulle ingenting förändras.
En mer förnuftig väg skulle istället vara att använda ett nyckelnamn som inte är tidsberoende. Användningen av expiration hanterar den funktionen åt dig. Låt oss kalla din prisbegränsade sak för en "session". Ditt nyckelnamn utan tidsstämpeln är "sessions-ID". Genom att ange ett utgångsdatum på 60-talet på den kommer den inte längre att vara tillgänglig vid 61-talet. Så du kan på ett säkert sätt öka och jämföra resultatet till din gräns utan att behöva veta aktuell tid eller utgångstid. Allt du behöver är ett statiskt nyckelnamn och ett lämpligt utgångsdatum på det.
Om du INCR
en icke-existerande nyckel kommer Redis att returnera "1" vilket betyder att den skapade nyckeln och ökade den i ett enda steg/samtal. så i princip ser logiken ut så här:
- skapa "session"-ID
- ökningsräknare med ID
- jämför resultat med limit
- om antalet ==1, ställ in utgången till 60s
- ID-antal> gräns, avvisa
Steg 3.1 är viktigt. Ett antal 1 betyder att detta är en ny nyckel i Redis, och du vill ställa in ditt utgångsdatum på den. Allt annat betyder att utgången redan borde ha ställts in. Om du ställer in den i 3.2 kommer du att bryta processen eftersom den kommer att bevara räknaren i mer än 60s.
Med detta behöver du inte ha dynamiska nyckelnamn baserat på utgångstiden, och behöver därför inte använda keys
för att ta reda på om det finns en befintlig "session" för det satsbegränsade objektet. Det gör också din kod mycket enklare och förutsägbar, samt minskar tur- och returresor till Redis - vilket innebär att det kommer att belasta Redis lägre och prestera bättre. Om hur man gör det med klientbiblioteket du använder kan jag inte säga eftersom jag inte är så bekant med det. Men den grundläggande sekvensen bör kunna översättas till den eftersom den är ganska grundläggande och enkel.
Vad du däremot inte har visat är något som stöder påståendet att utgången inte sker. Allt du har gjort är att visa att Redis verkligen blir tillsagd och anger ett utgångsdatum. För att stödja ditt påstående måste du visa att nyckeln inte löper ut. Vilket innebär att du måste visa hämtning av nyckeln efter utgångstiden, och att räknaren inte "återställdes" genom att återskapas efter utgången. Ett sätt som du kan se att utgången är på väg är att använda tangentutrymmesaviseringar. Med det kommer du att kunna se Redis säga att en nyckel har gått ut.
Där denna process kommer att misslyckas lite är om du gör flera fönster för att begränsa hastigheten, eller om du har ett mycket större fönster (dvs. 10 minuter) i vilket fall sorterade uppsättningar kan vara ett mer förnuftigt alternativ för att förhindra att förfrågningar laddas i förväg. - om så önskas. Men som ditt exempel är skrivet, kommer ovanstående att fungera bra.