Bevezetés a salátába - a Java Redis kliensbe

1. Áttekintés

Ez a cikk a Redis Java kliens, a Lettuce bemutatása.

A Redis egy memóriában lévő kulcsérték-tároló, amely adatbázisként, gyorsítótárként vagy üzenetközvetítőként használható. Az adatok hozzáadása, lekérdezése, módosítása és törlése olyan parancsokkal történik, amelyek a Redis memóriában lévő adatstruktúrájának kulcsain működnek.

A saláta támogatja a teljes Redis API szinkron és aszinkron kommunikációs használatát, beleértve az adatstruktúrákat, a pub / sub üzenetküldést és a magas rendelkezésre állású szerver kapcsolatokat.

2. Miért saláta?

Az előző bejegyzések egyikében ismertettük Jedist. Miben különbözik a saláta?

A legjelentősebb különbség az aszinkron támogatás a Java 8-asokon keresztül CompletionStage interfész és a reaktív folyamok támogatása. Amint alább láthatjuk, a Lettuce természetes felületet kínál aszinkron kérelmek küldéséhez a Redis adatbázis-kiszolgálótól és adatfolyamok létrehozásához.

A Netty-t is használja a szerverrel való kommunikációhoz. Ez egy „nehezebb” API-t eredményez, de egyben több szálon is megoszthatja a kapcsolatot.

3. Beállítás

3.1. Függőség

Kezdjük azzal, hogy deklaráljuk az egyetlen függőséget, amelyre szükségünk lesz pom.xml:

 io.saláta saláta-mag 5.0.1.FELHASZNÁLÁS 

A könyvtár legújabb verziója a Github adattárban vagy a Maven Centralon ellenőrizhető.

3.2. Redis telepítés

Legalább egy Redis-példányt telepítenünk és futtatnunk kell, kettőt, ha fürtözés vagy őrszem módot akarunk tesztelni (bár az őrszem mód három kiszolgálót igényel a megfelelő működéshez.) A cikkhez a 4.0.x-et használjuk - a legújabb stabil verziója ebben a pillanatban.

További információ a Redis használatának kezdetéről itt található, beleértve a Linux és MacOS letöltéseket.

Redis hivatalosan nem támogatja a Windows rendszert, de van itt egy szerver port. A Redist a Dockerben is futtathatjuk, amely jobb alternatíva a Windows 10 számára, és gyors módja a fel- és működésnek.

4. Csatlakozások

4.1. Csatlakozás szerverhez

A Redis-hez való csatlakozás négy lépésből áll:

  1. Redis URI létrehozása
  2. Az URI használatával csatlakozhat a RedisClient
  3. Redis kapcsolat megnyitása
  4. Készlet generálása RedisCommands

Lássuk a megvalósítást:

RedisClient redisClient = RedisClient .create ("redis: // [e-mail védett]: 6379 /"); StatefulRedisConnection kapcsolat = redisClient.connect ();

A StatefulRedisConnection hogy hangzik; szálbiztos kapcsolat a Redis kiszolgálóval, amely fenntartja a kapcsolatot a szerverrel, és szükség esetén újracsatlakozik. Ha van kapcsolatunk, használhatjuk a Redis parancsok szinkron vagy aszinkron végrehajtására.

RedisClient jelentős rendszererőforrásokat használ, mivel a Netty erőforrásokkal rendelkezik a Redis szerverrel való kommunikációhoz. A több kapcsolatot igénylő alkalmazásoknak egyetlenet kell használniuk RedisClient.

4.2. Redis URI-k

Létrehozunk egy RedisClient URI továbbításával a statikus gyári módszerhez.

A saláta egyéni szintaxist használ a Redis URI-khoz. Ez a séma:

redis: // [[e-mail védett]] gazdagép [: port] [/ adatbázis] [? [időkorlát = időtúllépés [d | h | m | s | ms | us | ns]] [& _adatbázis = adatbázis_]] 

Négy URI séma létezik:

  • redis - önálló Redis szerver
  • rediss - önálló Redis szerver SSL kapcsolaton keresztül
  • redis-foglalat - önálló Redis szerver a Unix tartományi foglalaton keresztül
  • redis-sentinel - egy Redis Sentinel szerver

A Redis adatbázis-példány megadható az URL elérési útjának részeként vagy további paraméterként. Ha mindkettő meg van adva, akkor a paraméternek nagyobb az elsőbbsége.

A fenti példában az a-t használjuk Húr reprezentáció. A salátának van még egy RedisURI osztály a kapcsolatok kiépítésére. Felajánlja a Építész minta:

RedisURI.Builder .redis ("localhost", 6379) .auth ("jelszó") .adatbázis (1) .build (); 

És egy kivitelező:

új RedisURI ("localhost", 6379, 60, TimeUnit.SECONDS); 

4.3. Szinkron parancsok

A Jedishez hasonlóan a Saláta egy komplett Redis parancskészletet biztosít metódusok formájában.

A Saláta azonban szinkron és aszinkron verziókat is megvalósít. Röviden áttekintjük a szinkron verziót, majd az oktatóanyag további részében az aszinkron megvalósítást használjuk.

Miután létrehoztunk egy kapcsolatot, azt használjuk egy parancskészlet létrehozására:

RedisCommands syncCommands = connection.sync (); 

Most van egy intuitív kezelőfelületünk a Redissel való kommunikációhoz.

Beállíthatjuk és megszerezhetjük Karakterlánc értékek:

syncCommands.set ("key", "Hello, Redis!"); Karaktersorozat = syncommands.get („kulcs”); 

Dolgozhatunk hashokkal:

syncCommands.hset ("rekordNév", "Keresztnév", "John"); syncCommands.hset ("rekordnév", "vezetéknév", "Smith"); Térképrekord = syncCommands.hgetall ("recordName"); 

A Redis-ről később a cikkben lesz szó.

A Lettuce szinkron API az aszinkron API-t használja. A blokkolás parancsnoki szinten történik helyettünk. Ez azt jelenti, hogy több kliens is megoszthatja a szinkron kapcsolatot.

4.4. Aszinkron parancsok

Vessünk egy pillantást az aszinkron parancsokra:

RedisAsyncCommands asyncCommands = connection.async (); 

Meghaladunk egy készletet RedisAsyncCommands a kapcsolattól, hasonlóan a szinkronkészlet lekéréséhez. Ezek a parancsok a RedisFuture (ami a CompletableFuture belsőleg):

RedisFuture eredmény = asyncCommands.get ("kulcs"); 

Útmutató a CompletableFuture itt található.

4.5. Reaktív API

Végül nézzük meg, hogyan kell működni a nem blokkoló reaktív API-val:

RedisStringReactiveCommands reactiveCommands = connection.reactive (); 

Ezek a parancsok a-ba csomagolva adják vissza az eredményeket Monó vagy a Fényáram a Project Reactortól.

Útmutató a Project Reactor használatához itt található.

5. Redis adatstruktúrák

Röviden megvizsgáltuk a fenti karakterláncokat és kivonatokat, nézzük meg, hogyan valósítja meg Lettuce a Redis többi adatstruktúráját. Ahogy arra számítottunk, minden Redis parancsnak hasonló elnevezésű módszere van.

5.1. Listák

A listák a Húrok a beszúrási sorrend megőrzésével. Az értékeket beillesztik vagy beolvassák mindkét végből:

asyncCommands.lpush ("feladatok", "firstTask"); asyncCommands.lpush ("feladatok", "secondTask"); RedisFuture redisFuture = asyncCommands.rpop ("feladatok"); String nextTask = redisFuture.get (); 

Ebben a példában nextTask egyenlőfirstTask“. Lpush értékeket tol a lista elejére, majd rpop felbukkan az érték a lista végén.

A másik oldalról is popelhetünk elemeket:

asyncCommands.del ("feladatok"); asyncCommands.lpush ("feladatok", "firstTask"); asyncCommands.lpush ("feladatok", "secondTask"); redisFuture = asyncCommands.lpop ("feladatok"); String nextTask = redisFuture.get (); 

A második példát a lista törlésével kezdjük del. Ezután ismét beillesztjük ugyanazokat az értékeket, de használjuk lpop hogy az értékeket a lista elejéről kiugorja, így a nextTask tart „secondTask”Szöveget.

5.2. Készletek

A Redis szettek rendezetlen gyűjteményei Húrok hasonló a Java-hoz Készletek; nincsenek ismétlődő elemek:

asyncCommands.sadd ("háziállatok", "kutya"); asyncCommands.sadd ("háziállatok", "macska"); asyncCommands.sadd ("háziállatok", "macska"); RedisFuture háziállatok = asyncCommands.smembers ("becenevek"); RedisFuture pastāv = asyncCommands.sismember ("háziállatok", "kutya"); 

Amikor lekérjük a Redis készletet a-ként Készlet, a méret kettő, mivel a másolat "macska" figyelmen kívül hagyták. Amikor Redis-t kérdezzük a "kutya" val vel sismember, a válasz az igaz.

5.3. Hashes

Röviden megvizsgáltunk egy példát a hashokra korábban. Gyors magyarázatot érdemelnek.

A Redis Hashes rekordok Húr mezők és értékek. Minden rekordnak van egy kulcsa az elsődleges indexben is:

asyncCommands.hset ("rekordNév", "Keresztnév", "John"); asyncCommands.hset ("rekordnév", "vezetéknév", "Smith"); RedisFuture lastName = syncCommands.hget ("rekordnév", "vezetéknév"); RedisFuture rekord = syncCommands.hgetall ("rekordNév"); 

Használunk hset mezők hozzáadása a kivonathoz, a hash nevének, a mező nevének és egy értékének megadása.

Ezután beolvasunk egy egyéni értéket a hget, a rekord és a mező neve. Végül a teljes lemezt kivonatoljuk hash-ként hgetall.

5.4. Válogatott készletek

A rendezett halmazok értékeket és rangot tartalmaz, amelyek szerint rendezésre kerülnek. A rang 64 bites lebegőpontos érték.

Az elemeket rangsor szerint adják hozzá, és egy tartományban kapják meg:

asyncCommands.zadd ("rendezett készlet", 1, "egy"); asyncCommands.zadd ("rendezett készlet", 4, "nulla"); asyncCommands.zadd ("rendezett készlet", 2, "kettő"); RedisFuture valuesForward = asyncCommands.zrange (kulcs, 0, 3); RedisFuture valuesReverse = asyncCommands.zrevrange (kulcs, 0, 3); 

A második érv a zadd rang. Egy tartományt beolvasunk rang szerint a zrange a növekvő sorrendért és zrevrange leereszkedésért.

Hozzáadtuknulla”4-es ranggal, így a végén jelenik meg értékek Előre elején pedig valuesReverse.

6. Tranzakciók

A tranzakciók lehetővé teszik egy parancssor végrehajtását egyetlen atomi lépésben. Ezeket a parancsokat garantáltan sorrendben és kizárólagosan hajtják végre. Egy másik felhasználó parancsai addig nem hajtódnak végre, amíg a tranzakció befejeződik.

Vagy az összes parancs végrehajtásra kerül, vagy egyik sem. A Redis nem hajt végre visszagörgetést, ha egyikük meghibásodik. Egyszer exec () meghívásra kerül, az összes parancs a megadott sorrendben kerül végrehajtásra.

Nézzünk meg egy példát:

asyncCommands.multi (); RedisFuture result1 = asyncCommands.set ("kulcs1", "érték1"); RedisFuture result2 = asyncCommands.set ("kulcs2", "érték2"); RedisFuture result3 = asyncCommands.set ("kulcs3", "érték3"); RedisFuture execResult = asyncCommands.exec (); TransactionResultactionResult = execResult.get (); String firstResult =actionResult.get (0); String secondResult =actionResult.get (0); String thirdResult = tranzakcióRezult.get (0); 

A hívás több megkezdi a tranzakciót. A tranzakció indításakor a következő parancsokat csak addig hajtják végre exec () nak, nek hívják.

Szinkron módban a parancsok visszatérnek nulla. Aszinkron módban a parancsok visszatérnek RedisFuture . Exec visszatér a TransactionResult amely a válaszok listáját tartalmazza.

Mivel a RedisFutures szintén megkapják az eredményeiket, az aszinkron API kliensek két helyen kapják meg a tranzakció eredményét.

7. Kötegelés

Normál körülmények között a saláta végrehajtja a parancsokat, amint egy API-ügyfél meghívja őket.

Ezt akarja a legtöbb normális alkalmazás, különösen, ha a parancsok eredményeinek soros fogadására támaszkodnak.

Ez a viselkedés azonban nem hatékony, ha az alkalmazásoknak nincs szükségük azonnal eredményre, vagy ha nagy mennyiségű adatot töltenek fel tömegesen.

Az aszinkron alkalmazások felülírhatják ezt a viselkedést:

commands.setAutoFlushCommands (hamis); Lista határidős = new ArrayList (); for (int i = 0; i <iterációk; i ++) {futures.add (commands.set ("key-" + i, "value-" + i);} commands.flushCommands (); logikai eredmény = LettuceFutures.awaitAll (5, TimeUnit.SECONDS, futures.toArray (új RedisFuture [0])); 

A setAutoFlushCommands értékre van állítva hamis, az alkalmazásnak hívnia kell flushCommands manuálisan. Ebben a példában többször álltunk sorba készlet parancsot, majd öblítette a csatornát. Várj mind várja az összes RedisFutures teljesíteni.

Ez az állapot kapcsolatonként van beállítva, és hatással van az összes szálra, amely használja a kapcsolatot. Ez a szolgáltatás nem alkalmazható a szinkron parancsokra.

8. Közzététel / Feliratkozás

A Redis egy egyszerű közzétételi / feliratkozási üzenetkezelő rendszert kínál. Az előfizetők a csatornával érkező üzeneteket fogyasztják a Iratkozz fel parancs. Az üzenetek nem maradnak fenn; csak akkor jutnak el a felhasználókhoz, ha feliratkoztak egy csatornára.

A Redis a kocsma / alrendszert használja a Redis adatkészlettel kapcsolatos értesítésekhez, így az ügyfelek képesek lesznek eseményeket fogadni a kulcsok beállításáról, törléséről, lejáratáról stb.

További részletekért lásd az itt található dokumentációt.

8.1. Előfizető

A RedisPubSubListener pub / sub üzeneteket fogad. Ez a felület számos módszert határoz meg, de itt csak az üzenetek fogadásának módszerét mutatjuk be:

public class Listener végrehajtja a RedisPubSubListener {@Orride public void message (String channel, String message) {log.debug ("Got {} on channel {}", message, channel); üzenet = új karakterlánc (s2); }} 

Használjuk a RedisClient kocsma / alcsatorna csatlakoztatásához és a hallgató telepítéséhez:

StatefulRedisPubSubConnection kapcsolat = client.connectPubSub (); connection.addListener (új Listener ()) RedisPubSubAsyncCommands async = connection.async (); async.subscribe ("csatorna"); 

Telepített hallgatóval lekérünk egy sor készletet RedisPubSubAsyncCommands és iratkozzon fel egy csatornára.

8.2. Kiadó

A közzététel csupán a Pub / Sub csatorna összekapcsolásának és a parancsok lekérésének kérdése:

StatefulRedisPubSubConnection kapcsolat = client.connectPubSub (); RedisPubSubAsyncCommands async = connection.async (); async.publish ("channel", "Hello, Redis!"); 

A közzétételhez csatorna és üzenet szükséges.

8.3. Reaktív előfizetések

A saláta egy reaktív felületet is kínál a pub / sub üzenetek feliratkozására:

StatefulRedisPubSubConnection kapcsolat = kliens .connectPubSub (); RedisPubSubAsyncCommands reaktív = kapcsolat .reaktív (); reaktív.observeChannels (). feliratkozás (üzenet -> {log.debug ("Van {} a csatornán {}", üzenet, csatorna); üzenet = új karakterlánc (s2);}); reaktív.feliratkozás ("csatorna"). feliratkozás (); 

A Fényáram által visszatért observChannels üzeneteket fogad minden csatornára, de mivel ez egy adatfolyam, a szűrés könnyen elvégezhető.

9. Magas rendelkezésre állás

A Redis számos lehetőséget kínál a magas rendelkezésre állás és méretezhetőség érdekében. A teljes megértéshez szükség van a Redis szerver konfigurációinak ismeretére, de áttekintünk egy rövid áttekintést arról, hogy a Saláta hogyan támogatja azokat.

9.1. Mesterszolga

A Redis szerverek master / slave konfigurációban replikálják magukat. A fő szerver a szolga számára egy olyan parancsfolyamot küld, amely megismétli a master gyorsítótárat. A Redis nem támogatja a kétirányú replikációt, ezért a rabszolgák csak olvashatók.

A saláta csatlakozhat a Master / Slave rendszerekhez, lekérdezheti tőlük a topológiát, majd kijelölheti a rabszolgákat az olvasási műveletekhez, ami javíthatja az átvitelt:

RedisClient redisClient = RedisClient.create (); StatefulRedisMasterSlaveConnection kapcsolat = MasterSlave.connect (redisClient, új Utf8StringCodec (), RedisURI.create ("redis: // localhost")); connection.setReadFrom (ReadFrom.SLAVE); 

9.2. Őrszem

A Redis Sentinel figyeli a master és a slave példányokat, és a master feladatátvétel esetén a rabszolgák feladatátvételét hangszereli.

A saláta csatlakozhat a Sentinelhez, felhasználhatja az aktuális mester címének felfedezésére, majd visszaállíthatja a kapcsolatot.

Ehhez mást építünk RedisURI és csatlakoztassa a mi RedisClient ezzel:

RedisURI redisUri = RedisURI.Builder .sentinel ("sentinelhost1", "clustername") .withSentinel ("sentinelhost2"). Build (); RedisClient kliens = új RedisClient (redisUri); RedisConnection kapcsolat = client.connect (); 

Felépítettük az URI-t az első Sentinel hosztnevével (vagy címével) és egy fürtnévvel, majd egy második őrszem címmel. Amikor csatlakozunk a Sentinelhez, Lettuce lekérdezi a topológiáról, és visszakapcsol minket az aktuális master szerverhez.

A teljes dokumentáció itt érhető el.

9.3. Klaszterek

A Redis Cluster elosztott konfigurációt használ a magas rendelkezésre állás és a nagy áteresztőképesség biztosítása érdekében.

A fürtök legfeljebb 1000 csomóponton osztják fel a kulcsokat, ezért a tranzakciók nem érhetők el egy fürtben:

RedisURI redisUri = RedisURI.Builder.redis ("localhost") .withPassword ("hitelesítés"). Build (); RedisClusterClient clusterClient = RedisClusterClient .create (rediUri); StatefulRedisClusterConnection kapcsolat = clusterClient.connect (); RedisAdvancedClusterCommands syncCommands = kapcsolat .sync (); 

RedisAdvancedClusterCommands birtokolja a fürt által támogatott Redis parancsok halmazát, átirányítva őket a kulcsot tartó példányhoz.

A teljes specifikáció itt érhető el.

10. Következtetés

Ebben az oktatóanyagban megvizsgáltuk, hogyan lehet a Lettuce segítségével csatlakozni és lekérdezni egy Redis szervert az alkalmazásunkon belül.

A saláta támogatja a Redis funkciók teljes készletét, egy teljesen szálbiztos aszinkron felület bónuszával. Széles körben használja a Java 8-okat is CompletionStage interfész, amely lehetővé teszi az alkalmazások számára az adatok fogadásának részletes ellenőrzését.

A kódminták, mint mindig, a GitHubon találhatók.