Introduktion til Jedis - Java Redis Client Library

1. Oversigt

Denne artikel er en introduktion til Jedis, et klientbibliotek i Java til Redis - det populære datastrukturlager i hukommelsen, der også kan fortsætte på disken. Det drives af en keystore-baseret datastruktur til at vedvare data og kan bruges som en database, cache, meddelelsesmægler osv.

For det første skal vi forklare, i hvilken slags situationer Jedis er nyttig, og hvad det handler om.

I de efterfølgende afsnit uddyber vi de forskellige datastrukturer og forklarer transaktioner, pipelining og publicerings- / abonnementsfunktionen. Vi afslutter med forbindelsespooling og Redis Cluster.

2. Hvorfor Jedis?

Redis viser de mest kendte klientbiblioteker på deres officielle side. Der er flere alternativer til Jedis, men kun to mere er i øjeblikket værd at anbefale deres stjerne, salat og Redisson.

Disse to klienter har nogle unikke funktioner som trådsikkerhed, gennemsigtig håndtering af genforbindelse og en asynkron API, som alle Jedis mangler.

Det er dog lille og betydeligt hurtigere end de to andre. Desuden er det klientbiblioteket, som Spring Framework-udviklerne vælger, og det har det største samfund af alle tre.

3. Maven-afhængigheder

Lad os starte med at erklære den eneste afhængighed, vi har brug for i pom.xml:

 redis.clients jedis 2.8.1 

Hvis du leder efter den nyeste version af biblioteket, skal du tjekke denne side.

4. Redis-installation

Du bliver nødt til at installere og fyre en af ​​de nyeste versioner af Redis op. Vi kører den seneste stabile version i øjeblikket (3.2.1), men enhver post 3.x-version skal være okay.

Find her flere oplysninger om Redis til Linux og Macintosh, de har meget ens grundlæggende installationstrin. Windows understøttes ikke officielt, men denne port er velholdt.

Derefter kan vi direkte dykke ind og oprette forbindelse til det fra vores Java-kode:

Jedis jedis = nye Jedis ();

Standardkonstruktøren fungerer fint, medmindre du har startet tjenesten på en ikke-standardport eller en fjernmaskine, i hvilket tilfælde du kan konfigurere den korrekt ved at videregive de korrekte værdier som parametre til konstruktøren.

5. Redis datastrukturer

De fleste af de oprindelige operationskommandoer understøttes, og praktisk nok deler de normalt det samme metodenavn.

5.1. Strenge

Strenge er den mest grundlæggende slags Redis-værdi, der er nyttig, når du har brug for at opretholde enkle nøgleværdidatatyper:

jedis.set ("begivenheder / by / rom", "32,15,223,828"); Streng cachedResponse = jedis.get ("begivenheder / by / rom");

Variablen cachedResponse holder værdien 32,15,223,828. Kombineret med udløbsstøtte, der diskuteres senere, kan det fungere som et lynhurtigt og enkelt at bruge cachelag til HTTP-anmodninger, der modtages i din webapplikation og andre krav til cache.

5.2. Lister

Redis-lister er simpelthen lister over strenge sorteret efter indsættelsesrækkefølge og gør det til et ideelt værktøj til at implementere for eksempel meddelelseskøer:

jedis.lpush ("kø # opgaver", "første opgave"); jedis.lpush ("kø # opgaver", "secondTask"); Strengopgave = jedis.rpop ("kø # opgaver");

Variablen opgave holder værdien første opgave. Husk at du kan serieisere ethvert objekt og vedligeholde det som en streng, så meddelelser i køen kan medføre mere komplekse data, når det er nødvendigt.

5.3. Sæt

Redis-sæt er en uordnet samling af strenge, der er nyttige, når du vil ekskludere gentagne medlemmer:

jedis.sadd ("kaldenavne", "kaldenavn nr. 1"); jedis.sadd ("kaldenavne", "kaldenavn # 2"); jedis.sadd ("kaldenavne", "kaldenavn nr. 1"); Indstil kaldenavne = jedis.smembers ("kaldenavne"); boolsk eksisterer = jedis.sismember ("kaldenavne", "kaldenavn nr. 1");

Java-sættet kaldenavne har en størrelse på 2, den anden tilføjelse af kaldenavn # 1 blev ignoreret. Også den eksisterer variabel har en værdi på rigtigt, metoden sismember giver dig mulighed for hurtigt at kontrollere, om der findes et bestemt medlem.

5.4. Hashes

Redis Hashes kortlægger mellem Snor felter og Snor værdier:

jedis.hset ("bruger nr. 1", "navn", "Peter"); jedis.hset ("bruger nr. 1", "job", "politiker"); Strengnavn = jedis.hget ("bruger nr. 1", "navn"); Kortfelter = jedis.hgetAll ("bruger nr. 1"); String job = fields.get ("job");

Som du kan se, er hashes en meget bekvem datatype, når du vil have adgang til objektets egenskaber individuelt, da du ikke behøver at hente hele objektet.

5.5. Sorterede sæt

Sorterede sæt er som et sæt, hvor hvert medlem har en tilknyttet placering, der bruges til at sortere dem:

Kortresultater = nyt HashMap (); scores.put ("PlayerOne", 3000.0); scores.put ("PlayerTwo", 1500.0); scores.put ("PlayerThree", 8200.0); scores.entrySet (). forEach (playerScore -> {jedis.zadd (key, playerScore.getValue (), playerScore.getKey ());}); String player = jedis.zrevrange ("ranking", 0, 1) .iterator (). Næste (); lang rang = jedis.zrevrank ("ranking", "PlayerOne");

Variablen spiller holder værdien PlayerTree fordi vi henter top 1-spilleren, og han er den med den højeste score. Det rang variabel har en værdi på 1, fordi PlayerOne er den anden i placeringen, og placeringen er nul-baseret.

6. Transaktioner

Transaktioner garanterer atomicitet og trådsikkerhedsoperationer, hvilket betyder, at anmodninger fra andre klienter aldrig vil blive håndteret samtidigt under Redis-transaktioner:

String friendsPrefix = "venner #"; String userOneId = "4352523"; String userTwoId = "5552321"; Transaktion t = jedis.multi (); t.sadd (friendsPrefix + userOneId, userTwoId); t.sadd (friendsPrefix + userTwoId, userOneId); f.eksec ();

Du kan endda gøre en transaktionssucces afhængig af en bestemt nøgle ved at "se" den lige før du starter din Transaktion:

jedis.watch ("venner # slettet #" + userOneId);

Hvis værdien af ​​denne nøgle ændres, før transaktionen udføres, afsluttes transaktionen ikke med succes.

7. Rørledning

Når vi skal sende flere kommandoer, kan vi pakke dem sammen i en anmodning og gemme forbindelsesomkostninger ved hjælp af rørledninger, det er i det væsentlige en netværksoptimering. Så længe operationerne er gensidigt uafhængige, kan vi drage fordel af denne teknik:

String userOneId = "4352523"; String userTwoId = "4849888"; Rørledning p = jedis.pipelined (); p.sadd ("søgte #" + userOneId, "paris"); p.zadd ("ranking", 126, userOneId); p.zadd ("ranking", 325, userTwoId); Svar pipeExists = p.sismember ("søgte #" + userOneId, "paris"); Respons pipeRanking = p.zrange ("ranking", 0, -1); p.sync (); Streng eksisterer = pipeExists.get (); Indstil ranking = pipeRanking.get ();

Bemærk, at vi ikke får direkte adgang til kommandosvarene, i stedet får vi en Respons forekomst, hvorfra vi kan anmode om det underliggende svar, efter at pipelinen er synkroniseret.

8. Udgiv / abonner

Vi kan bruge funktionaliteten Redis messaging-mægler til at sende meddelelser mellem de forskellige komponenter i vores system. Sørg for, at abonnent- og udgivertråde ikke deler den samme Jedis-forbindelse.

8.1. Abonnent

Abonner og lyt til beskeder sendt til en kanal:

Jedis jSubscriber = nye Jedis (); jSubscriber.subscribe (ny JedisPubSub () {@Override public void onMessage (String channel, String message) {// handle message}}, "channel");

Abonner er en blokeringsmetode, du skal afmelde dig JedisPubSub eksplicit. Vi har tilsidesat onMessage metode, men der er mange flere nyttige metoder til at tilsidesætte.

8.2. Forlægger

Send derefter bare beskeder til den samme kanal fra forlagets tråd:

Jedis jPublisher = nye Jedis (); jPublisher.publish ("kanal", "testmeddelelse");

9. Forbindelse pooling

Det er vigtigt at vide, at den måde, vi har behandlet vores Jedis-instans på, er naiv. I et virkeligt scenarie vil du ikke bruge en enkelt forekomst i et miljø med flere tråde, da en enkelt forekomst ikke er trådsikker.

Heldigvis kan vi nemt oprette en pool af forbindelser til Redis, så vi kan genbruge efter behov, en pool, der er trådsikker og pålidelig, så længe du returnerer ressourcen til puljen, når du er færdig med den.

Lad os oprette JedisPool:

endelige JedisPoolConfig poolConfig = buildPoolConfig (); JedisPool jedisPool = ny JedisPool (poolConfig, "localhost"); privat JedisPoolConfig buildPoolConfig () {final JedisPoolConfig poolConfig = new JedisPoolConfig (); poolConfig.setMaxTotal (128); poolConfig.setMaxIdle (128); poolConfig.setMinIdle (16); poolConfig.setTestOnBorrow (sand); poolConfig.setTestOnReturn (sand); poolConfig.setTestWhileIdle (sand); poolConfig.setMinEvictableIdleTimeMillis (Duration.ofSeconds (60) .toMillis ()); poolConfig.setTimeBetweenEvictionRunsMillis (Duration.ofSeconds (30) .toMillis ()); poolConfig.setNumTestsPerEvictionRun (3); poolConfig.setBlockWhenExhausted (true); retur poolConfig; }

Da poolinstansen er trådsikker, kan du gemme den et eller andet sted statisk, men du skal sørge for at ødelægge poolen for at undgå lækager, når applikationen lukkes ned.

Nu kan vi bruge vores pool fra hvor som helst i applikationen, når det er nødvendigt:

prøv (Jedis jedis = jedisPool.getResource ()) {// udfør operationer med jedis resource}

Vi brugte Java-prøve-med-ressourcer-erklæringen for at undgå at skulle lukke Jedis-ressourcen manuelt, men hvis du ikke kan bruge denne erklæring, kan du også lukke ressourcen manuelt i langt om længe klausul.

Sørg for at bruge en pool, som vi har beskrevet i din ansøgning, hvis du ikke vil have ubehagelige multi-threading-problemer. Du kan naturligvis spille med poolkonfigurationsparametrene for at tilpasse den til det bedste setup i dit system.

10. Redis-klynge

Denne Redis-implementering giver let skalerbarhed og høj tilgængelighed, vi opfordrer dig til at læse deres officielle specifikation, hvis du ikke er fortrolig med den. Vi dækker ikke Redis-klyngeopsætning, da det er lidt uden for denne artikels anvendelsesområde, men du skal ikke have nogen problemer med at gøre det, når du er færdig med dokumentationen.

Når vi har det klar, kan vi begynde at bruge det fra vores applikation:

prøv (JedisCluster jedisCluster = ny JedisCluster (ny HostAndPort ("localhost", 6379))) {// brug jedisCluster-ressourcen som om det var en normal Jedis-ressource} fangst (IOException e) {}

Vi behøver kun at angive værts- og portoplysningerne fra en af ​​vores masterforekomster, det vil automatisk opdage resten af ​​forekomsterne i klyngen.

Dette er bestemt en meget kraftig funktion, men det er ikke en sølvkugle. Når du bruger Redis Cluster, kan du ikke udføre transaktioner eller bruge rørledninger, to vigtige funktioner, som mange applikationer er afhængige af for at sikre dataintegritet.

Transaktioner er deaktiveret, fordi nøglerne i et klynget miljø forbliver på tværs af flere forekomster. Driftens atomicitet og trådsikkerhed kan ikke garanteres for operationer, der involverer kommandokørsel i forskellige tilfælde.

Nogle avancerede strategier til oprettelse af nøgler vil sikre, at data, der er interessante for dig at blive vedvarende i samme tilfælde, bliver vedvarende på den måde. I teorien skulle det gøre det muligt for dig at udføre transaktioner med succes ved hjælp af en af ​​de underliggende Jedis-forekomster af Redis-klyngen.

Desværre kan du i øjeblikket ikke finde ud af, i hvilken Redis-forekomst en bestemt nøgle gemmes ved hjælp af Jedis (som faktisk understøttes af Redis), så du ved ikke, hvilke af de tilfælde du skal udføre transaktionshandling. Hvis du er interesseret i dette, kan du finde mere information her.

11. Konklusion

Langt størstedelen af ​​funktionerne fra Redis er allerede tilgængelige i Jedis, og dens udvikling bevæger sig fremad i et godt tempo.

Det giver dig mulighed for at integrere en kraftfuld lagermotor i hukommelsen i din applikation med meget lidt besvær, bare glem ikke at oprette forbindelsespooling for at undgå trådsikkerhedsproblemer.

Du kan finde kodeeksempler i GitHub-projektet.


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