When was the last time you needed to submit or extract some data from a website, and it took an eternity?
Caching is a well-known concept, and it has existed for a very long time.
Unfortunately, many applications fail to extract their full potential. With such a system within your application, your response times can become significantly faster, without much work.
Your clients will thank you later!
Today, I will explain to you, what and how through the following topics:
- Cache Definition
- What the heck is Redis (Caching System)?
- How can I integrate it with Spring Boot?
- Example Time!
# Cache Definition
Caching is the process of storing data that was once fetched so that in the future, a second request can be served without needing to fetch the resource again
Operations like database queries are heavy in time-space and resource allocation, and having a caching system helps speed up the serving of these processes.
# What a heck is Redis (Caching System)?
The Redis stands for Remote Dictionary Service. This framework is a simple key-value based distributed database built in-memory.
The official webpage describes it as:
Redis is an open-source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams.
The main reason why Redis stands out so much is two major advantages it has, persistence and additional datatypes.
- Persistence — Due to its abstraction, it can be managed as a legitimate database, where for instance, after a restart, all data remains intact, something that doesn’t happen in some other caching systems (e.g Memcached);
- Datatypes — You are not limited to a simple type, where other frameworks, such as Memcached narrow you to one;
We use Redis mainly with the goal of:
- Improve performance — By caching the values, we are significantly improving the performance of several key services. We tend to cache the data that’s heavily used. Doing so will reduce the cost of reading the database, which as previously mentioned, is very high;
- Increase services resiliency — If for some reason some services stop working, we have the opportunity to return the cached data. Cached data is better than no data at all.
Ohhh, and I almost forgot, it’s amazingly fast:
To give a quick idea, Redis comes along with the Redis-CLI (Command Line Interface), and with it, you can easily interact with Redis like:
Storing a value:
127.0.0.1:6379> set example hello
Fetching a cached value:
127.0.0.1:6379> get example
# How can I integrate it with Spring Boot?
As you probably already noticed from my previous articles, Spring Boot can easily be integrated with a lot of tools, and the process is fast and easy, most of the time.
Redis is no exception! The below diagram shows how Spring Boot will be interconnected with Redis:
- The client requests a given resource that will require a resource from service B.
- Before contacting the service B, we will check whether the resource is already present in the cache, and if so, we can immediately return it, and save a lot of time.
- If no value is found in the cache, we will then fetch it from service B.
# Example Time!
In the example below, we will have two services communicating with each other, service A (Client Service) with service B (Address Service).
In the current use case, we will have a user requesting a client address to the service A, and having in mind that the current service is mainly responsible for client domain information, we will need to request another service, the correspondent domain data, the address.
We will be using on service A a simple POJO that will match the returned data from the service B:
- The first step is to add the Redis dependencies to your Maven or Gradle
- Spring-boot-starter-data-redis (Redis itself)
- Commons-pool2 (Redis helpers)
- Jedis (Used to communicate with the Redis server)
2. Add the connection to your Redis server through the Jedis factory definition and the template we will be using.
- ClientConfigProperties.java is a simple properties class. We need it to extract the configured host and port from our application.yml. You can easily create one through here;
- The examples use Lombok. It removes some boilerplate code like setters, getters, constructors, and so on. Just by defining the annotation @RequiredArgsConstructor, all final fields will get automatically autowired.
3. Define your RedisRepository interface that will be used by your service:
4. Below we will add the correspondent repository implementation, but before, we must understand the following:
Every time an operation is called, we must also send the current context. In this case, that context is “address”.
Every time an operation is called, the current context must pass through it, in the current case, “address”.
5. After defining our repository implementation, the only thing missing is using it. In the place where the service B invocation occurs, we will add the following checks:
- Check if the requested address is already cached, if so, we can immediately return it and save a lot of time to the end-user;
- If not, we will request the required address from service B;
- If we get a valid response, we will then save it into our Redis cache;
Other alternatives to Redis exist, like ArangoDB, Azure Cosmos DB, Amazon DynamoDB, etc. All of them with awesome features and their drawbacks.
I hope these examples enlighten you a bit more about how Redis works behind the scenes.
Feel free to ask any questions. Thanks for your time!
Using Correlation IDs With Spring Cloud Gateway and Eureka
In a microservice architecture, sometimes we want to ensure behaviors across all services, such as: request tracking…