Hogyan használjuk a SCAN parancsot a KEYS helyett a Redisben?

A Redis, mint villámgyors, memóriában tárolt kulcs-érték adatbázis, a modern webes alkalmazások és szolgáltatások alapköve. Képességével, hogy milliónyi műveletet hajtson végre másodpercenként, kiválóan alkalmas gyorsítótárazásra, valós idejű üzenetküldésre, munkamenet-kezelésre és számos más feladatra. Azonban, mint minden erőteljes eszköz esetében, itt is elengedhetetlen a helyes használat. Az egyik leggyakoribb hiba, amivel a fejlesztők szembesülnek, a Redis kulcsainak kezelésével kapcsolatos, különösen, amikor az összes vagy egy részük lekérdezésére kerül sor. Ezen a ponton merül fel a kérdés: KEYS vagy SCAN?

Ez a cikk mélyrehatóan tárgyalja a két parancs közötti különbségeket, rávilágít a KEYS parancs veszélyeire produkciós környezetben, és bemutatja, hogyan válhat a SCAN parancs a legfőbb szövetségesévé a Redis kulcsainak biztonságos és hatékony kezelésében.

A KEYS Parancs Átka: Miért Kerüljük El Produkciós Környezetben?

A KEYS parancs első ránézésre rendkívül vonzó lehet. Egyszerűen használható: csak meg kell adni egy mintát (például KEYS * az összes kulcs lekérdezéséhez, vagy KEYS user:* a „user:” prefixszel kezdődő kulcsokhoz), és máris megkapjuk a találatokat. Gyorsnak tűnik, hiszen azonnal visszatér az eredménnyel. De ez a látszólagos egyszerűség és sebesség valójában egy alattomos csapda, különösen éles rendszerekben.

Blokkoló Működés: A Redis Teljes Leállása

A KEYS parancs működése alapvetően blokkoló. Ez azt jelenti, hogy amikor kiadja ezt a parancsot a Redis szervernek, a szerver minden egyéb műveletet felfüggeszt addig, amíg az összes kulcsot meg nem találta és vissza nem adta az eredményt. Képzeljen el egy forgalmas weboldalt vagy szolgáltatást, amely másodpercenként több ezer kérést dolgoz fel a Redis segítségével. Ha egy ilyen környezetben kiadja a KEYS * parancsot egy adatbázison, amely több százezer vagy millió kulcsot tartalmaz, a Redis szerver percekig, vagy akár órákig is blokkolva maradhat. Ez az alkalmazás teljes leállását, vagy súlyos késedelmeket eredményez, ami felhasználói elégedetlenséghez és bevételkieséshez vezethet.

A probléma mértéke egyenesen arányos a kulcsok számával. Minél több kulcs van az adatbázisban, annál tovább tart a KEYS parancs végrehajtása, és annál hosszabb ideig lesz blokkolva a szerver. A modern, skálázható alkalmazásoknál ez elfogadhatatlan.

Teljesítménybeli Hatások: CPU és Memória Terhelés

A blokkoláson túl a KEYS parancs jelentős CPU és memória terhelést is okoz. A Redis-nek át kell vizsgálnia az összes kulcsot a memória-beli kulcstérben, hogy megtalálja a mintának megfelelőket. Ez intenzív CPU-használattal jár. Ráadásul az összes megtalált kulcsot a válaszba kell gyűjtenie, és el kell küldenie a kliensnek. Nagy számú kulcs esetén ez a válasz nagyon nagy lehet, ami extra hálózati sávszélességet és memóriát igényel mind a szerver, mind a kliens oldalán.

Egy Redis szerver, amely amúgy is közel van a maximális kapacitásához, könnyen túlterheltté válhat egy KEYS parancs hatására, ami további performancia romláshoz, sőt összeomláshoz is vezethet.

Skálázhatósági Problémák: Jövőbeni Fejfájások

Az adatbázisok mérete általában növekszik az idő múlásával. Ami ma egy kis, kezelhető adathalmaznak számít, az holnapra egy hatalmas, kritikus rendszerré válhat. Ha az alkalmazásod a KEYS parancsra épül, a skálázódás elkerülhetetlenül performancia problémákat fog okozni. Egy jól megtervezett rendszernek képesnek kell lennie a növekedésre anélkül, hogy fundamentálisan megváltoztatná az alapvető műveleteit. A KEYS parancs használata ezt a rugalmasságot nem biztosítja.

Összefoglalva: a KEYS parancsot soha ne használja produkciós környezetben! Csupán fejlesztői és tesztelési célokra, rendkívül kis adathalmazok esetén fogadható el, ahol a blokkolás következményei elhanyagolhatóak.

Ismerkedés a SCAN Parancs Családjával: A Biztonságos Út a Kulcsokhoz

Szerencsére a Redis egy sokkal elegánsabb és biztonságosabb megoldást kínál a kulcsok iterálására: a SCAN parancsot. A SCAN, és rokonai (SSCAN, HSCAN, ZSCAN) úgy lettek megtervezve, hogy a szerver blokkolása nélkül, iteratív módon járják be a kulcsteret. Ez a nem blokkoló működés teszi lehetővé, hogy a Redis továbbra is kiszolgálja az összes bejövő kérést, miközben Ön a kulcsok között keresgél.

Hogyan Működik a SCAN: Lépésről Lépésre

A SCAN parancs egy kurzor alapú iterációs protokollt használ. Ahelyett, hogy egyszerre adna vissza minden eredményt, a SCAN minden híváskor visszaad egy kis adathalmazt (kulcsokat) és egy új kurzorértéket. Ezt a kurzorértéket kell átadni a következő SCAN hívásnak a folytatáshoz. A folyamat addig ismétlődik, amíg a visszakapott kurzor értéke 0 nem lesz, ami jelzi, hogy az iteráció befejeződött.

A SCAN parancs szintaxisa:

SCAN kurzor [MATCH minta] [COUNT szám] [TYPE típus]
  • kurzor: Egy 64 bites unsigned integer, ami az iteráció aktuális pozícióját reprezentálja. Az első híváskor mindig 0-val kell kezdeni. A Redis adja vissza a következő kurzorértéket.
  • MATCH minta (opcionális): Hasonlóan a KEYS-hez, itt is megadhatunk egy glob-stílusú mintát a kulcsok szűrésére (pl. user:*, log-2023-*-*).
  • COUNT szám (opcionális): Ez egy tipp a Redis-nek, hogy hány elemet adjon vissza egy iterációban. Fontos megérteni, hogy ez NEM garancia arra, hogy pontosan annyi elemet kap vissza. A Redis próbálja ezt a számot megközelíteni, de a belső adatszerkezetektől függően kevesebbet vagy többet is visszaadhat. A lényeg, hogy szabályozhatóvá teszi az egy-egy iterációval járó terhelést.
  • TYPE típus (opcionális, Redis 6.0+): Lehetővé teszi, hogy csak bizonyos típusú kulcsokat (pl. string, hash, set, list, zset, stream) keressen.

A SCAN Működési Elve Részletesen

Ahhoz, hogy hatékonyan használjuk a SCAN-t, értsük meg mélyebben a működését:

A Kurzor: Az Iteráció Szíve

A kurzor az iterációs folyamat legfontosabb eleme. Ez egy numerikus érték, amelyet a Redis használ a belső kulcstároló adatstruktúrájának bejárásához. Amikor elindítja a SCAN 0 paranccsal, a Redis elkezdi bejárni a kulcsokat. A parancs visszatér egy új kurzorértékkel és egy listával a talált kulcsokról. A következő hívásnál ezt az új kurzorértéket kell átadni, és így tovább, amíg a Redis végül 0 kurzorértéket nem ad vissza. Ez azt jelzi, hogy az összes kulcsot bejárták, vagy legalábbis az összes elérhető kulcsot a jelenlegi pillanatban.

A MATCH Opció: Szűrés Ráterhelés Nélkül

A MATCH opcióval pontosan olyan mintákat adhat meg, mint a KEYS parancs esetében. Például:

  • MATCH user:*: A „user:” előtaggal kezdődő kulcsok.
  • MATCH *session*: Bárhol tartalmazza a „session” szót.
  • MATCH logs:2023:*-*-*: Egy specifikus log formátum.

A MATCH használata a SCAN-nel sokkal biztonságosabb, mint a KEYS-szel, mert a szűrést a szerver fokozatosan végzi, és nem blokkolja azt.

A COUNT Opció: Egy Tipp, Nem Garancia

A COUNT opcióval adhatunk egy javaslatot a Redis-nek, hogy hány elemet próbáljon meg visszaadni egy iteráció során. Az alapértelmezett érték 10. Nagyobb adatbázisoknál érdemes lehet nagyobb COUNT értéket, például 100 vagy 1000-et használni. Fontos megérteni, hogy ez egy heuristikus opció. A Redis nem garantálja, hogy pontosan annyi elemet ad vissza, amennyit megadott. Lehet kevesebb, és extrém esetben (pl. kevés kulcs az adatbázisban, de sok kitörölt kulcs) lehet több is, vagy akár nulla kulcsot is visszaadhat, miközben a kurzor nem 0. Ez teljesen normális és a SCAN tervezési elvéből fakad. A lényeg, hogy a visszatérő kurzort mindig használjuk a következő híváshoz, függetlenül attól, hogy hány kulcsot kaptunk.

Gyakorlati Példák a SCAN Használatára

Nézzük meg, hogyan használhatjuk a SCAN-t a Redis CLI-n keresztül, majd egy általános logikai példát egy alkalmazásban.

CLI Példák

1. Összes kulcs iterálása:

127.0.0.1:6379> SCAN 0
1) "17"
2) 1) "key:17"
   2) "another:key:3"
   3) "data:value:10"
   4) "user:profile:5"

127.0.0.1:6379> SCAN 17
1) "0"
2) 1) "key:2"
   2) "mykey"
   3) "session:abc"
   4) "product:123"

Az első hívásnál a kurzor 0. Visszakapunk egy 17-es kurzort és 4 kulcsot. A következő hívásnál a 17-es kurzort használjuk. Ekkor 0 kurzort kapunk vissza, ami jelzi a befejezést, és további 4 kulcsot. (Megjegyzés: A kurzorértékek és a kulcsok száma eltérhet a tényleges szerver állapotától.)

2. Szűrt kulcsok iterálása (MATCH):

127.0.0.1:6379> SCAN 0 MATCH user:*
1) "5"
2) 1) "user:profile:1"
   2) "user:data:7"

127.0.0.1:6379> SCAN 5 MATCH user:*
1) "0"
2) 1) "user:settings:9"

Itt csak a „user:” előtaggal rendelkező kulcsokat keressük.

3. COUNT opció használata:

127.0.0.1:6379> SCAN 0 COUNT 100
1) "23"
2) 1) "large_key:1"
   2) "large_key:2"
   ... (kb. 100 kulcs, de lehet kevesebb vagy több)

Ez egy javaslat a Redis-nek, hogy próbáljon meg körülbelül 100 kulcsot visszaadni. A tényleges szám eltérhet.

Alkalmazás Logika (Pszeudokód)

A legtöbb Redis klienskönyvtár rendelkezik beépített SCAN funkcióval, amely leegyszerűsíti ezt a folyamatot. Íme egy általános pszeudokód, ami bemutatja, hogyan kezelheti a SCAN-t az alkalmazásában:

def process_all_keys_with_prefix(prefix_pattern):
    cursor = 0
    all_found_keys = []
    
    while True:
        # A Redis kliens hívása a SCAN paranccsal
        # Ez a példa feltételezi, hogy a kliens `scan` metódusa visszaadja a következő kurzort és a kulcsok listáját
        next_cursor, keys_batch = redis_client.scan(cursor, match=prefix_pattern, count=1000)
        
        for key in keys_batch:
            all_found_keys.append(key)
            # Itt végezhetünk valamilyen műveletet az adott kulccsal
            # print(f"Feldolgozom a kulcsot: {key}")
            
        cursor = next_cursor
        
        # Ha a kurzor 0, az iteráció befejeződött
        if cursor == 0:
            break
            
    return all_found_keys

# Példa használat
# found_user_keys = process_all_keys_with_prefix("user:*")
# print(f"Talált felhasználói kulcsok száma: {len(found_user_keys)}")

Ez a minta biztosítja, hogy a Redis szerver soha ne legyen blokkolva, függetlenül az adatbázis méretétől, és Ön fokozatosan, ellenőrzött módon dolgozza fel a kulcsokat.

A SCAN Család Egyéb Tagjai: SSCAN, HSCAN, ZSCAN

A SCAN parancs nem csak a Redis adatbázis fő kulcsterének iterálására alkalmas, hanem hasonló funkciókat biztosít a komplexebb adatszerkezetek (halmazok, hash-ek, rendezett halmazok) elemeinek bejárására is:

  • SSCAN key cursor [MATCH pattern] [COUNT count]: Egy adott halmaz (Set) elemeit iterálja. Használható például egy felhasználó által kedvelt elemek listájának fokozatos lekérdezésére.
  • HSCAN key cursor [MATCH pattern] [COUNT count]: Egy adott hash (Hash) kulcs-érték párjait iterálja. Ideális például egy komplex objektum (pl. egy felhasználó profiljának összes adata) attribútumainak bejárására.
  • ZSCAN key cursor [MATCH pattern] [COUNT count]: Egy adott rendezett halmaz (Sorted Set) elemeit és pontszámait iterálja. Jó választás például ranglisták elemeinek lapozásához, ahol az elemekhez pontszám is tartozik.

Mindhárom parancs pontosan ugyanazt a kurzor alapú, nem blokkoló iterációs elvet követi, mint a fő SCAN parancs, biztosítva a konzisztens és biztonságos adatkezelést a Redis-ben.

A SCAN Előnyei Összefoglalva

Miért érdemes tehát a SCAN-t választani a KEYS helyett?

  • Nem blokkoló működés: A Redis szerver továbbra is elérhető marad az összes többi művelet számára az iteráció során.
  • Fokozatos terhelés: Az erőforrás-használat (CPU, memória, hálózati sávszélesség) elosztott, nem pedig egy hirtelen csúcsot jelent.
  • Produkciós környezetben használható: Biztonságosan alkalmazható éles rendszerekben is, anélkül, hogy aggódni kellene a szolgáltatás kiesése miatt.
  • Kontrollált iteráció: A COUNT opcióval beállítható, hogy egy-egy iteráció mekkora terhelést jelentsen.
  • Skálázhatóság: A SCAN parancs használata nem befolyásolja hátrányosan az alkalmazás skálázhatóságát, még akkor sem, ha az adatbázis mérete exponenciálisan növekszik.

A SCAN Hátrányai és Megfontolásai

Bár a SCAN sokkal jobb alternatíva, vannak bizonyos szempontok, amiket figyelembe kell venni:

  • Esetleges Ismétlődések és Kihagyások: Mivel a SCAN nem pillanatfelvétel-szerűen működik, ha az adatbázis kulcsai módosulnak (törlés, hozzáadás, átnevezés) az iteráció során, lehetséges, hogy ugyanazt a kulcsot többször is megkapja, vagy egyes kulcsok kimaradnak az iterációból. Ez általában nem kritikus probléma, ha a feldolgozás idempotens.
  • Végleges Konzisztencia: A SCAN csak véglegesen konzisztens eredményeket garantál. Ez azt jelenti, hogy az iteráció végére minden, az iteráció kezdetén létező kulcsot bejár, de a közben hozzáadott vagy törölt kulcsok megjelenése/eltűnése nem garantált, csak az, hogy a teljes kulcstér bejárása megtörténik.
  • Kliensoldali Logika Szükségessége: A SCAN használata megköveteli, hogy a kliens alkalmazás kezelje a kurzort és az iterációs logikát (pl. egy while ciklusban), szemben a KEYS paranccsal, ami egyetlen hívással visszatér az összes eredménnyel.

Mikor Használjuk Akkor a KEYS-t? (Spoiler: Nagyon Ritkán)

Ahogy fentebb említettük, a KEYS parancsnak nagyon korlátozott a használhatósága. Kizárólag:

  • Fejlesztés és Helyi Tesztelés: Amikor egy kis, kontrollált tesztadatbázison dolgozik, és gyorsan meg akar győződni bizonyos kulcsok létezéséről.
  • Nagyon Kicsi, Non-Produkciós Adathalmazok: Ritka esetekben, ahol a Redis nem kritikus fontosságú és az adatbázis mérete garantáltan rendkívül kicsi marad.

De még ilyen esetekben is javasolt a SCAN használatának gyakorlása, hogy megszokja a helyes Redis használati mintákat.

Legjobb Gyakorlatok a SCAN Hatékony Használatához

A SCAN parancs maximális kihasználásához tartsa be a következőket:

  • Használjon Realisztikus COUNT Értéket: Egy 100-1000 közötti COUNT érték általában jó kiindulópont. Ez elegendő kulcsot biztosít a hatékony feldolgozáshoz, de nem terheli túl a szervert. Tesztelje különböző értékekkel a saját környezetében, hogy megtalálja az optimálisat.
  • Mindig Kezelje a Visszatérő Kurzort: Soha ne feledje el a Redis által visszaadott kurzorértéket használni a következő hívásnál. Ellenkező esetben végtelen ciklusba kerülhet, vagy nem járja be az összes kulcsot.
  • Kliensoldali Pufferezés és Feldolgozás: Miután megkapott egy köteget kulcsot a SCAN-től, dolgozza fel azokat a kliens oldalán. Ha további Redis műveletekre van szükség a talált kulcsokkal, végezze el azokat kötegelve (pl. MGET, DEL több kulcsra egyszerre) a hálózati késleltetés minimalizálása érdekében.
  • Optimalizálja a MATCH Mintát: Ha lehetséges, használjon specifikus MATCH mintákat (pl. prefix:*), hogy csökkentse a Redis-nek átvizsgálandó kulcsok számát.
  • Legyen Idempotens a Feldolgozás: Mivel a kulcsok ismétlődhetnek, győződjön meg róla, hogy a kliensoldali logika képes kezelni az ismétlődő kulcsokat anélkül, hogy hibákat okozna vagy nem kívánt mellékhatásokat eredményezne.

Konklúzió: A SCAN Mint Kötelező Eszköz a Redis Kezelésben

A SCAN parancs és családja nem csupán egy alternatíva a KEYS-nek; ez a helyes és biztonságos módja a Redis kulcsainak iterálására, különösen produkciós környezetben. A KEYS parancs használata, különösen nagy adathalmazok esetén, súlyos performancia- és rendelkezésre állási problémákhoz vezethet, ami veszélyeztetheti az egész alkalmazás működését.

A SCAN elsajátítása és beépítése a Redis kulcskezelési stratégiájába elengedhetetlen a robusztus, skálázható és megbízható alkalmazások építéséhez. Bár némi kliensoldali logikát igényel, az általa nyújtott stabilitás és performancia messze felülmúlja a kezdeti befektetést. Ne kockáztassa alkalmazása stabilitását – válassza a SCAN-t a Redis kulcsainak hatékony és biztonságos kezeléséhez!

Leave a Reply

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük