Руководство по Redis с Redisson

Руководство по Redis с Redisson

1. обзор

Redisson is a Redis client for Java. В этой статье мы рассмотрим некоторые его функции и продемонстрируем, как это может облегчить создание распределенных бизнес-приложений.

Redisson constitutes an in-memory data grid, который предлагает распределенные объекты и службы Java, поддерживаемые Redis.. Распределенная модель данных в памяти позволяет разделять объекты и службы домена между приложениями и серверами.

В этой статье мы расскажем, как настроить Redisson, понять, как он работает, а также изучить некоторые объекты и службы Redisson.

2. Maven Зависимости

Давайте начнем с импортаRedisson в наш проект, добавив раздел ниже в нашpom.xml:


    org.redisson
    redisson
    3.3.0

Последнюю версию этой зависимости можно найти вhere.

3. конфигурация

Прежде чем начать, мы должны убедиться, что у нас установлена ​​и запущена последняя версия Redis. Если у вас нет Redis и вы используете Linux или Macintosh, вы можете следовать информацииhere, чтобы настроить его. Если вы пользователь Windows, вы можете настроить Redis с помощью этого неофициальногоport.

Нам нужно настроить Redisson для подключения к Redis. Redisson поддерживает подключения к следующим конфигурациям Redis:

  • Один узел

  • Мастер с подчиненными узлами

  • Часовые узлы

  • Кластерные узлы

  • Реплицированные узлы

Redisson supports Amazon Web Services (AWS) ElastiCache Cluster and Azure Redis Cache для кластерных и реплицированных узлов.

Давайте подключимся к экземпляру Redis с одним узлом. Этот экземпляр работает локально на порту по умолчанию, 6379:

RedissonClient client = Redisson.create();

Вы можете передавать различные конфигурации методуcreate объектаRedisson. Это могут быть конфигурации для подключения к другому порту или подключения к кластеру Redis. Этоconfiguration could be in Java code or loaded from an external configuration file.

3.1. Конфигурация Java

Давайте настроим Redisson в Java-коде:

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

RedissonClient client = Redisson.create(config);

Мыspecify Redisson configurations in an instance of a Config object, а затем передаем его методуcreate. Выше мы указали Redisson, что мы хотим подключиться к одному экземпляру узла Redis. Для этого мы использовали методuseSingleServer объектаConfig. Это возвращает ссылку на объектSingleServerConfig.

У объектаSingleServerConfig есть настройки, которые Redisson использует для подключения к экземпляру Redis с одним узлом. Здесь мы используем его методsetAddress для настройки параметраaddress. Это устанавливает адрес узла, к которому мы подключаемся. Некоторые другие настройки включаютretryAttempts,connectionTimeout иclientName. Эти параметры настраиваются с использованием соответствующих им методов установки.

Мы можем настроить Redisson для разных конфигураций Redis аналогичным образом, используя следующие методы объектаConfig:

  • useSingleServer - для экземпляра с одним узлом. Получить настройки одного узлаhere

  • useMasterSlaveServers - для мастера с подчиненными узлами. Получить настройки главного-подчиненного узлаhere

  • useSentinelServers - для сторожевых узлов. Получить настройки сторожевого узлаhere

  • useClusterServers - для кластерных узлов. Получить настройки кластерного узлаhere

  • useReplicatedServers - для реплицированных узлов. Получить настройки реплицированного узлаhere

3.2. Конфигурация файла

ФайлыRedisson can load configurations from external JSON or YAML:

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

МетодfromJSON объектаConfig может загружать конфигурации из строки, файла, входного потока или URL.

Вот пример конфигурации в файлеsingleNodeConfig.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
}

Вот соответствующий файл конфигурации YAML:

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

Мы можем настроить другие конфигурации Redis из файла аналогичным образом, используя параметры, характерные для этой конфигурации. Для справки, вот их форматы файлов JSON и YAML:

  • Один узел -format

  • Мастер с подчиненными узлами -format

  • Сторожевые узлы -format

  • Кластерные узлы -format

  • Реплицированные узлы -format

Чтобы сохранить конфигурацию Java в формате JSON или YAML, мы можем использовать методыtoJSON илиtoYAML объектаConfig:

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

Теперь, когда мы знаем, как настроить Redisson, давайте посмотрим, как Redisson выполняет операции.

4. операция

Redisson supports synchronous, asynchronous and reactive interfaces. Операции над этимиinterfaces are thread-safe.

Все сущности (объекты, коллекции, блокировки и службы), сгенерированныеRedissonClient, имеют синхронные и асинхронные методы. Synchronous methods bear asynchronous variants. Эти методы обычно имеют одинаковые имена методов их синхронных вариантов, добавленных с помощью «Async». Давайте посмотрим на синхронный метод объектаRAtomicLong:

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

Асинхронный вариант синхронного методаcompareAndSet будет:

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

Асинхронный вариант метода возвращает объектRFuture. Мы можем установить слушателей на этот объект, чтобы получить результат, когда он станет доступным:

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

Чтобы сгенерировать реактивные объекты, нам нужно будет использоватьRedissonReactiveClient: `++`

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

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

Этот метод возвращает реактивные объекты на основе стандартаReactive Streams для Java 9.

Давайте рассмотрим некоторые из распределенных объектов, предоставляемых Redisson.

5. Объекты

Отдельный экземплярRedisson object is serialized and stored in any of the available Redis nodes backing Redisson. Эти объекты могут быть распределены в кластере по нескольким узлам и могут быть доступны одному приложению или нескольким приложениям / серверам.

Эти распределенные объекты следуют спецификациямjava.util.concurrent.atomic package.They support lock-free, thread-safe and atomic operations on objects stored in Redis. Согласованность данных между приложениями / серверами обеспечивается, поскольку значения не обновляются, пока другое приложение читает объект.

Объекты Redisson связаны с ключами Redis. Мы можем управлять этими ключами через интерфейсRKeys. Мы получаем доступ к нашим объектам Redisson, используя эти ключи.

Мы можем получить все ключи:

RKeys keys = client.getKeys();

Мы можем извлечь все имена ключей в виде повторяемых наборов строк:

Iterable allKeys = keys.getKeys();

Мы можем получить ключи, соответствующие шаблону:

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

Интерфейс RKeys также позволяет удалять ключи, удалять ключи по шаблону и другие полезные операции на основе ключей, которые мы могли бы использовать для управления нашими ключами и объектами.

Распределенные объекты, предоставляемые Redisson, включают в себя:

  • ObjectHolder

  • BinaryStreamHolder

  • Геопространственный держатель

  • BitSet

  • AtomicLong

  • AtomicDouble

  • Тема

  • BloomFilter

  • HyperLogLog

Давайте посмотрим на три из этих объектов:ObjectHolder, AtomicLong, иTopic..

5.1. Держатель объекта

Представленный классомRBucket, этот объект может содержать любой тип объекта. Этот объект имеет максимальный размер 512 МБ:

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

ОбъектRBucket может выполнять атомарные операции, такие какcompareAndSet andgetAndSet, над объектами, которые он содержит.

5.2. AtomicLong

Представленный классомRAtomicLong, этот объект очень похож на классjava.util.concurrent.atomic.AtomicLong и представляет значениеlong, которое может обновляться атомарно:

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

5.3. Тема

ОбъектTopic поддерживает механизм «публикации и подписки» Redis. Чтобы прослушать опубликованные сообщения:

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

ВышеTopic зарегистрирован для прослушивания сообщений из «примера» канала. Затем мы добавляем слушателя в тему для обработки входящих сообщений с этого канала. Мы можем добавить несколько слушателей на канал.

Опубликуем сообщения на «примерном» канале:

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

Это может быть опубликовано из другого приложения или сервера. ОбъектCustomMessage будет получен слушателем и обработан, как определено в методеonMessage.

Мы можем узнать больше о других объектах Redissonhere.

6. Коллекции

Мы работаем с коллекциями Redisson так же, как с объектами.

Распределенные коллекции, предоставляемые Redisson, включают в себя:

  • Map

  • Multimap

  • Set

  • SortedSet

  • ScoredSortedSet

  • LexSortedSet

  • List

  • Очередь

  • Deque

  • BlockingQueue

  • BoundedBlockingQueue

  • BlockingDeque

  • BlockingFairQueue

  • DelayedQueue

  • PriorityQueue

  • PriorityDeque

Давайте посмотрим на три из этих коллекций:Map, Set, иList..

6.1. Mapс

Карты на основе Redisson реализуют интерфейсыjava.util.concurrent.ConcurrentMap иjava.util.Map. Redisson имеет четыре реализации карт. ЭтоRMap,RMapCache,RLocalCachedMap иRClusteredMap.

Давайте создадим карту с Redisson:

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

RMapCache поддерживает удаление записи из карты. RLocalCachedMap позволяет локальное кэширование записей карты.. RClusteredMap позволяет разделять данные из одной карты между главными узлами кластера Redis.

Мы можем узнать больше о картах Redissonhere.

6.2. Setс

Set на основе Redisson реализует интерфейсjava.util.Set.

Redisson имеет три реализацииSet,RSet,RSetCache иRClusteredSet с аналогичной функциональностью, что и их аналоги карты.

Давайте создадимSet с помощью Redisson:

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

Мы можем узнать больше о наборах Redissonhere.

6.3. Listс

Lists на основе Redisson реализует интерфейсjava.util.List.

Давайте создадимList с помощью Redisson:

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

Мы можем узнать больше о других коллекциях Redissonhere.

7. Замки и синхронизаторы

distributed locks allow for thread synchronizationRedisson в приложениях / серверах. Список блокировок и синхронизаторов Redisson включает:

  • Lock

  • FairLock

  • MultiLock

  • ReadWriteLock

  • семафор

  • РазрешитьЭкспирируемыйСемафора

  • CountDownLatch

Давайте посмотрим наLock иMultiLock.

7.1. Lock

RedissonLock реализует интерфейсjava.util.concurrent.locks.Lock.

Давайте реализуем блокировку, представленную классомRLock:

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

7.2. MultiLock

RedissonRedissonMultiLock группирует несколько объектовRLock и обрабатывает их как одну блокировку:

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();

Мы можем узнать больше о других блокировкахhere.

8. Сервисы

Redisson предоставляет 4 вида распределенных сервисов. Это:Remote Service,Live Object Service,Executor Service иScheduled Executor Service. Давайте посмотрим на удаленную службу и службу живых объектов.

8.1. Удаленное обслуживание

Эта услуга предоставляетJava remote method invocation facilitated by Redis. Удаленная служба Redisson состоит из серверной части (рабочий экземпляр) и клиентской реализации. Реализация на стороне сервера выполняет удаленный метод, вызываемый клиентом. Вызовы из удаленной службы могут быть синхронными или асинхронными.

На стороне сервера регистрируется интерфейс для удаленного вызова:

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

remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);

Клиентская сторона вызывает метод зарегистрированного удаленного интерфейса:

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

List entries = ledgerService.getEntries(10);

Мы можем узнать больше об удаленных сервисахhere.

8.2. Служба живых объектов

Живые объекты Redisson расширяют концепцию стандартных объектов Java, к которым можно получить доступ только с одной JVM, доenhanced Java objects that could be shared between different JVMs in different machines. Это достигается путем сопоставления полей объекта с хешем Redis. Это отображение выполняется через прокси-класс, созданный во время выполнения. Получатели и установщики полей отображаются в команды Redis hget / hset.

Живые объекты Redisson поддерживают доступ к атомарным полям в результате однопоточной природы Redis.

Создать живой объект очень просто:

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

    // getters and setters...
}

Мы аннотируем наш класс@REntity и уникальное или идентифицирующее поле с помощью@RId. Как только мы это сделаем, мы можем использовать наш Live Object в нашем приложении:

RLiveObjectService service = client.getLiveObjectService();

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

ledger = service.persist(ledger);

Мы создаем наш Live Object как стандартные объекты Java, используя ключевое словоnew. Затем мы используем экземплярRLiveObjectService, чтобы сохранить объект в Redis, используя его методpersist.

Если объект ранее был сохранен в Redis, мы можем получить объект:

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

Мы используемRLiveObjectService, чтобы получить наш Live Object, используя поле, помеченное@RId.

Мы можем узнать больше о Redisson Live Objectshere.

Мы также можем узнать больше о других сервисах Redissonhere.

9. Pipelining

Redisson поддерживает конвейерную обработку. Multiple operations can be batched as a single atomic operation. Этому способствует классRBatch. Перед выполнением несколько команд объединяются с экземпляром объектаRBatch:

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

List result = batch.execute();

10. Scripting

Redisson поддерживает скрипты 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. Низкоуровневый клиент

Возможно, мы захотим выполнить операции Redis, которые еще не поддерживаются 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();

Низкоуровневый клиент также поддерживает асинхронные операции.

12. Заключение

В этой статье демонстрируется Redisson и некоторые функции, которые делают его идеальным для разработки распределенных приложений. Мы исследовали его распределенные объекты, коллекции, замки и сервисы. Мы также изучили некоторые другие его функции, такие как конвейерная обработка, создание сценариев и его низкоуровневый клиент.

Redisson also provides integration with other frameworks, такие как JCache API, Spring Cache, Hibernate Cache и Spring Sessions. Мы можем узнать больше о его интеграции с другими фреймворкамиhere.

Вы можете найти образцы кода вGitHub project.