Zoznam všetkých dostupných Redis kľúčov

Java Top

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

1. Prehľad

Zbierky sú základným stavebným prvkom, ktorý sa zvyčajne vyskytuje takmer vo všetkých moderných aplikáciách. Nie je teda prekvapením Redis ponúka rôzne populárne dátové štruktúry napríklad zoznamy, množiny, hašovanie a triedené množiny, ktoré môžeme použiť.

V tomto tutoriále sa dozvieme, ako môžeme efektívne čítať všetky dostupné kľúče Redis, ktoré zodpovedajú konkrétnemu vzoru.

2. Preskúmajte zbierky

Poďme si predstaviť, že náš aplikácia používa Redis na ukladanie informácií o loptičkách používané v rôznych športoch. Mali by sme byť schopní vidieť informácie o každej lopte dostupné z kolekcie Redis. Pre zjednodušenie obmedzíme našu množinu údajov iba na tri guľôčky:

  • Kriketová lopta s hmotnosťou 160 g
  • Futbal s hmotnosťou 450 g
  • Volejbal s hmotnosťou 270 g

Ako obvykle, najskôr si objasnime naše základy prácou na naivnom prístupe k skúmaniu zbierok Redis.

3. Naivný prístup Používanie redis-cli

Predtým, ako začneme písať kód Java na preskúmanie zbierok, mali by sme mať reálnu predstavu o tom, ako to urobíme pomocou súboru redis-cli rozhranie. Predpokladajme, že naša inštancia Redis je k dispozícii na adrese 127.0.0.1 v prístave 6379, aby sme preskúmali každý typ kolekcie pomocou rozhrania príkazového riadku.

3.1. Prepojený zoznam

Najskôr uložme našu množinu údajov do zoznamu prepojených Redisov gule vo formáte športové meno_guľová váha s pomocou rpush príkaz:

% redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> RPUSH lopty „cricket_160“ (celé číslo) 1 127.0.0.1:6379> RPUSH lopty „football_450“ (celé číslo) 2 127.0.0.1:6379> RPUSH lopty „volejbal_270“ (celé číslo) 3

Môžeme si to všimnúť úspešné vloženie do zoznamu spôsobí novú dĺžku zoznamu. Vo väčšine prípadov však budeme voči činnosti vkladania údajov slepí. Vďaka tomu môžeme zistiť dĺžku prepojeného zoznamu pomocou llen príkaz:

127.0.0.1:6379> guľôčky len (celé číslo) 3

Keď už vieme dĺžku zoznamu, je to vhodné Použi oranžová príkaz na jednoduché získanie celého súboru údajov:

127.0.0.1:6379> loptové lopty 0 2 1) „kriket_160“ 2) „futbal_450“ 3) „volejbal_270“

3.2. Nastaviť

Ďalej sa pozrime, ako môžeme preskúmať množinu údajov, keď sa rozhodneme uložiť ju do množiny Redis. Aby sme to dosiahli, musíme najskôr naplniť našu množinu údajov v súbore Redis s názvom gule pomocou znaku smutný príkaz:

127.0.0.1:6379> sedlové lopty „cricket_160“ „football_450“ „volejbal_270“ „kriket_160“ (celé číslo) 3

Ojoj! V našom príkaze sme mali duplicitnú hodnotu. Ale keďže sme do sady pridávali hodnoty, nemusíme sa obávať duplikátov. Samozrejme, vidíme počet položiek pridaných z výstupnej hodnoty odpovede.

Teraz môžeme využiť pamätá príkaz na zobrazenie všetkých nastavených členov:

127.0.0.1:6379> uznáva loptičky 1) „volejbal_270“ 2) „kriket_160“ 3) „futbal_450“

3.3. Hash

Teraz použijeme štruktúru hashovej dát Redis na uloženie našej množiny údajov v hašovacom kľúči s názvom gule, takže hashovacie pole je športový názov a hodnota poľa je váha lopty. Môžeme to urobiť pomocou hmset príkaz:

127.0.0.1:6379> hmset lopty kriket 160 futbal 450 volejbal 270 OK

Ak chcete vidieť informácie uložené v našom haši, môžeme Použi hgetall príkaz:

127.0.0.1:6379> hgetall loptičky 1) „kriket“ 2) „160“ 3) „futbal“ 4) „450“ 5) „volejbal“ 6) „270“

3.4. Zoradená sada

Okrem jedinečnej členské hodnoty nám triedené sady umožňujú udržať skóre vedľa nich. V našom prípade použitia môžeme ponechať názov športu ako hodnotu člena a váhu lopty ako skóre. Použime zadd príkaz na uloženie našej množiny údajov:

127.0.0.1:6379> zadd lopty 160 kriket 450 futbal 270 volejbal (celé číslo) 3

Teraz môžeme najskôr použiť zcard príkazom vyhľadajte dĺžku zoradenej množiny a potom znakom zrange príkaz preskúmať celú sadu:

127.0.0.1:6379> loptičky zcard (celé číslo) 3 127.0.0.1:6379> loptičky zrange 0 2 1) „kriket“ 2) „volejbal“ 3) „futbal“

3.5. Struny

Môžeme tiež vidieť obvyklé reťazce kľúč - hodnota ako povrchná zbierka položiek. Najprv vyplníme náš súbor údajov pomocou mset príkaz:

127.0.0.1:6379> mset lopty: kriket 160 lôpt: futbal 450 lôpt: volejbal 270 ok

Musíme poznamenať, že sme pridali predponu „gule:aby sme mohli identifikovať tieto kľúče od zvyšku kľúčov, ktoré sa môžu nachádzať v našej databáze Redis. Táto stratégia pomenovania nám navyše umožňuje používať kľúče príkaz na preskúmanie našej množiny údajov pomocou porovnávania vzorov predpon:

127.0.0.1:6379> kľúče lopty * 1) „lopty: kriket“ 2) „lopty: volejbal“ 3) „lopty: futbal“

4. Naivná implementácia Java

Teraz, keď sme vyvinuli základnú myšlienku príslušných príkazov Redis, ktoré môžeme použiť na preskúmanie zbierok rôznych typov, je čas, aby sme si zašpinili ruky kódom.

4.1. Maven závislosť

V tejto časti budeme pomocou Jedis klientská knižnica pre Redis v našej implementácii:

 redis.clients jedis 3.2.0 

4.2. Redis klient

Knižnica Jedis prichádza s podobnými metódami Redis-CLI. Odporúčame to však my vytvorte obalového klienta Redis, ktorý bude interne vyvolávať volania funkcií Jedis.

Kedykoľvek pracujeme s knižnicou Jedis, musíme to mať na pamäti jedna inštancia Jedis nie je bezpečná pre vlákna. Preto, aby sme do našej aplikácie dostali zdroj Jedis, môžeme použiť JedisBool, čo je bezpečná oblasť pre vlákna sieťových pripojení.

A keďže nechceme, aby sa počas životného cyklu našej aplikácie v danom čase vznášali viaceré inštancie klientov Redis, mali by sme vytvoriť RedisClient triedy na princípe singletonového vzorového vzoru.

Najskôr vytvorme súkromného konštruktora pre nášho klienta, ktorý interne inicializuje JedisBool keď inštancia RedisClient trieda je vytvorená:

súkromný statický JedisPool jedisPool; private RedisClient (String ip, int port) {try {if (jedisPool == null) {jedisPool = new JedisPool (new URI ("//" + ip + ":" + port)); }} catch (URISyntaxException e) {log.error ("Zlá adresa servera", e); }}

Ďalej potrebujeme prístupový bod k nášmu singleton klientovi. Vytvorme teda statickú metódu getInstance () pre tento účel:

private static volatile RedisClient instance = null; public static RedisClient getInstance (String ip, final int port) {if (instance == null) {synchronized (RedisClient.class) {if (instance == null) {instance = new RedisClient (ip, port); }}} návratová inštancia; }

Na záver sa pozrime, ako môžeme vytvoriť metódu obaľovania nad rámec Jedisovych metód lrangeova metóda:

public List lrange (final String key, final long start, final long stop) {try (Jedis jedis = jedisPool.getResource ()) {return jedis.lrange (key, start, stop); } catch (Výnimka ex) {log.error ("Výnimka zachytená v lrange", ex); } vrátiť nový LinkedList (); }

Rovnakou stratégiou samozrejme môžeme postupovať aj pri vytvorení zvyšných obalových metód ako napr lpush, hmset, hgetall, smutný, pamätá, kľúče, zadda zrange.

4.3. Analýza

Všetky príkazy Redis, na ktoré môžeme použiť preskúmať kolekciu na jeden záťah bude mať v lepšom prípade prirodzene O (n) časovú zložitosť.

Sme možno trochu liberálni a tento prístup označujeme za naivný. V skutočnej produkčnej inštancii Redisu je úplne bežné mať v jednej zbierke tisíce alebo milióny kľúčov. Ďalej Redisova povaha s jedným vláknom prináša viac utrpenia a náš prístup by mohol katastroficky zablokovať ďalšie operácie s vyššou prioritou.

Mali by sme teda uviesť, že obmedzujeme náš naivný prístup, aby sa používal iba na účely ladenia.

5. Základy iterátora

Hlavnou chybou v našej naivnej implementácii je to, že požadujeme, aby nám spoločnosť Redis poskytla všetky výsledky nášho jediného načítavacieho dotazu naraz. Aby sme tento problém prekonali, môžeme náš pôvodný dopyt na načítanie rozdeliť do viacerých dotazov na postupné načítanie, ktoré fungujú na menších častiach celého súboru údajov.

Predpokladajme, že máme 1 000-stranovú knihu, ktorú si máme prečítať. Ak budeme postupovať podľa nášho naivného prístupu, budeme musieť túto veľkú knihu prečítať na jedno posedenie bez akýchkoľvek prestávok. To bude pre naše blaho osudné, pretože to odčerpá našu energiu a zabráni nám v akejkoľvek inej činnosti s vyššou prioritou.

Správnou cestou je samozrejme dokončenie knihy v priebehu niekoľkých čítaní. V každej relácii pokračujeme od miesta, kde sme skončili v predchádzajúcej relácii - môžeme sledovať náš pokrok pomocou záložky stránky.

Aj keď bude mať celková doba čítania v obidvoch prípadoch porovnateľnú hodnotu, druhý prístup je lepší, pretože nám dáva priestor na dýchanie.

Pozrime sa, ako môžeme na preskúmanie zbierok Redis použiť prístup založený na iterátoroch.

6. Znova skontrolujte skenovanie

Redis ponúka niekoľko stratégií skenovania na čítanie kľúčov zo zbierok pomocou prístupu založeného na kurzore, ktorý je v zásade podobný záložke stránky.

6.1. Stratégie skenovania

Cez celý obchod na zhromažďovanie kľúčov a hodnôt môžeme skenovať pomocou Skenovať príkaz. Ak však chceme náš súbor údajov obmedziť podľa typov zbierok, môžeme použiť jednu z variantov:

  • Sscan je možné použiť na iteráciu súprav
  • Hscan pomáha nám iterovať prostredníctvom párov hodnoty poľa v hashe
  • Zscan umožňuje iteráciu členmi uloženými v zoradenej množine

Musíme poznamenať, že my skutočne nepotrebujete stratégiu kontroly na strane servera špeciálne navrhnutú pre prepojené zoznamy. Je to preto, že k členom prepojeného zoznamu môžeme pristupovať prostredníctvom indexov pomocou znaku lindex alebo oranžová príkaz. Navyše môžeme zistiť počet prvkov a použitie oranžová v jednoduchej slučke na iteráciu celého zoznamu po malých častiach.

Použime SKENOVAŤ príkaz na skenovanie cez kľúče typu reťazca. Na začatie skenovania musíme použiť hodnotu kurzora ako „0“, zodpovedajúci reťazec vzoru ako „lopta *“:

127.0.0.1:6379> loptičky mset: kriket 160 loptičiek: futbal 450 loptičiek: volejbal 270 OK 127.0.0.1:6379> SKENOVAŤ 0 MATCH loptičiek * POČET 1 1) „2“ 2) 1) „loptičky: kriket“ 127.0.0.1 : 6379> SKENOVAŤ 2 ZÁPASOVÁ lopta * POČET 1 1) "3" 2) 1) "lopty: volejbal" 127.0.0.1:6379> SKENOVAŤ 3 ZÁPASNÁ lopta * POČET 1 1) "0" 2) 1) "lopty: futbal „

S každým dokončeným skenovaním získame ďalšiu hodnotu kurzora, ktorá sa má použiť v nasledujúcej iterácii. Nakoniec vieme, že sme prehľadali celú kolekciu, keď je ďalšia hodnota kurzora „0“.

7. Skenovanie pomocou Javy

Teraz už máme dostatok pochopenia pre náš prístup, aby sme ho mohli začať implementovať v Jave.

7.1. Stratégie skenovania

Ak nahliadneme do základnej funkcie skenovania, ktorú ponúka Jedis triedy nájdeme stratégie skenovania rôznych typov zbierok:

verejné skenovanie ScanResult (konečný kurzor reťazca, konečné parametre ScanParams); verejný ScanResult sscan (konečný kláves String, konečný kurzor reťazca, konečné parametre ScanParams); verejné ScanResult hscan (posledný reťazec, posledný reťazec, posledný parameter ScanParams); verejný ScanResult zscan (konečný kláves String, konečný kurzor reťazca, konečné parametre ScanParams);

Jedis vyžaduje dva voliteľné parametre, vzor vyhľadávania a veľkosť výsledku, aby bolo možné efektívne kontrolovať skenovanie - ScanParams to robí. Z tohto dôvodu sa opiera o: zápas() a count () metódy, ktoré voľne vychádzajú z návrhového vzoru staviteľa:

public ScanParams match (final String pattern); počet verejných ScanParams (konečný počet celých čísel);

Teraz, keď sme si nasiakli základné vedomosti o Jediovia skenovacieho prístupu, poďme tieto stratégie modelovať pomocou a ScanStrategy rozhranie:

verejné rozhranie ScanStrategy {ScanResult scan (Jedis jedis, String cursor, ScanParams scanParams); }

Najskôr pracujme na najjednoduchších skenovať stratégia, ktorá je nezávislá od typu kolekcie a číta kľúče, ale nie hodnotu kľúčov:

public class Scan implementuje ScanStrategy {public ScanResult scan (Jedis jedis, String kurzor, ScanParams scanParams) {return jedis.scan (kurzor, scanParams); }}

Ďalej poďme vyzdvihnúť hscan stratégia, ktorá je prispôsobená na čítanie všetkých kľúčov poľa a hodnôt poľa konkrétneho hash kľúča:

verejná trieda Hscan implementuje ScanStrategy {private String key; @ Override verejné ScanResult scan (Jedis jedis, String kurzor, ScanParams scanParams) {return jedis.hscan (klávesa, kurzor, scanParams); }}

Nakoniec si vytvorme stratégie pre množiny a triedené množiny. The sscan stratégia dokáže prečítať všetkých členov množiny, zatiaľ čo zscan Stratégia dokáže prečítať členov spolu s ich skóre vo forme Násobnýs:

verejná trieda Sscan implementuje ScanStrategy {private String key; public ScanResult scan (Jedis jedis, String cursor, ScanParams scanParams) {return jedis.sscan (key, cursor, scanParams); }} verejná trieda Zscan implementuje ScanStrategy {súkromný reťazcový kľúč; @Override public ScanResult scan (Jedis jedis, String cursor, ScanParams scanParams) {return jedis.zscan (key, cursor, scanParams); }}

7.2. Redis Iterator

Ďalej si načrtneme stavebné bloky potrebné na zostavenie našej RedisIterator trieda:

  • Kurzor na báze reťazcov
  • Stratégia skenovania ako napr skenovať, sscan, hscan, zscan
  • Zástupný symbol pre parametre skenovania
  • Prístup k JedisBool získať a Jedis zdroj

Teraz môžeme pokračovať a definovať týchto členov v našom RedisIterator trieda:

súkromné ​​finále JedisPool jedisPool; súkromné ​​ScanParams scanParams; súkromný kurzor reťazca; súkromná stratégia ScanStrategy;

Naša fáza je nastavená na definovanie funkcií špecifických pre iterátor pre náš iterátor. Za to naše RedisIterator trieda musí implementovať Iterátor rozhranie:

verejná trieda RedisIterator implementuje Iterator { }

Prirodzene, sme povinní prepísať hasNext () a Ďalšie() metódy zdedené z Iterátor rozhranie.

Najskôr si vyberieme nízko zavesené ovocie - hasNext () metóda - keďže podkladová logika je priama. Len čo sa hodnota kurzora zmení na „0“, vieme, že sme hotoví so skenovaním. Pozrime sa teda, ako to môžeme implementovať iba v jednom riadku:

@Override public boolean hasNext () {návrat! "0" .equals (kurzor); }

Ďalej poďme pracovať na Ďalšie() metóda, ktorá robí ťažké zdvíhanie skenovania:

@ Override public List next () {if (cursor == null) {cursor = "0"; } try (Jedis jedis = jedisPool.getResource ()) {ScanResult scanResult = strategy.scan (jedis, cursor, scanParams); cursor = scanResult.getCursor (); vrátiť scanResult.getResult (); } catch (Výnimka ex) {log.error ("Výnimka zachytená v next ()", ex); } vrátiť nový LinkedList (); }

To musíme poznamenať ScanResult poskytuje nielen naskenované výsledky, ale aj nasledujúcu hodnotu kurzora potrebné pre následné skenovanie.

Na záver môžeme tejto funkcii povoliť vytváranie našich RedisIterator v RedisClient trieda:

public RedisIterator iterator (int initialScanCount, String pattern, ScanStrategy strategy) {return new RedisIterator (jedisPool, initialScanCount, pattern, strategy); }

7.3. Čítať s Redis Iterator

Ako sme navrhli náš iterátor Redis pomocou Iterátor je to celkom intuitívne prečítajte si hodnoty zbierky pomocou Ďalšie() metóda pokiaľ hasNext () vracia pravda.

Kvôli úplnosti a jednoduchosti najskôr uložíme dataset súvisiaci so športovými loptičkami do hash Redis. Potom použijeme našu RedisClient vytvoriť iterátor pomocou Hscan stratégia skenovania. Vyskúšajme našu implementáciu tak, že to uvidíme v akcii:

@Test public void testHscanStrategy () {HashMap hash = nový HashMap (); hash.put ("kriket", "160"); hash.put ("futbal", "450"); hash.put ("volejbal", "270"); redisClient.hmset ("gule", hash); Hscan scanStrategy = nový Hscan („gule“); int iterationCount = 2; RedisIterator iterator = redisClient.iterator (iterationCount, "*", scanStrategy); Zoznam results = new LinkedList(); while (iterator.hasNext ()) {results.addAll (iterator.next ()); } Assert.assertEquals (hash.size (), results.size ()); }

Môžeme sledovať rovnaký myšlienkový proces s malými úpravami, aby sme otestovali a implementovali zostávajúce stratégie skenovania a čítania kľúčov dostupných v rôznych druhoch zbierok.

8. Záver

Tento tutoriál sme začali s úmyslom dozvedieť sa, ako môžeme prečítať všetky zodpovedajúce kľúče v Redis.

Zistili sme, že Redis ponúka jednoduchý spôsob čítania kľúčov jedným ťahom. Aj keď je to jednoduché, diskutovali sme o tom, ako to zaťažuje zdroje, a preto to nie je vhodné pre produkčné systémy. Pri hlbšom kopaní sme prišli na to, že existuje iterátorský prístup k skenovaniu prostredníctvom zodpovedajúcich kľúčov Redis pre náš dopyt na čítanie.

Úplný zdrojový kód implementácie Java použitý v tomto článku je ako vždy k dispozícii na serveri GitHub.

Java dole

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

$config[zx-auto] not found$config[zx-overlay] not found