Un guide pour Redis avec Redisson

Un guide pour Redis avec Redisson

1. Vue d'ensemble

Redisson is a Redis client for Java. Dans cet article, nous allons explorer certaines de ses fonctionnalités et montrer comment il peut faciliter la création d'applications métier distribuées.

Redisson constitutes an in-memory data grid qui offre des objets et des services Java distribués soutenus par Redis. Son modèle de données distribuées en mémoire permet le partage d’objets et de services de domaine entre les applications et les serveurs.

Cet article nous explique comment configurer Redisson, comprendre son fonctionnement et explorer certains objets et services de Redisson.

2. Dépendances Maven

Commençons par importerRedisson dans notre projet en ajoutant la section ci-dessous à nospom.xml:


    org.redisson
    redisson
    3.3.0

La dernière version de cette dépendance peut être trouvéehere.

3. Configuration

Avant de commencer, nous devons nous assurer que nous avons la dernière version de l’installation et du fonctionnement de Redis. Si vous n’avez pas Redis et que vous utilisez Linux ou Macintosh, vous pouvez suivre les informationshere pour le configurer. Si vous êtes un utilisateur Windows, vous pouvez configurer Redis en utilisant ceport non officiel.

Nous devons configurer Redisson pour se connecter à Redis. Redisson prend en charge les connexions aux configurations Redis suivantes:

  • Noeud unique

  • Maître avec nœuds esclaves

  • Nœuds sentinelles

  • Nœuds en cluster

  • Noeuds répliqués

Redisson supports Amazon Web Services (AWS) ElastiCache Cluster and Azure Redis Cache pour les nœuds en cluster et répliqués.

Connectons-nous à une seule instance de nœud de Redis. Cette instance s'exécute localement sur le port par défaut, 6379:

RedissonClient client = Redisson.create();

Vous pouvez transmettre différentes configurations à la méthodecreate de l’objetRedisson. Il peut s'agir de configurations pour le connecter à un autre port, ou peut-être pour se connecter à un cluster Redis. Ceconfiguration could be in Java code or loaded from an external configuration file.

3.1. Configuration Java

Configurons Redisson en code Java:

Config config = new Config();
config.useSingleServer()
  .setAddress("127.0.0.1:6379");

RedissonClient client = Redisson.create(config);

Nousspecify Redisson configurations in an instance of a Config object puis le passons à la méthodecreate. Ci-dessus, nous avons spécifié à Redisson que nous souhaitons nous connecter à une instance de nœud unique de Redis. Pour ce faire, nous avons utilisé la méthodeuseSingleServer de l’objetConfig. Cela renvoie une référence à un objetSingleServerConfig.

L'objetSingleServerConfig a des paramètres que Redisson utilise pour se connecter à une seule instance de nœud de Redis. Ici, nous utilisons sa méthodesetAddress pour configurer le paramètreaddress. Ceci définit l'adresse du nœud auquel nous nous connectons. Certains autres paramètres incluentretryAttempts,connectionTimeout etclientName. Ces paramètres sont configurés à l'aide des méthodes de définition correspondantes.

Nous pouvons configurer Redisson pour différentes configurations Redis de la même manière en utilisant les méthodes suivantes de l’objetConfig:

  • useSingleServer - pour une instance de nœud unique. Obtenir les paramètres de nœud uniquehere

  • useMasterSlaveServers - pour maître avec nœuds esclaves. Obtenir les paramètres du nœud maître-esclavehere

  • useSentinelServers - pour les nœuds sentinelles. Obtenir les paramètres du nœud sentinellehere

  • useClusterServers - pour les nœuds en cluster. Obtenir les paramètres de nœud en clusterhere

  • useReplicatedServers - pour les nœuds répliqués. Obtenir les paramètres de nœud répliquéhere

3.2. Configuration des fichiers

FichiersRedisson can load configurations from external JSON or YAML:

Config config = Config.fromJSON(new File("singleNodeConfig.json"));
RedissonClient client = Redisson.create(config);

La méthodefromJSON de l’objetConfig peut charger des configurations à partir d’une chaîne, d’un fichier, d’un flux d’entrée ou d’une URL.

Voici l'exemple de configuration dans le fichiersingleNodeConfig.json:

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

Voici un fichier de configuration YAML correspondant:

singleServerConfig:
    idleConnectionTimeout: 10000
    pingTimeout: 1000
    connectTimeout: 10000
    timeout: 3000
    retryAttempts: 3
    retryInterval: 1500
    reconnectionTimeout: 3000
    failedAttempts: 3
    password: null
    subscriptionsPerConnection: 5
    clientName: null
    address: "redis://127.0.0.1:6379"
    subscriptionConnectionMinimumIdleSize: 1
    subscriptionConnectionPoolSize: 50
    connectionMinimumIdleSize: 10
    connectionPoolSize: 64
    database: 0
    dnsMonitoring: false
    dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: ! {}
useLinuxNativeEpoll: false

Nous pouvons configurer d'autres configurations Redis à partir d'un fichier de manière similaire à l'aide de paramètres spécifiques à cette configuration. Pour votre information, voici leurs formats de fichiers JSON et YAML:

Pour enregistrer une configuration Java au format JSON ou YAML, nous pouvons utiliser les méthodestoJSON outoYAML de l'objetConfig:

Config config = new Config();
// ... we configure multiple settings here in Java
String jsonFormat = config.toJSON();
String yamlFormat = config.toYAML();

Maintenant que nous savons comment configurer Redisson, voyons comment Redisson exécute les opérations.

4. Opération

Redisson supports synchronous, asynchronous and reactive interfaces. Opérations sur cesinterfaces are thread-safe.

Toutes les entités (objets, collections, verrous et services) générées par unRedissonClient ont des méthodes synchrones et asynchrones. Synchronous methods bear asynchronous variants. Ces méthodes portent normalement le même nom de méthode que leurs variantes synchrones, suivies de “Async”. Examinons une méthode synchrone de l’objetRAtomicLong:

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

La variante asynchrone de la méthode synchronecompareAndSet serait:

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

La variante asynchrone de la méthode renvoie un objetRFuture. Nous pouvons définir des auditeurs sur cet objet pour récupérer le résultat lorsqu'il devient disponible:

isSet.handle((result, exception) -> {
    // handle the result or exception here.
});

Pour générer des objets réactifs, nous aurions besoin d'utiliser leRedissonReactiveClient: `++`

RedissonReactiveClient client = Redisson.createReactive();
RAtomicLongReactive myLong = client.getAtomicLong("myLong");

Publisher isSetPublisher = myLong.compareAndSet(5, 28);

Cette méthode renvoie des objets réactifs basés sur le standardReactive Streams pour Java 9.

Explorons certains des objets distribués fournis par Redisson.

5. Objets

Une instance individuelle d'unRedisson object is serialized and stored in any of the available Redis nodes backing Redisson. Ces objets peuvent être répartis dans un cluster sur plusieurs nœuds et accessibles via une seule application ou plusieurs applications / serveurs.

Ces objets distribués suivent les spécifications desjava.util.concurrent.atomic package.They support lock-free, thread-safe and atomic operations on objects stored in Redis. La cohérence des données entre les applications / serveurs est assurée car les valeurs ne sont pas mises à jour pendant la lecture de l'objet par une autre application.

Les objets Redisson sont liés aux clés Redis. Nous pouvons gérer ces clés via l'interfaceRKeys. Nous accédons à nos objets Redisson en utilisant ces clés.

Nous pouvons obtenir toutes les clés:

RKeys keys = client.getKeys();

Nous pouvons extraire tous les noms de clés sous forme de collections de chaînes itérables:

Iterable allKeys = keys.getKeys();

Nous pouvons obtenir des clés conformes à un modèle:

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

L’interface de RKeys permet également de supprimer des clés, modèle par modèle, ainsi que d’autres opérations utiles basées sur les clés que nous pourrions utiliser pour gérer nos clés et nos objets.

Les objets distribués fournis par Redisson incluent:

  • ObjectHolder

  • BinaryStreamHolder

  • GeospatialHolder

  • BitSet

  • AtomicLong

  • AtomicDouble

  • Sujet

  • BloomFilter

  • HyperLogLog

Examinons trois de ces objets:ObjectHolder, AtomicLong, etTopic.

5.1. Porte-objet

Représenté par la classeRBucket, cet objet peut contenir tout type d'objet. Cet objet a une taille maximale de 512 Mo:

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

L'objetRBucket peut effectuer des opérations atomiques telles quecompareAndSet andgetAndSet sur les objets qu'il contient.

5.2. AtomicLong

Représenté par la classeRAtomicLong, cet objet ressemble étroitement à la classejava.util.concurrent.atomic.AtomicLong et représente une valeurlong qui peut être mise à jour de manière atomique:

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

5.3. Sujet

L'objetTopic prend en charge le mécanisme «publier et souscrire» de Redis. Pour écouter les messages publiés:

RTopic subscribeTopic = client.getTopic("example");
subscribeTopic.addListener(
  (channel, customMessage)
  -> future.complete(customMessage.getMessage()));

Ci-dessus, leTopic est enregistré pour écouter les messages du canal «exemple». Nous ajoutons ensuite un écouteur à la rubrique pour gérer les messages entrants provenant de ce canal. Nous pouvons ajouter plusieurs auditeurs à un canal.

Publions des messages sur la chaîne "exemple":

RTopic publishTopic = client.getTopic("example");
long clientsReceivedMessage
  = publishTopic.publish(new CustomMessage("This is a message"));

Cela pourrait être publié depuis une autre application ou un autre serveur. L'objetCustomMessage sera reçu par l'auditeur et traité comme défini dans la méthodeonMessage.

Nous pouvons en savoir plus sur les autres objets Redissonhere.

6. Des collections

Nous traitons les collections Redisson de la même manière que nous traitons les objets.

Les collections distribuées fournies par Redisson comprennent:

  • Map

  • Multimap

  • Set

  • SortedSet

  • ScoredSortedSet

  • LexSortedSet

  • List

  • Queue

  • Deque

  • BlockingQueue

  • BoundedBlockingQueue

  • BlockingDeque

  • BlockingFairQueue

  • DelayedQueue

  • File d'attente de priorité

  • PriorityDeque

Jetons un coup d'œil à trois de ces collections:Map, Set, etList.

6.1. Map

Les cartes basées sur Redisson implémentent les interfacesjava.util.concurrent.ConcurrentMap etjava.util.Map. Redisson a quatre implémentations de carte. Ce sontRMap,RMapCache,RLocalCachedMap etRClusteredMap.

Créons une carte avec Redisson:

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

RMapCache prend en charge l'expulsion des entrées de carte. RLocalCachedMap permet la mise en cache locale des entrées de mappe. RClusteredMap permet aux données d'une seule mappe d'être réparties sur les nœuds maîtres du cluster Redis.

Nous pouvons en savoir plus sur les cartes Redissonhere.

6.2. Set

Redisson basé surSet implémente l'interfacejava.util.Set.

Redisson a trois implémentationsSet,RSet,RSetCache etRClusteredSet avec des fonctionnalités similaires à celles de leurs homologues cartographiques.

Créons unSet avec Redisson:

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

Nous pouvons en savoir plus sur les ensembles Redissonhere.

6.3. List

LesListsbasés sur Redisson implémentent l'interfacejava.util.List.

Créons unList avec Redisson:

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

Nous pouvons en savoir plus sur les autres collections Redissonhere.

7. Serrures et synchroniseurs

Lesdistributed locks allow for thread synchronizationde Redisson sur les applications / serveurs. La liste des verrous et synchroniseurs de Redisson comprend:

  • Lock

  • FairLock

  • MultiLock

  • ReadWriteLock

  • Sémaphore

  • PermisExpirableSémaphore

  • CountDownLatch

Jetons un œil àLock etMultiLock.

7.1. Lock

Lock de Redisson implémente l'interfacejava.util.concurrent.locks.Lock.

Implémentons un verrou, représenté par la classeRLock:

RLock lock = client.getLock("lock");
lock.lock();
// perform some long operations...
lock.unlock();

7.2. MultiLock

LeRedissonMultiLock de Redisson regroupe plusieurs objetsRLock et les traite comme un verrou unique:

RLock lock1 = clientInstance1.getLock("lock1");
RLock lock2 = clientInstance2.getLock("lock2");
RLock lock3 = clientInstance3.getLock("lock3");

RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
// perform long running operation...
lock.unlock();

Nous pouvons en savoir plus sur les autres verroushere.

8. Prestations de service

Redisson expose 4 types de services distribués. Ce sont:Remote Service,Live Object Service,Executor Service etScheduled Executor Service. Examinons le service à distance et le service d'objets en direct.

8.1. Service à distance

Ce service fournitJava remote method invocation facilitated by Redis. Un service distant Redisson consiste en une implémentation côté serveur (instance de travail) et côté client. L'implémentation côté serveur exécute une méthode distante appelée par le client. Les appels d'un service distant peuvent être synchrones ou asynchrones.

Le côté serveur enregistre une interface pour l'appel à distance:

RRemoteService remoteService = client.getRemoteService();
LedgerServiceImpl ledgerServiceImpl = new LedgerServiceImpl();

remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);

Le côté client appelle une méthode de l'interface distante enregistrée:

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

List entries = ledgerService.getEntries(10);

Nous pouvons en savoir plus sur les services à distancehere.

8.2. Service d'objets en direct

Redisson Live Objects étend le concept d'objets Java standard qui ne pouvaient être accessibles qu'à partir d'une seule JVM àenhanced Java objects that could be shared between different JVMs in different machines. Ceci est accompli en mappant les champs d'un objet à un hachage Redis. Ce mappage est effectué via une classe proxy construite à l'exécution. Les getters et les setters de terrain sont mappés aux commandes Redis hget / hset.

Redisson Live Objects prend en charge l’accès aux champs atomiques en raison de la nature mono-threadée de Redis.

Créer un objet en direct est simple:

@REntity
public class LedgerLiveObject {
    @RId
    private String name;

    // getters and setters...
}

Nous annotons notre classe avec@REntity et un champ unique ou identifiant avec@RId. Une fois cela fait, nous pouvons utiliser notre objet en direct dans notre application:

RLiveObjectService service = client.getLiveObjectService();

LedgerLiveObject ledger = new LedgerLiveObject();
ledger.setName("ledger1");

ledger = service.persist(ledger);

Nous créons notre objet en direct comme des objets Java standard en utilisant le mot-clénew. Nous utilisons ensuite une instance deRLiveObjectService pour enregistrer l'objet dans Redis en utilisant sa méthodepersist.

Si l'objet a déjà été conservé dans Redis, nous pouvons le récupérer:

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

Nous utilisons lesRLiveObjectService pour obtenir notre objet en direct en utilisant le champ annoté avec@RId.

Nous pouvons en savoir plus sur Redisson Live Objectshere.

Nous pouvons également en savoir plus sur les autres services Redissonhere.

9. Pipelining

Redisson soutient le pipeline. Multiple operations can be batched as a single atomic operation. Ceci est facilité par la classeRBatch. Plusieurs commandes sont regroupées sur une instance d'objetRBatch avant d'être exécutées:

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

List result = batch.execute();

10. Scripting

Redisson prend en charge les scripts LUA. We can execute LUA scripts against Redis:

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

11. Client de bas niveau

Il est possible que nous souhaitions effectuer des opérations Redis non encore prises en charge par Redisson. Redisson provides a low-level client that allows execution of native Redis commands:

RedisClient client = new RedisClient("localhost", 6379);
RedisConnection conn = client.connect();
conn.sync(StringCodec.INSTANCE, RedisCommands.SET, "test", 0);

conn.closeAsync();
client.shutdown();

Le client de bas niveau prend également en charge les opérations asynchrones.

12. Conclusion

Cet article présente Redisson et certaines des fonctionnalités qui le rendent idéal pour développer des applications distribuées. Nous avons exploré ses objets distribués, collections, verrous et services. Nous avons également exploré certaines de ses autres fonctionnalités telles que le traitement en pipeline, les scripts et son client de bas niveau.

Redisson also provides integration with other frameworks tels que l'API JCache, Spring Cache, Hibernate Cache et Spring Sessions. Nous pouvons en savoir plus sur son intégration avec d'autres frameworkshere.

Vous pouvez trouver des exemples de code dans lesGitHub project.