1. Введение
В этом руководстве мы узнаем, как настраивать и реализовывать операции Redis с помощью ReactiveRedisTemplate Spring Data.
Мы рассмотрим основные способы использования ReactiveRedisTemplate
, например, как хранить и извлекать объекты в Redis. И мы рассмотрим, как выполнять команды Redis с помощью ReactiveRedisConnection
.
Чтобы охватить основы, ознакомьтесь с нашим введением в Spring Data Redis .
2. Настройка
Чтобы использовать ReactiveRedisTemplate
в нашем коде, сначала нам нужно добавить зависимость для модуля Spring Boot Redis Reactive:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
3. Конфигурация
Затем нам нужно
установить соединение с нашим сервером Redis. Нам не нужно добавлять какой-либо код для настройки, если мы хотим подключиться к серверу Redis по адресу localhost:6379
.
Но если бы наш сервер был удаленным или находился на другом порту, мы могли бы указать имя хоста и порт в конструкторе LettuceConnectionFactory
:
@Bean
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
4. Список операций
Списки Redis — это списки строк, отсортированные по порядку вставки. Мы можем добавлять или удалять элементы из списка, нажимая или выталкивая их слева или справа.
4.1. Строковый шаблон
Для работы со списками нам понадобится экземпляр ReactiveStringRedisTemplate
для получения ссылки на RedisListOperations
:
@Autowired
private ReactiveStringRedisTemplate redisTemplate;
private ReactiveListOperations<String, String> reactiveListOps;
@Before
public void setup() {
reactiveListOps = redisTemplate.opsForList();
}
4.2. LPUSH и LPOP
Теперь, когда у нас есть экземпляр ReactiveListOperations,
давайте выполним операцию LPUSH для списка с demo_list
в качестве идентификатора списка.
После этого мы выполним LPOP в списке, а затем проверим, что элемент выскочил:
@Test
public void givenListAndValues_whenLeftPushAndLeftPop_thenLeftPushAndLeftPop() {
Mono<Long> lPush = reactiveListOps.leftPushAll(LIST_NAME, "first", "second")
.log("Pushed");
StepVerifier.create(lPush)
.expectNext(2L)
.verifyComplete();
Mono<String> lPop = reactiveListOps.leftPop(LIST_NAME)
.log("Popped");
StepVerifier.create(lPop)
.expectNext("second")
.verifyComplete();
}
Обратите внимание, что при тестировании реактивных компонентов мы можем использовать StepVerifier
для блокировки выполнения задачи.
5. Операции со значениями
Мы можем также захотеть использовать пользовательские объекты, а не только строки.
Итак, давайте проделаем аналогичные операции с объектом Employee
, чтобы продемонстрировать наши операции с POJO:
public class Employee implements Serializable {
private String id;
private String name;
private String department;
// ... getters and setters
// ... hashCode and equals
}
5.1. Шаблон сотрудника
Нам нужно создать второй экземпляр ReactiveRedisTemplate.
Мы по-прежнему будем использовать String
для нашего ключа, но на этот раз значением будет Employee
:
@Bean
public ReactiveRedisTemplate<String, Employee> reactiveRedisTemplate(
ReactiveRedisConnectionFactory factory) {
StringRedisSerializer keySerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Employee> valueSerializer =
new Jackson2JsonRedisSerializer<>(Employee.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, Employee> builder =
RedisSerializationContext.newSerializationContext(keySerializer);
RedisSerializationContext<String, Employee> context =
builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
Чтобы правильно сериализовать пользовательский объект, нам нужно указать Spring, как это сделать. Здесь мы сказали шаблону использовать библиотеку Jackson, настроив Jackson2JsonRedisSerializer
для значения . Поскольку ключ — это просто строка, мы можем использовать для этого StringRedisSerializer
.
Затем мы используем этот контекст сериализации и нашу фабрику соединений для создания шаблона, как и раньше.
Далее мы создадим экземпляр ReactiveValueOperations
так же, как мы делали ранее с ReactiveListOperations
:
@Autowired
private ReactiveRedisTemplate<String, Employee> redisTemplate;
private ReactiveValueOperations<String, Employee> reactiveValueOps;
@Before
public void setup() {
reactiveValueOps = redisTemplate.opsForValue();
}
5.2. Сохранение и извлечение операций
Теперь, когда у нас есть экземпляр ReactiveValueOperations,
давайте используем его для хранения экземпляра Employee
:
@Test
public void givenEmployee_whenSet_thenSet() {
Mono<Boolean> result = reactiveValueOps.set("123",
new Employee("123", "Bill", "Accounts"));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
}
И тогда мы можем получить тот же объект от Redis:
@Test
public void givenEmployeeId_whenGet_thenReturnsEmployee() {
Mono<Employee> fetchedEmployee = reactiveValueOps.get("123");
StepVerifier.create(fetchedEmployee)
.expectNext(new Employee("123", "Bill", "Accounts"))
.verifyComplete();
}
5.3. Операции со сроком действия
Мы часто хотим поместить в кеш значения, срок действия которых истечет естественным образом , и мы можем сделать это с помощью той же операции установки :
@Test
public void givenEmployee_whenSetWithExpiry_thenSetsWithExpiryTime()
throws InterruptedException {
Mono<Boolean> result = reactiveValueOps.set("129",
new Employee("129", "John", "Programming"),
Duration.ofSeconds(1));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
Thread.sleep(2000L);
Mono<Employee> fetchedEmployee = reactiveValueOps.get("129");
StepVerifier.create(fetchedEmployee)
.expectNextCount(0L)
.verifyComplete();
}
Обратите внимание, что этот тест выполняет некоторую собственную блокировку, чтобы дождаться истечения срока действия ключа кэша.
6. Команды Redis
Команды Redis — это в основном методы, которые клиент Redis может вызывать на сервере. И Redis поддерживает десятки команд, некоторые из которых мы уже видели, например, LPUSH и LPOP.
API операций
— это абстракция более высокого уровня вокруг набора команд Redis.
Однако, если мы хотим более непосредственно использовать примитивы команд Redis, Spring Data Redis Reactive также предоставляет нам Commands
API.
Итак, давайте взглянем на команды String и Key через призму Commands
API.
6.1. Строковые и ключевые команды
Для выполнения командных операций Redis мы получим экземпляры ReactiveKeyCommands
и ReactiveStringCommands.
Мы можем получить их оба из нашего экземпляра ReactiveRedisConnectionFactory :
@Bean
public ReactiveKeyCommands keyCommands(ReactiveRedisConnectionFactory
reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection().keyCommands();
}
@Bean
public ReactiveStringCommands stringCommands(ReactiveRedisConnectionFactory
reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection().stringCommands();
}
6.2. Установить и получить операции
Мы можем использовать ReactiveStringCommands
для хранения нескольких ключей с помощью одного вызова, в основном вызывая команду SET несколько раз .
И затем мы можем получить эти ключи через ReactiveKeyCommands
, вызвав команду KEYS :
@Test
public void givenFluxOfKeys_whenPerformOperations_thenPerformOperations() {
Flux<SetCommand> keys = Flux.just("key1", "key2", "key3", "key4");
.map(String::getBytes)
.map(ByteBuffer::wrap)
.map(key -> SetCommand.set(key).value(key));
StepVerifier.create(stringCommands.set(keys))
.expectNextCount(4L)
.verifyComplete();
Mono<Long> keyCount = keyCommands.keys(ByteBuffer.wrap("key*".getBytes()))
.flatMapMany(Flux::fromIterable)
.count();
StepVerifier.create(keyCount)
.expectNext(4L)
.verifyComplete();
}
Обратите внимание, что, как было сказано ранее, этот API гораздо более низкоуровневый. Например, вместо того, чтобы иметь дело с высокоуровневыми объектами, мы отправляем поток байтов, используя ByteBuffer
. Кроме того, мы используем больше примитивов Redis, таких как SET и SCAN.
Наконец, String и Key Commands — это всего лишь два из многих командных интерфейсов, которые Spring Data Redis предоставляет реактивно.
7. Заключение
В этом руководстве мы рассмотрели основы использования шаблона Spring Data Reactive Redis и различные способы его интеграции с нашим приложением.
Полный исходный код примеров доступен на GitHub .