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:
- Redis URI létrehozása
- Az URI használatával csatlakozhat a RedisClient
- Redis kapcsolat megnyitása
- 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
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.