1. Обзор
Radisson-это клиент Redis для Java . В этой статье мы рассмотрим некоторые из его функций и продемонстрируем, как он может облегчить создание распределенных бизнес-приложений.
Radisson представляет собой сетку данных в памяти , которая предлагает распределенные объекты Java и службы, поддерживаемые Redis . Его распределенная модель данных в памяти позволяет совместно использовать доменные объекты и службы между приложениями и серверами.
В этой статье мы рассмотрим, как настроить Radisson, поймем, как он работает, и изучим некоторые объекты и услуги Radisson.
2. Зависимости Maven
Давайте начнем с импорта Radisson в наш проект, добавив раздел ниже к вашему pom.xml:
org.redisson redisson 3.13.1
Последнюю версию этой зависимости можно найти здесь .
3. Конфигурация
Прежде чем мы начнем, мы должны убедиться, что у нас установлена и запущена последняя версия Redis. Если у вас нет Redis и вы используете Linux или Macintosh, вы можете следовать информации здесь , чтобы настроить его. Если вы являетесь пользователем Windows, вы можете настроить Redis, используя этот неофициальный порт .
Нам нужно настроить Radisson для подключения к Redis. Radisson поддерживает подключения к следующим конфигурациям Redis:
- Один узел
- Ведущий с подчиненными узлами
- Сторожевые узлы
- Кластеризованные узлы
- Реплицированные узлы
Radisson поддерживает кластер Amazon Web Services (AWS) ElastiCache и кэш Azure Redis для кластеризованных и реплицированных узлов.
Давайте подключимся к экземпляру Redis с одним узлом. Этот экземпляр работает локально на порту по умолчанию 6379:
RedissonClient client = Redisson.create();
Вы можете передать различные конфигурации в метод Radisson объекта create . Это может быть конфигурация для подключения к другому порту или, возможно, для подключения к кластеру Redis. Эта конфигурация может быть в коде Java или загружена из внешнего файла конфигурации .
3.1. Конфигурация Java
Давайте настроим его в коде Java:
Config config = new Config(); config.useSingleServer() .setAddress("redis://127.0.0.1:6379"); RedissonClient client = Redisson.create(config);
Мы указываем конфигурации в экземпляре Config object , а затем передаем его методу create . Выше мы указали Radisson, что хотим подключиться к экземпляру Redis с одним узлом. Для этого мы использовали метод Config объекта use Single Server . Это возвращает ссылку на объект Single Server Config .
Объект Single Server Config имеет настройки, которые Radisson использует для подключения к экземпляру Redis с одним узлом. Здесь мы используем его метод setAddress для настройки параметра address . Это устанавливает адрес узла, к которому мы подключаемся. Некоторые другие настройки включают в себя повторные попытки , тайм-аут подключения и Имя клиента . Эти параметры настраиваются с помощью соответствующих методов настройки.
Мы можем настроить Radisson для различных конфигураций Redis аналогичным образом, используя следующие методы объекта Config :
- useSingleServer – для экземпляра одного узла. Получить настройки одного узла здесь
- useMasterSlaveServers – для ведущего с подчиненными узлами. Получить настройки ведущего-ведомого узла здесь
- useSentinelServers – для узлов sentinel. Получить настройки узла sentinel здесь
- useClusterServers – для кластеризованных узлов. Получить настройки кластеризованного узла здесь
- useReplicatedServers – для реплицированных узлов. Получить настройки реплицированного узла здесь
3.2. Конфигурация файла
Вы можете загружать конфигурации из внешних файлов JSON или YAML :
Config config = Config.fromJSON(new File("singleNodeConfig.json")); RedissonClient client = Redisson.create(config);
Метод Config объекта FromJSON может загружать конфигурации из строки, файла, входного потока или URL-адреса.
Вот пример конфигурации в файле single Node Config.json :
{ "singleServerConfig": { "idleConnectionTimeout": 10000, "connectTimeout": 10000, "timeout": 3000, "retryAttempts": 3, "retryInterval": 1500, "password": 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 }
Вот соответствующий файл конфигурации YAML:
singleServerConfig: idleConnectionTimeout: 10000 connectTimeout: 10000 timeout: 3000 retryAttempts: 3 retryInterval: 1500 password: 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: !{}
Мы можем настроить другие конфигурации Redis из файла аналогичным образом, используя параметры, характерные для этой конфигурации. Для справки, вот их форматы файлов JSON и YAML:
- Один узел – формат
- Ведущий с подчиненными узлами – формат
- Сторожевые узлы – формат
- Кластеризованные узлы – формат
- Реплицированные узлы – формат
Чтобы сохранить конфигурацию 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();
Теперь, когда мы знаем, как настроить Radisson, давайте посмотрим, как Radisson выполняет операции.
4. Эксплуатация
Radisson поддерживает синхронные, асинхронные и реактивные интерфейсы . Операции над этими интерфейсами являются потокобезопасными .
Все сущности (объекты, коллекции, блокировки и службы), созданные клиентом Radisson , имеют синхронные и асинхронные методы. Синхронные методы имеют асинхронные варианты . Эти методы обычно имеют одно и то же имя метода их синхронных вариантов, добавленное с “асинхронным”. Давайте рассмотрим синхронный метод объекта Atomiclong :
RedissonClient client = Redisson.create(); RAtomicLong myLong = client.getAtomicLong('myLong');
Асинхронным вариантом метода synchronous compareAndSet будет:
RFutureisSet = myLong.compareAndSetAsync(6, 27);
Асинхронный вариант метода возвращает объект Future . Мы можем установить прослушиватели на этот объект, чтобы получить результат, когда он станет доступным:
isSet.handle((result, exception) -> { // handle the result or exception here. });
Чтобы генерировать реактивные объекты, нам нужно будет использовать клиент Radisson Reactive :
RedissonReactiveClient client = Redisson.createReactive(); RAtomicLongReactive myLong = client.getAtomicLong("myLong"); PublisherisSetPublisher = myLong.compareAndSet(5, 28);
Этот метод возвращает реактивные объекты на основе стандарта Reactive Streams для Java 9.
Давайте рассмотрим некоторые из распределенных объектов, предоставляемых Radisson.
5. Объекты
Отдельный экземпляр объекта Radisson сериализуется и хранится в любом из доступных узлов Redis, поддерживающих Redisson . Эти объекты могут быть распределены в кластере по нескольким узлам и доступны одному приложению или нескольким приложениям/серверам.
Эти распределенные объекты следуют спецификациям из пакета java.util.concurrent.atomic. Они поддерживают операции без блокировки, потокобезопасные и атомарные операции с объектами, хранящимися в Redis . Согласованность данных между приложениями/серверами обеспечивается, поскольку значения не обновляются, пока другое приложение считывает объект.
Объекты Radisson привязаны к ключам Redis. Мы можем управлять этими ключами через интерфейс Keys . А затем мы получаем доступ к нашим объектам Radisson с помощью этих ключей.
Есть несколько вариантов, которые мы можем использовать для получения ключей Redis.
Мы можем просто получить все ключи:
RKeys keys = client.getKeys();
В качестве альтернативы мы можем извлечь только имена:
IterableallKeys = keys.getKeys();
И, наконец, мы можем получить ключи, соответствующие шаблону:
IterablekeysByPattern = keys.getKeysByPattern('key*')
Интерфейс ключей также позволяет удалять ключи, удалять ключи по шаблону и другие полезные операции на основе ключей, которые мы могли бы использовать для управления нашими ключами и объектами.
Распределенные объекты, предоставляемые Radisson, включают в себя:
- Держатель объекта
- Держатель BinaryStream
- Геопространственный держатель
- Набор битов
- АтомикЛонг
- Атомный Двойник
- Тема
- Фильтр Блума
- HyperLogLog
Давайте рассмотрим три из этих объектов: Держатель объекта, AtomicLong, и Тема.
5.1. Держатель объекта
Представленный классом Bucket , этот объект может содержать объекты любого типа. Этот объект имеет максимальный размер 512 МБ:
RBucketbucket = client.getBucket("ledger"); bucket.set(new Ledger()); Ledger ledger = bucket.get();
Объект Bucket может выполнять атомарные операции, такие как compareAndSet и get и Set на объектах, которые он содержит.
5.2. Атомная длина
Представленный классом Atomiclong , этот объект очень похож на java.util.concurrent.atomic.Класс AtomicLong и представляет значение long , которое может быть обновлено атомарно:
RAtomicLong atomicLong = client.getAtomicLong("myAtomicLong"); atomicLong.set(5); atomicLong.incrementAndGet();
5.3. Тема
Объект Topic поддерживает механизм “публикации и подписки” Redis. Прослушивание опубликованных сообщений:
RTopic subscribeTopic = client.getTopic("baeldung"); subscribeTopic.addListener(CustomMessage.class, (channel, customMessage) -> future.complete(customMessage.getMessage()));
Выше Тема зарегистрирована для прослушивания сообщений с канала “baeldung”. Затем мы добавляем прослушиватель в тему для обработки входящих сообщений с этого канала. Мы можем добавить несколько слушателей на канал.
Давайте опубликуем сообщения на канале “baeldung”:
RTopic publishTopic = client.getTopic("baeldung"); long clientsReceivedMessage = publishTopic.publish(new CustomMessage("This is a message"));
Это может быть опубликовано из другого приложения или сервера. Объект Custom Message будет получен слушателем и обработан, как определено в методе onMessage .
Мы можем узнать больше о других объектах Radisson здесь .
6. Коллекции
Мы обрабатываем коллекции Radisson таким же образом, как и объекты.
Распределенные коллекции, предоставляемые Radisson, включают в себя:
- Карта
- Multimap
- Набор
- Сортированный набор
- Забил сортированный набор
- Лекс Сортированный набор
- Список
- Очередь
- Деке
- BlockingQueue
- BoundedBlockingQueue
- BlockingDeque
- Блокировка Справедливой Очереди
- Отложенная очередь
- Приоритетная очередь
- Приоритетный Дек
Давайте рассмотрим три из этих коллекций: Map, Set, и List.
6.1. Карта
Карты на основе Radisson реализуют java.util.concurrent.ConcurrentMap и java.util.Карта Интерфейсы. Radisson имеет четыре реализации карт. Это RMap , RMapCache , RLocalCachedMap и R Кластерная карта .
Давайте создадим карту с Radisson:
RMapmap = client.getMap("ledger"); Ledger newLedger = map.put("123", new Ledger());map
Кэш карт поддерживает выселение записей на карте. RLocalCachedMap позволяет локальное кэширование записей карты . Кластерная карта позволяет распределять данные с одной карты по основным узлам кластера Redis.
Мы можем узнать больше о картах Radisson здесь .
6.2. Набор
/| Set реализует java.util.Установить интерфейс.
Radisson имеет три реализации Set , Reset , Reset Cache и R Clustered Set с аналогичной функциональностью , как и их аналоги на карте.
Давайте создадим Набор с помощью Radisson:
RSetledgerSet = client.getSet("ledgerSet"); ledgerSet.add(new Ledger());
Мы можем узнать больше о наборах Radisson здесь .
6.3. Список
На основе/| Списков реализуйте java.util.Список интерфейс.
Давайте создадим Список с помощью Radisson:
RListledgerList = client.getList("ledgerList"); ledgerList.add(new Ledger());
Мы можем узнать больше о других коллекциях Radisson здесь .
7. Замки и синхронизаторы
Распределенные блокировки Radisson позволяют синхронизировать потоки между приложениями/серверами. Список блокировок и синхронизаторов Radisson включает в себя:
- Замок
- Шлюз
- Мультиблок
- ReadWriteLock
- Семафор
- PermitExpirableSemaphore
- Обратный отсчет
Давайте взглянем на Lock и Multi Lock.
7.1. Блокировка
/| Lock реализует java.util.concurrent.замки.Блокировка интерфейс.
Давайте реализуем блокировку, представленную классом RLock :
RLock lock = client.getLock("lock"); lock.lock(); // perform some long operations... lock.unlock();
7.2. Мультиблокировка
Radisson RedissonMultiLock группирует несколько 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();
Мы можем узнать больше о других замках здесь .
8. Услуги
Radisson предоставляет 4 типа распределенных услуг. Это: Удаленная служба , Служба живых объектов , ExecutorService и ScheduledExecutorService . Давайте рассмотрим Удаленную службу и Службу живых объектов.
8.1. Удаленное обслуживание
Эта служба обеспечивает Удаленный вызов метода Java, облегченный Redis . Удаленная служба Radisson состоит из серверной (рабочий экземпляр) и клиентской реализации. Реализация на стороне сервера выполняет удаленный метод, вызываемый клиентом. Вызовы из удаленной службы могут быть синхронными или асинхронными.
Серверная сторона регистрирует интерфейс для удаленного вызова:
RRemoteService remoteService = client.getRemoteService(); LedgerServiceImpl ledgerServiceImpl = new LedgerServiceImpl(); remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);
Клиентская сторона вызывает метод зарегистрированного удаленного интерфейса:
RRemoteService remoteService = client.getRemoteService(); LedgerServiceInterface ledgerService = remoteService.get(LedgerServiceInterface.class); Listentries = ledgerService.getEntries(10);
Мы можем узнать больше об удаленных сервисах здесь .
8.2. Обслуживание живых объектов
Живые объекты Redisson расширяют концепцию стандартных объектов Java, доступ к которым возможен только из одной JVM, до расширенных объектов Java, которые могут совместно использоваться различными JVM на разных машинах . Это достигается путем сопоставления полей объекта с хэшем Redis. Это сопоставление выполняется через прокси-класс, созданный во время выполнения. Геттеры и сеттеры полей сопоставляются командам Redis hget/h set.
Живые объекты Radisson поддерживают доступ к атомарным полям в результате однопоточной природы Redis.
Создание живого объекта очень просто:
@REntity public class LedgerLiveObject { @RId private String name; // getters and setters... }
Мы аннотируем наш класс с помощью @Entity и уникального или идентифицирующего поля с помощью @RId . Как только мы это сделаем, мы сможем использовать наш живой объект в нашем приложении:
RLiveObjectService service = client.getLiveObjectService(); LedgerLiveObject ledger = new LedgerLiveObject(); ledger.setName("ledger1"); ledger = service.persist(ledger);
Мы создаем наш живой объект, как стандартные объекты Java, используя ключевое слово new . Затем мы используем экземпляр R Live Object Service , чтобы сохранить объект в Redis, используя его метод persist .
Если объект ранее сохранялся в Redis, мы можем получить его:
LedgerLiveObject returnLedger = service.get(LedgerLiveObject.class, "ledger1");
Мы используем сервис R Live Object , чтобы получить наш живой объект, используя поле с аннотацией @RId .
Здесь мы можем узнать больше об объектах Radisson Live, а другие услуги Radisson описаны здесь.
9. Конвейеризация
Radisson поддерживает конвейерную обработку. Несколько операций могут быть объединены в одну атомарную операцию . Этому способствует класс Batch . Несколько команд объединяются с экземпляром объекта R Batch перед их выполнением:
RBatch batch = client.createBatch(); batch.getMap("ledgerMap").fastPutAsync("1", "2"); batch.getMap("ledgerMap").putAsync("2", "5"); BatchResult> batchResult = batch.execute();
10. Сценарии
Radisson поддерживает сценарии LUA. Мы можем выполнять LUA-скрипты против Redis :
client.getBucket("foo").set("bar"); String result = client.getScript().eval(Mode.READ_ONLY, "return redis.call('get', 'foo')", RScript.ReturnType.VALUE);
11. Клиент низкого Уровня
Возможно, мы захотим выполнить операции Redis, которые еще не поддерживаются Radisson. Radisson предоставляет низкоуровневый клиент, который позволяет выполнять собственные команды Redis :
RedisClientConfig redisClientConfig = new 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();
Клиент низкого уровня также поддерживает асинхронные операции.
12. Заключение
В этой статье мы продемонстрировали Radisson и некоторые функции, которые делают его идеальным для разработки распределенных приложений. Мы исследовали его распределенные объекты, коллекции, замки и сервисы. Мы также изучили некоторые другие его функции, такие как конвейеризация, сценарии и низкоуровневый клиент.
Radisson также обеспечивает интеграцию с другими фреймворками , такими как API JCache, Spring Cache, Hibernate Cache и Spring Sessions. Мы можем узнать больше о его интеграции с другими фреймворками здесь .
Примеры кода можно найти в проекте GitHub .