Een gids voor Redis met Redisson

1. Overzicht

Redisson is een Redis-client voor Java. In dit artikel zullen we enkele van de functies onderzoeken en laten zien hoe het het bouwen van gedistribueerde bedrijfsapplicaties zou kunnen vergemakkelijken.

Redisson vormt een gegevensraster in het geheugen die gedistribueerde Java-objecten en -services aanbiedt die worden ondersteund door Redis. Dankzij het gedistribueerde gegevensmodel in het geheugen kunnen domeinobjecten en -services worden gedeeld tussen applicaties en servers.

In dit artikel zullen we zien hoe Redisson moet worden opgezet, hoe het werkt, en enkele van Redisson's objecten en diensten verkennen.

2. Maven afhankelijkheden

Laten we beginnen met importeren Redisson aan ons project door het onderstaande gedeelte toe te voegen aan ons pom.xml:

 org.redisson redisson 3.13.1 

De laatste versie van deze afhankelijkheid is hier te vinden.

3. Configuratie

Voordat we aan de slag gaan, moeten we ervoor zorgen dat we de nieuwste versie van Redis hebben geïnstalleerd en uitgevoerd. Als je geen Redis hebt en je Linux of Macintosh gebruikt, kun je de informatie hier volgen om het te installeren. Als u een Windows-gebruiker bent, kunt u Redis instellen met deze niet-officiële poort.

We moeten Redisson configureren om verbinding te maken met Redis. Redisson ondersteunt verbindingen met de volgende Redis-configuraties:

  • Eén knooppunt
  • Master met slaafknooppunten
  • Sentinel-knooppunten
  • Geclusterde knooppunten
  • Gerepliceerde knooppunten

Redisson ondersteunt Amazon Web Services (AWS) ElastiCache Cluster en Azure Redis Cache voor geclusterde en gerepliceerde knooppunten.

Laten we verbinding maken met één knooppuntinstantie van Redis. Dit exemplaar wordt lokaal uitgevoerd op de standaardpoort, 6379:

RedissonClient client = Redisson.create ();

U kunt verschillende configuraties doorgeven aan het Redisson voorwerpen creëren methode. Dit kunnen configuraties zijn om verbinding te maken met een andere poort, of misschien om verbinding te maken met een Redis-cluster. Dit configuratie kan in Java-code zijn of geladen vanuit een extern configuratiebestand.

3.1. Java-configuratie

Laten we Redisson configureren in Java-code:

Config config = nieuwe Config (); config.useSingleServer () .setAddress ("redis: //127.0.0.1: 6379"); RedissonClient client = Redisson.create (config);

Wij specificeer Redisson-configuraties in een instantie van een Config voorwerp en geef het vervolgens door aan de creëren methode. Hierboven hebben we aan Redisson gespecificeerd dat we verbinding willen maken met een enkel knooppuntinstantie van Redis. Om dit te doen hebben we de Config voorwerpen useSingleServer methode. Dit retourneert een verwijzing naar een SingleServerConfig voorwerp.

De SingleServerConfig object heeft instellingen die Redisson gebruikt om verbinding te maken met één knooppuntinstantie van Redis. Hier gebruiken we zijn setAddress methode om het adres instelling. Dit stelt het adres in van het knooppunt waarmee we verbinding maken. Enkele andere instellingen zijn retryAttempts, connectionTimeout en klantnaam. Deze instellingen worden geconfigureerd met behulp van hun overeenkomstige setter-methoden.

We kunnen Redisson voor verschillende Redis-configuraties op een vergelijkbare manier configureren met behulp van de Config object's volgende methoden:

  • useSingleServer - voor instantie met één knooppunt. Download hier de instellingen voor één knooppunt
  • useMasterSlaveServers - voor master met slave-knooppunten. Download hier de instellingen voor master-slave-knooppunten
  • useSentinelServers - voor schildwachtknopen. Download hier de sentinel node-instellingen
  • useClusterServers - voor geclusterde knooppunten. Download hier de instellingen voor geclusterde knooppunten
  • useReplicatedServers - voor gerepliceerde knooppunten. Download hier gerepliceerde knooppuntinstellingen

3.2. Bestandsconfiguratie

Redisson kan configuraties laden vanuit externe JSON of YAML bestanden:

Config config = Config.fromJSON (nieuw bestand ("singleNodeConfig.json")); RedissonClient client = Redisson.create (config);

De Config voorwerpen van JSON methode kan configuraties laden vanuit een string, bestand, invoerstroom of URL.

Hier is de voorbeeldconfiguratie in het singleNodeConfig.json het dossier:

{"singleServerConfig": {"idleConnectionTimeout": 10000, "connectTimeout": 10000, "timeout": 3000, "retryAttempts": 3, "retryInterval": 1500, "wachtwoord": null, "subscriptionsPerConnection": 5, "clientName ": null," address ":" redis: //127.0.0.1: 6379 "," subscriptionConnectionMinimumIdleSize ": 1," subscriptionConnectionPoolSize ": 50," connectionMinimumIdleSize ": 10," connectionPoolSize ": 64," database ": 0, "dnsMonitoringInterval": 5000}, "threads": 0, "nettyThreads": 0, "codec": null}

Hier is een overeenkomstig YAML-configuratiebestand:

singleServerConfig: idleConnectionTimeout: 10000 connectTime-out: 10000 time-out: 3000 retryAttempts: 3 retryInterval: 1500 wachtwoord: null subscriptionsPerConnection: 5 clientName: null adres: "redis: //127.0.0.1: 6379" subscriptionConnectionMinimumIdleSize: 1 abonnementMinimumIdleSize: 1 abonnement 64 database: 0 dnsMonitoringInterval: 5000 threads: 0 nettyThreads: 0 codec:! {} 

We kunnen andere Redis-configuraties vanuit een bestand op een vergelijkbare manier configureren met instellingen die eigen zijn aan die configuratie. Ter referentie, hier zijn hun JSON- en YAML-bestandsindelingen:

  • Single node - formaat
  • Master met slaafknooppunten - formaat
  • Sentinel-knooppunten - formaat
  • Geclusterde knooppunten - formaat
  • Gerepliceerde knooppunten - formaat

Om een ​​Java-configuratie op te slaan in JSON- of YAML-indeling, kunnen we de toJSON of toYAML methoden van de Config voorwerp:

Config config = nieuwe Config (); // ... we configureren hier meerdere instellingen in Java String jsonFormat = config.toJSON (); String yamlFormat = config.toYAML ();

Nu we weten hoe we Redisson moeten configureren, gaan we kijken hoe Redisson bewerkingen uitvoert.

4. Werking

Redisson ondersteunt synchrone, asynchrone en reactieve interfaces. Operaties over deze interfaces zijn thread-safe.

Alle entiteiten (objecten, verzamelingen, sloten en services) gegenereerd door een RedissonClient hebben synchrone en asynchrone methoden. Synchrone methoden hebben asynchrone varianten. Deze methoden dragen normaal gesproken dezelfde methodenaam als hun synchrone varianten, toegevoegd met “Async”. Laten we eens kijken naar een synchrone methode van de RAtomicLong voorwerp:

RedissonClient client = Redisson.create (); RAtomicLong myLong = client.getAtomicLong ('myLong'); 

De asynchrone variant van de synchrone vergelijkAndSet methode zou zijn:

RFuture isSet = myLong.compareAndSetAsync (6, 27);

De asynchrone variant van de methode retourneert een RFuture voorwerp. We kunnen luisteraars op dit object instellen om het resultaat terug te krijgen wanneer het beschikbaar komt:

isSet.handle ((resultaat, uitzondering) -> {// behandel hier het resultaat of de uitzondering.});

Om reactieve objecten te genereren, zouden we de RedissonReactiveClient:

RedissonReactiveClient client = Redisson.createReactive (); RAtomicLongReactive myLong = client.getAtomicLong ("myLong"); Uitgever isSetPublisher = myLong.compareAndSet (5, 28);

Deze methode retourneert reactieve objecten op basis van de Reactive Streams Standard voor Java 9.

Laten we eens kijken naar enkele van de gedistribueerde objecten die door Redisson worden geleverd.

5. Objecten

Een individueel exemplaar van een Redisson-object wordt geserialiseerd en opgeslagen in een van de beschikbare Redis-knooppunten die Redisson ondersteunen. Deze objecten kunnen worden gedistribueerd in een cluster over meerdere knooppunten en zijn toegankelijk voor een enkele applicatie of meerdere applicaties / servers.

Deze gedistribueerde objecten volgen specificaties van het java.util.concurrent.atomic pakket. Ze ondersteunen vergrendelingsvrije, draadveilige en atomaire bewerkingen op objecten die zijn opgeslagen in Redis. De gegevensconsistentie tussen applicaties / servers is verzekerd omdat waarden niet worden bijgewerkt terwijl een andere applicatie het object aan het lezen is.

Redisson-objecten zijn gebonden aan Redis-sleutels. We kunnen deze sleutels beheren via het RKeys koppel. En dan hebben we toegang tot onze Redisson-objecten met behulp van deze sleutels.

Er zijn verschillende opties die we kunnen gebruiken om de Redis-sleutels te krijgen.

We kunnen eenvoudig alle sleutels krijgen:

RKeys-sleutels = client.getKeys ();

Als alternatief kunnen we alleen de namen extraheren:

Herhaalbare allKeys = keys.getKeys ();

En tot slot zijn we in staat om de sleutels volgens een patroon te krijgen:

Herhaalbare keysByPattern = keys.getKeysByPattern ('key *')

De RKeys-interface maakt het ook mogelijk om sleutels te verwijderen, sleutels te verwijderen volgens een patroon en andere nuttige sleutelgebaseerde bewerkingen die we zouden kunnen gebruiken om onze sleutels en objecten te beheren.

Gedistribueerde objecten die door Redisson worden geleverd, zijn onder meer:

  • ObjectHolder
  • BinaryStreamHolder
  • GeospatialHolder
  • BitSet
  • AtomicLong
  • AtomicDouble
  • Onderwerp
  • BloomFilter
  • HyperLogLog

Laten we eens kijken naar drie van deze objecten: ObjectHolder, AtomicLong, en Onderwerp.

5.1. Objecthouder

Vertegenwoordigd door de RBucket class, kan dit object elk type object bevatten. Dit object heeft een maximale grootte van 512 MB:

RBucket bucket = client.getBucket ("ledger"); bucket.set (new Ledger ()); Ledger ledger = bucket.get ();

De RBucket object kan atomaire bewerkingen uitvoeren, zoals vergelijkAndSet engetAndSet op objecten die het vasthoudt.

5.2. AtomicLong

Vertegenwoordigd door de RAtomicLong class, lijkt dit object sterk op de java.util.concurrent.atomic.AtomicLong klasse en vertegenwoordigt een lang waarde die atomair kan worden bijgewerkt:

RAtomicLong atomicLong = client.getAtomicLong ("myAtomicLong"); atomicLong.set (5); atomicLong.incrementAndGet ();

5.3. Onderwerp

De Onderwerp object ondersteunt het "publiceren en abonneren" -mechanisme van Redis. Luisteren naar gepubliceerde berichten:

RTopic subscribeTopic = client.getTopic ("baeldung"); subscribeTopic.addListener (CustomMessage.class, (kanaal, customMessage) -> future.complete (customMessage.getMessage ()));

Boven de Onderwerp is geregistreerd om naar berichten van het "baeldung" -kanaal te luisteren. Vervolgens voegen we een luisteraar toe aan het onderwerp om inkomende berichten van dat kanaal af te handelen. We kunnen meerdere luisteraars aan een kanaal toevoegen.

Laten we berichten publiceren op het "baeldung" -kanaal:

RTopic publishTopic = client.getTopic ("baeldung"); long clientsReceivedMessage = publishTopic.publish (nieuwe CustomMessage ("Dit is een bericht"));

Dit kan worden gepubliceerd vanaf een andere applicatie of server. De Aangepast bericht object wordt ontvangen door de luisteraar en verwerkt zoals gedefinieerd in het onMessage methode.

We kunnen hier meer leren over andere Redisson-objecten.

6. Collecties

We behandelen Redisson-collecties op dezelfde manier als objecten.

Gedistribueerde collecties aangeboden door Redisson zijn onder meer:

  • Kaart
  • Multimap
  • Set
  • SortedSet
  • ScoredSortedSet
  • LexSortedSet
  • Lijst
  • Wachtrij
  • Deque
  • BlockingQueue
  • BoundedBlockingQueue
  • Deque blokkeren
  • BlockingFairQueue
  • Vertraagde wachtrij
  • Prioriteits-rij
  • PrioriteitDeque

Laten we eens kijken naar drie van deze collecties: Kaart, set, en Lijst.

6.1. Kaart

Op Redisson gebaseerde kaarten implementeren het java.util.concurrent.ConcurrentMap en java.util.Map interfaces. Redisson heeft vier kaartimplementaties. Dit zijn RMap, RMapCache, RLocalCachedMap en RClusteredMap.

Laten we een kaart maken met Redisson:

RMap map = client.getMap ("grootboek"); Ledger newLedger = map.put ("123", new Ledger ()); map

RMapCache ondersteunt het verwijderen van kaartinvoer. RLocalCachedMap staat lokale caching van kaartingangen toe. RClusteredMap maakt het mogelijk om gegevens van een enkele kaart te splitsen over hoofdknooppunten van Redis-clusters.

We kunnen hier meer leren over Redisson-kaarten.

6.2. Set

Redisson gebaseerd Set implementeert het java.util.Set koppel.

Redisson heeft er drie Set implementaties, RSet, RSetCache, en RClusteredSet met vergelijkbare functionaliteit als hun tegenhangers op de kaart.

Laten we een Set met Redisson:

RSet ledgerSet = client.getSet ("ledgerSet"); ledgerSet.add (nieuwe Ledger ());

We kunnen hier meer leren over Redisson-sets.

6.3. Lijst

Op redisson gebaseerd Lijsten implementeer het java.util.List koppel.

Laten we een Lijst met Redisson:

RList ledgerList = client.getList ("ledgerList"); ledgerList.add (nieuwe Ledger ());

We kunnen hier meer lezen over andere Redisson-collecties.

7. Sloten en synchronisatoren

Redisson's gedistribueerde vergrendelingen maken thread-synchronisatie mogelijk tussen applicaties / servers. De lijst met vergrendelingen en synchronizers van Redisson omvat:

  • Slot
  • FairLock
  • MultiLock
  • ReadWriteLock
  • Semafoor
  • PermitExpettableSemaphore
  • CountDownLatch

Laten we eens kijken Slot en MultiLock.

7.1. Slot

Redisson's Slot werktuigen java.util.concurrent.locks.Lock koppel.

Laten we een slot implementeren, vertegenwoordigd door de RLock klasse:

RLock lock = client.getLock ("lock"); lock.lock (); // voer een aantal lange operaties uit ... lock.unlock ();

7.2. MultiLock

Redisson's RedissonMultiLock groepen meerdere RLock objecten en behandelt ze als een enkel slot:

RLock lock1 = clientInstance1.getLock ("lock1"); RLock lock2 = clientInstance2.getLock ("lock2"); RLock lock3 = clientInstance3.getLock ("lock3"); RedissonMultiLock lock = nieuw RedissonMultiLock (lock1, lock2, lock3); lock.lock (); // voer een langlopende bewerking uit ... lock.unlock ();

We kunnen hier meer leren over andere sloten.

8. Diensten

Redisson stelt 4 soorten gedistribueerde services bloot. Dit zijn: Service op afstand, Live Object-service, Executor Service en Geplande uitvoerdersdienst. Laten we eens kijken naar de Remote Service en Live Object Service.

8.1. Service op afstand

Deze dienst biedt Aanroep van Java-methode op afstand mogelijk gemaakt door Redis. Een Redisson-service op afstand bestaat uit een server-side (worker-instantie) en client-side implementatie. De implementatie aan de serverzijde voert een externe methode uit die door de client wordt aangeroepen. Oproepen van een externe service kunnen synchroon of asynchroon zijn.

De serverzijde registreert een interface voor externe aanroep:

RRemoteService remoteService = client.getRemoteService (); LedgerServiceImpl ledgerServiceImpl = nieuwe LedgerServiceImpl (); remoteService.register (LedgerServiceInterface.class, ledgerServiceImpl);

De client-side roept een methode van de geregistreerde externe interface aan:

RRemoteService remoteService = client.getRemoteService (); LedgerServiceInterface ledgerService = remoteService.get (LedgerServiceInterface.class); Lijstitems = ledgerService.getEntries (10);

We kunnen hier meer lezen over externe services.

8.2. Live Object-service

Redisson Live Objects breidt het concept van standaard Java-objecten uit die alleen toegankelijk waren vanaf een enkele JVM naar verbeterde Java-objecten die kunnen worden gedeeld tussen verschillende JVM's op verschillende machines. Dit wordt bereikt door de velden van een object toe te wijzen aan een Redis-hash. Deze mapping wordt gemaakt door middel van een door runtime geconstrueerde proxyklasse. Veldgetters en setters worden toegewezen aan Redis hget / hset-opdrachten.

Redisson Live Objects ondersteunen atomaire veldtoegang als resultaat van de single-threaded aard van Redis.

Het maken van een levend object is eenvoudig:

@REntity openbare klasse LedgerLiveObject {@RId private String-naam; // getters en setters ...}

We annoteren onze klas met @REntity en een uniek of identificerend veld met @RID. Zodra we dit hebben gedaan, kunnen we ons Live Object in onze applicatie gebruiken:

RLiveObjectService service = client.getLiveObjectService (); LedgerLiveObject ledger = new LedgerLiveObject (); ledger.setName ("ledger1"); grootboek = service.persist (grootboek);

We maken ons Live Object zoals standaard Java-objecten met behulp van de nieuw trefwoord. We gebruiken dan een instantie van RLiveObjectService om het object in Redis op te slaan met behulp van zijn volharden methode.

Als het object eerder is vastgehouden aan Redis, kunnen we het object ophalen:

LedgerLiveObject returnLedger = service.get (LedgerLiveObject.class, "ledger1");

Wij gebruiken de RLiveObjectService om ons Live Object te krijgen met behulp van het veld dat is geannoteerd met @RID.

Hier kunnen we meer vinden over Redisson Live Objects, en andere Redisson-services worden hier beschreven.

9. Pipelining

Redisson ondersteunt pipelining. Meerdere bewerkingen kunnen als een enkele atomaire bewerking worden gecombineerd. Dit wordt mogelijk gemaakt door de RBatch klasse. Meerdere commando's worden geaggregeerd tegen een RBatch objectinstantie voordat ze worden uitgevoerd:

RBatch batch = client.createBatch (); batch.getMap ("ledgerMap"). fastPutAsync ("1", "2"); batch.getMap ("ledgerMap"). putAsync ("2", "5"); BatchResult batchResult = batch.execute ();

10. Scripting

Redisson ondersteunt LUA-scripting. We kunnen LUA-scripts uitvoeren tegen Redis:

client.getBucket ("foo"). set ("bar"); String resultaat = client.getScript (). Eval (Mode.READ_ONLY, "return redis.call ('get', 'foo')", RScript.ReturnType.VALUE);

11. Klant op laag niveau

Het is mogelijk dat we Redis-bewerkingen willen uitvoeren die nog niet worden ondersteund door Redisson. Redisson biedt een client op laag niveau waarmee native Redis-opdrachten kunnen worden uitgevoerd:

RedisClientConfig redisClientConfig = nieuwe RedisClientConfig (); redisClientConfig.setAddress ("localhost", 6379); RedisClient-client = RedisClient.create (redisClientConfig); RedisConnection conn = client.connect (); conn.sync (StringCodec.INSTANCE, RedisCommands.SET, "test", 0); conn.closeAsync (); client.shutdown ();

De low-level client ondersteunt ook asynchrone bewerkingen.

12. Conclusie

Dit artikel behandelde Redisson en enkele van de functies die het ideaal maken voor het ontwikkelen van gedistribueerde applicaties. We hebben de gedistribueerde objecten, collecties, sloten en services onderzocht. We hebben ook enkele van de andere functies onderzocht, zoals pipelining, scripting en de low-level client.

Redisson biedt ook integratie met andere frameworks zoals de JCache API, Spring Cache, Hibernate Cache en Spring Sessions. We kunnen hier meer leren over de integratie met andere frameworks.

U kunt codevoorbeelden vinden in het GitHub-project.