Several application scenarios of Redis in micro service architecture

  • 2021-07-24 11:00:08
  • OfStack

This paper introduces three scenarios in which Redis is used as Pub/Sub asynchronous communication, cache or master database and configuration server in SpringCloud.

Redis can be widely used in microservice architecture. It may be one of the few popular software solutions that your application leverages in many different ways. It can act as a master database, cache, or message broker as required. Although it is also a key/value store, we can use it as a configuration server or a discovery server in a microservices architecture. Although it is usually defined as an in-memory data structure, we can also run it in persistent mode.

Here I'll show you some examples of microservices built on top of the Redis and Spring Boot and Spring Cloud frameworks. These applications will use Redis Pub/Sub asynchronous communication, Redis as the cache or master database, and Redis as the configuration server.

Redis as Configuration Server

If you have built a microservice using Spring Cloud, you may have some experience with Spring Cloud Config. It is responsible for providing distributed configuration mode for microservices.

Unfortunately, Spring Cloud Config does not support Redis as a back-end repository for attribute sources. This is why I decided to fork off the Spring Cloud Config project and implement this functionality.

I hope my implementation will soon be included in the official version of Spring Cloud, but for now, you can run it using my fork repo. How do we use it? It's quite simple. Let's have a look.

The current SNAPSHOT version 2.2. 0. BUILD-SNAPSHOT of Spring Boot is the same as our version for Spring Cloud Config. When building Spring Cloud Config Server, we only need to include these two dependencies, as shown below.


<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>config-service</artifactId>
<groupId>pl.piomin.services</groupId>
<version>1.0-SNAPSHOT</version>
<dependencies>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
    <version>2.2.0.BUILD-SNAPSHOT</version>
  </dependency>
</dependencies>

By default, Spring Cloud Config Server uses the Git repository backend. We need to activate the redis configuration file to force it to use Redis as the backend. If your Redis instance is listening on an address other than localhost: 6379, you need to override the automatically configured connection settings with the spring. redis. * property. This is our bootstrap. yml file.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100

The application main class should be annotated @ EnableConfigServer:


@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {
  public static void main(String[] args) {
    new SpringApplicationBuilder(ConfigApplication.class).run(args);
  }
}

Before running the application, we need to start the Redis instance. This is the command to run it as an Docker container and expose it on port 6379.


$ docker run -d --name redis -p 6379:6379 redis

Each application must be configured in the key {spring. application. name} or {spring. application. name}-${spring. profiles. active [n]}. We must create a hash using the key corresponding to the configuration property name.

Our sample application driver-management uses three configuration properties: server. port to set the HTTP listening port, spring. redis. host to change the default Redis address that serves as the message broker and database, and sample. topic. name to set the name of the topic for asynchronous communication between our microservices. This is the structure of the Redis hash we created for driver-management using RDBTools visualization.

Run HGETALL in Redis CLI and return:


>> HGETALL driver-management
{
  "server.port": "8100",
   "sample.topic.name": "trips",
   "spring.redis.host": "192.168.99.100"
}

After setting the key values in Redis and running Spring Cloud Config Server using the redis configuration file, we need to enable distributed configuration functionality on the client side. To do this, we only need to include spring-cloud-starter-config dependencies on pom.xml for each microservice.


<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

Use the latest stable Spring Cloud:


<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>Greenwich.SR1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

The name of the application is spring. application. name obtained from properties at startup, so we need to provide the following bootstrap. yml file.


spring:
 application:
  name: driver-management

Redis as Message Broker

Now we can continue to use the second use case of Redis-message broker in the microservice-based architecture. We will implement a typical asynchronous system.

Microservices trip-management send notifications to Redis Pub/Sub after creating a new trip and completing the current trip. Notifications are received by driver-management subscribing to a specific channel.

Our application is very simple. We only need to add the following dependencies to provide REST API and integrate with Redis Pub/Sub.


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

We should register bean with the channel channel name and publisher. TripPublisher is responsible for sending messages to the target topic.


@Configuration
public class TripConfiguration {
  @Autowired
    RedisTemplate<?, ?> redisTemplate;
  @Bean
    TripPublisher redisPublisher() {
    return new TripPublisher(redisTemplate, topic());
  }
  @Bean
    ChannelTopic topic() {
    return new ChannelTopic("trips");
  }
}

TripPublisher uses RedisTemplate to send messages to the topic. Before sending, it uses Jackson2JsonRedisSerializer to convert each message from the object to an JSON string.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
0

We have implemented the logic on the publisher side. Now, we can continue to accept the code in consumption beforehand.

We have two microservices, driver-management and passenger-management, which listen to notifications sent by trip-management microservices. We need to define RedisMessageListenerContainerbean and set up the message listener implementation class.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
1

The class responsible for handling incoming notifications needs to implement the MessageListener interface. After receiving the message, DriverSubscriber deserializes it from JSON to an object and changes the state of the driver.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
2

Redis as the primary database

Although the primary purpose of using Redis is to cache in memory or as a key/value store, it can also act as the primary database for an application. In this case, it is worthwhile to run Redis in persistent mode.


$ docker run -d --name redis -p 6379:6379 redis redis-server --appendonly yes

Entities are stored in Redis using a hash hash operation and an mmap structure. Each entity requires 1 hash key and id.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
4

Fortunately, Spring Data Redis provides a well-known repository pattern for Redis integration. To enable it, we should configure the class or main class using the @ EnableRedisRepositories annotation. When using the Spring repository pattern, we don't have to build any queries for Redis ourselves.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
5

With the Spring Data repository, we don't have to build any Redis queries, just follow the name method under the conventions of Spring Data. For the purposes of our example, we can use the default method implemented in Spring Data. This is the declaration of the repository interface driver-management.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
6

Don't forget to enable the Spring Data repository by using the @ EnableRedisRepositories annotated main application class or configuration class.


spring:
 application:
  name: config-service
 profiles:
  active: redis
 redis:
  host: 192.168.99.100
7

Conclusion

As I mentioned in the foreword, Redis has various use cases in the microservice architecture. I just showed you how to use it with Spring Cloud and Spring Data1 to provide configuration servers, message brokers, and databases. Redis is usually thought of as a cached store, but I hope you'll change your mind after reading this article.


Related articles: