Uvod u Jedije - biblioteku klijenata Java Redis

1. Pregled

Ovaj je članak uvod u Jedije, klijentska knjižnica u Javi za Redis - popularno spremište podataka u memoriji koje može postojati i na disku. Pokreće ga struktura podataka koja se temelji na pohrani ključeva kako bi se i dalje održavali podaci i može se koristiti kao baza podataka, predmemorija, posrednik poruka itd.

Prvo ćemo objasniti u kojim su situacijama Jediji korisni i o čemu se radi.

U sljedećim odjeljcima razrađujemo različite strukture podataka i objašnjavamo transakcije, cjevovod i značajku objavljivanja / pretplate. Zaključujemo spajanjem veza i Redis klasterom.

2. Zašto Jediji?

Redis na svojim službenim stranicama navodi najpoznatije knjižnice klijenata. Postoji više mogućnosti za Jedije, ali samo su još dvije trenutno vrijedne zvijezde preporuke, salate i Redissona.

Ova dva klijenta imaju neke jedinstvene značajke kao što su sigurnost niti, transparentno rukovanje ponovnim povezivanjem i asinkroni API, a sve to Jedima nedostaje.

Međutim, mali je i znatno brži od druga dva. Osim toga, to je klijentska biblioteka koju su odabrali programeri Spring Framework i ima najveću zajednicu od sve tri.

3. Ovisnosti Mavena

Počnimo s proglašenjem jedine ovisnosti koja će nam trebati u pom.xml:

 redis.klijenti jedis 2.8.1 

Ako tražite najnoviju verziju knjižnice, pogledajte ovu stranicu.

4. Instalacija Redisa

Morat ćete instalirati i pokrenuti jednu od najnovijih verzija Redisa. Trenutno imamo najnoviju stabilnu verziju (3.2.1), ali bilo koja verzija 3.x trebala bi biti u redu.

Ovdje možete pronaći više informacija o Redisu za Linux i Macintosh, oni imaju vrlo slične osnovne korake instalacije. Windows službeno nije podržan, ali ovaj je priključak dobro održavan.

Nakon toga možemo izravno zaroniti i povezati se s njim iz našeg Java koda:

Jedi jedis = novi Jedi ();

Zadani konstruktor će raditi sasvim u redu ako niste pokrenuli uslugu na ne-zadanom priključku ili udaljenom stroju, u tom slučaju ga možete ispravno konfigurirati prosljeđivanjem ispravnih vrijednosti kao parametara u konstruktor.

5. Redisove strukture podataka

Podržane su većine izvornih naredbi za rad i, što je vrlo povoljno, obično dijele isto ime metode.

5.1. Žice

Nizovi su najosnovnija vrsta Redisove vrijednosti, korisna kada trebate zadržati jednostavne tipove podataka ključ / vrijednost:

jedis.set ("događaji / grad / Rim", "32,15,223,828"); Niz cachedResponse = jedis.get ("događaji / grad / rome");

Varijabla cachedResponse zadržat će vrijednost 32,15,223,828. Zajedno s podrškom za istek, o kojoj ćemo kasnije razgovarati, može raditi kao brzi i jednostavan za korištenje sloja predmemorije za HTTP zahtjeve primljene u vašoj web aplikaciji i druge zahtjeve predmemoriranja.

5.2. Popisi

Redis popisi su jednostavno popisi nizova, poredani prema redoslijedu umetanja i čine ga idealnim alatom za primjenu, na primjer, redova poruka:

jedis.lpush ("red zadataka # zadataka", "firstTask"); jedis.lpush ("red zadataka # zadataka", "secondTask"); String zadatak = jedis.rpop ("red zadataka #");

Varijabla zadatak zadržat će vrijednost firstTask. Imajte na umu da bilo koji objekt možete serializirati i zadržati ga kao niz, tako da poruke u redu mogu po potrebi nositi složenije podatke.

5.3. Kompleti

Redis skupovi su nesređena kolekcija žica koje dobro dođu kad želite isključiti ponovljene članove:

jedis.sadd ("nadimci", "nadimak # 1"); jedis.sadd ("nadimci", "nadimak # 2"); jedis.sadd ("nadimci", "nadimak # 1"); Postavite nadimke = jedis.smembers ("nadimci"); boolean postoji = jedis.sismember ("nadimci", "nadimak # 1");

Java set nadimci imat će veličinu 2, drugi dodatak nadimak # 1 bio ignoriran. Također, postoji varijabla će imati vrijednost pravi, metoda sismember omogućuje vam brzu provjeru postojanja određenog člana.

5.4. Hashevi

Redis hashes mapiraju između Niz polja i Niz vrijednosti:

jedis.hset ("korisnik # 1", "ime", "Peter"); jedis.hset ("korisnik # 1", "posao", "političar"); Naziv niza = jedis.hget ("user # 1", "name"); Polja karte = jedis.hgetAll ("user # 1"); String posao = polja.get ("posao");

Kao što vidite, hashi su vrlo prikladna vrsta podataka kada želite pojedinačno pristupiti svojstvima objekta, jer ne morate dohvatiti cijeli objekt.

5.5. Poredani skupovi

Sortirani skupovi su poput skupa gdje svaki član ima pridruženi poredak koji se koristi za njihovo razvrstavanje:

Rezultati na karti = novi HashMap (); scores.put ("PlayerOne", 3000.0); scores.put ("PlayerTwo", 1500.0); scores.put ("PlayerThree", 8200,0); scores.entrySet (). forEach (playerScore -> {jedis.zadd (ključ, playerScore.getValue (), playerScore.getKey ());}); String player = jedis.zrevrange ("ranking", 0, 1) .iterator (). Next (); dugi rang = jedis.zrevrank ("poredak", "PlayerOne");

Varijabla igrač zadržat će vrijednost PlayerThree jer dohvaćamo najboljih 1 igrača, a on je onaj s najvećim rezultatom. The rang varijabla imat će vrijednost 1 jer PlayerOne je drugi na ljestvici, a poredak se temelji na nuli.

6. Transakcije

Transakcije jamče atomskost i operacije sigurnosti niti, što znači da se zahtjevi drugih klijenata nikada neće obrađivati ​​istodobno tijekom Redisovih transakcija:

String friendsPrefix = "prijatelji #"; String userOneId = "4352523"; Niz userTwoId = "5552321"; Transakcija t = jedis.multi (); t.sadd (friendsPrefix + userOneId, userTwoId); t.sadd (friendsPrefix + userTwoId, userOneId); t.exec ();

Možete čak i postići da uspjeh transakcije ovisi o određenom ključu tako što ćete ga "gledati" neposredno prije nego što instantirate svoj Transakcija:

jedis.watch ("prijatelji # izbrisani #" + userOneId);

Ako se vrijednost tog ključa promijeni prije izvršenja transakcije, transakcija neće biti uspješno dovršena.

7. Cjevovod

Kada moramo poslati više naredbi, možemo ih spakirati u jedan zahtjev i uštedjeti opseg veze pomoću cjevovoda, to je u osnovi optimizacija mreže. Sve dok su operacije međusobno neovisne, možemo iskoristiti ovu tehniku:

String userOneId = "4352523"; Niz userTwoId = "4849888"; Cjevovod p = jedis.pipelined (); p.sadd ("pretražili #" + userOneId, "paris"); p.zadd ("poredak", 126, userOneId); p.zadd ("poredak", 325, userTwoId); Response pipeExists = p.sismember ("pretražili #" + userOneId, "paris"); Odgovor pipeRanking = p.zrange ("poredak", 0, -1); p.sync (); Niz postoji = pipeExists.get (); Postavi rang = pipeRanking.get ();

Primijetite da ne dobivamo izravan pristup odgovorima naredbi, umjesto toga dobivamo Odgovor instancu od koje možemo zatražiti temeljni odgovor nakon sinkronizacije cjevovoda.

8. Objavi / pretplati se

Funkciju posrednika za razmjenu poruka Redis možemo koristiti za slanje poruka između različitih komponenata našeg sustava. Pazite da niti pretplatnika i izdavača ne dijele istu Jedis vezu.

8.1. Pretplatnik

Pretplatite se i slušajte poruke poslane na kanal:

Jedi jSubscriber = novi Jedi (); jSubscriber.subscribe (novi JedisPubSub () {@Preuzmi javnu prazninu onMessage (kanal niza, poruka niza) {// obradi poruku}}, "kanal");

Pretplata je metoda blokiranja, morat ćete otkazati pretplatu na JedisPubSub eksplicitno. Nadjačali smo onMessage metoda, ali postoji mnogo korisnijih metoda dostupnih za poništavanje.

8.2. Izdavač

Zatim jednostavno pošaljite poruke na isti kanal iz niti izdavača:

Jedi jPublisher = novi Jedi (); jPublisher.publish ("kanal", "testna poruka");

9. Spajanje veza

Važno je znati da je način na koji smo imali posla s našim jedinicama Jedije naivan. U stvarnom scenariju ne želite koristiti jedan primjerak u okruženju s više niti jer jedan primjerak nije siguran u niti.

Srećom, lako možemo stvoriti skup veza s Redisom kako bismo ga ponovno upotrebljavali na zahtjev, spremište koje je sigurno i pouzdano sve dok resurs vraćate u bazen kad završite s tim.

Stvorimo JedisPool:

konačni JedisPoolConfig poolConfig = buildPoolConfig (); JedisPool jedisPool = novi JedisPool (poolConfig, "localhost"); private JedisPoolConfig buildPoolConfig () {final JedisPoolConfig poolConfig = new JedisPoolConfig (); poolConfig.setMaxTotal (128); poolConfig.setMaxIdle (128); poolConfig.setMinIdle (16); poolConfig.setTestOnBorrow (istina); poolConfig.setTestOnReturn (true); poolConfig.setTestWhileIdle (true); poolConfig.setMinEvictableIdleTimeMillis (Duration.ofSeconds (60) .toMillis ()); poolConfig.setTimeBetweenEvictionRunsMillis (Duration.ofSeconds (30) .toMillis ()); poolConfig.setNumTestsPerEvictionRun (3); poolConfig.setBlockWhenExhausted (true); return poolConfig; }

Budući da je instanca bazena sigurna u nitima, možete je negdje statički pohraniti, ali trebali biste se pobrinuti za uništavanje bazena kako biste izbjegli curenje kad se aplikacija isključuje.

Sada po potrebi možemo koristiti svoj bazen s bilo kojeg mjesta u aplikaciji:

probajte (Jedis jedis = jedisPool.getResource ()) {// radite operacije s resursom jedis}

Koristili smo Java izjavu try-with-resources kako bismo izbjegli ručno zatvaranje resursa Jedis, ali ako ne možete koristiti ovu izjavu, resurs možete zatvoriti i ručno u konačno klauzula.

Obavezno koristite bazen kao što smo opisali u vašoj prijavi ako se ne želite suočiti s gadnim problemima s više navoja. Očito se možete igrati s parametrima konfiguracije bazena kako biste ga prilagodili najboljim postavkama u vašem sustavu.

10. Redis klaster

Ova Redisova implementacija omogućuje jednostavnu skalabilnost i visoku dostupnost, preporučujemo vam da pročitate njihove službene specifikacije ako vam nisu poznate. Nećemo obrađivati ​​postavljanje klastera Redis, jer je to malo izvan opsega ovog članka, ali ne biste trebali imati problema u tome kad završite s njegovom dokumentacijom.

Kad to spremimo, možemo ga početi koristiti iz naše aplikacije:

probajte (JedisCluster jedisCluster = novi JedisCluster (novi HostAndPort ("localhost", 6379))) {// koristite resurs jedisCluster kao da je to uobičajeni Jedis resurs} ulov (IOException e) {}

Trebamo pružiti detalje o hostu i priključku iz jedne od naših glavnih instanci, ona će automatski otkriti ostale instance u klasteru.

Ovo je sigurno vrlo moćna značajka, ali nije srebrni metak. Kada koristite Redis Cluster, ne možete izvršavati transakcije niti koristiti cjevovode, dvije važne značajke na koje se mnoge aplikacije oslanjaju kako bi osigurale integritet podataka.

Transakcije su onemogućene jer će se u klaster okruženju ključevi zadržati na više instanci. Atomicnost rada i sigurnost niti ne mogu se zajamčiti za operacije koje uključuju izvršavanje naredbi u različitim instancama.

Neke napredne strategije stvaranja ključeva osigurat će da se podaci koji su zanimljivi za vas da biste nastavili u istoj instanci tako i sačuvaju. U teoriji, to bi vam trebalo omogućiti uspješno obavljanje transakcija pomoću jedne od temeljnih Jedi instanci Redis klastera.

Nažalost, trenutno ne možete saznati u kojoj se instanci Redisa određeni ključ sprema pomoću Jedis-a (što je u stvari izvorno podržava Redis), tako da ne znate u kojoj instanci morate izvršiti operaciju transakcije. Ako ste zainteresirani za ovo, ovdje možete pronaći više informacija.

11. Zaključak

Velika većina Redisovih značajki već je dostupna u Jedisima i njegov razvoj napreduje dobrim tempom.

Omogućuje vam integriranje moćnog mehanizma za pohranu u memoriji u vašu aplikaciju s vrlo malo muke, samo nemojte zaboraviti postaviti spremanje veza kako biste izbjegli probleme sa sigurnošću niti.

Uzorke koda možete pronaći u projektu GitHub.