Creating and Configuring Azure Redis Cache and use in Spring Boot Application

Creating and Configuring Azure Redis Cache and use in Spring Boot Application

Prerequisite

  • Azure Subscription
  • Java Development Kit (JDK)
  • Apache Maven

Introduction: Azure Cache for Redis

In today’s fast pacing world, the need for high performing, efficient and user-friendly application is highly desired. To achieve these, the software’s architectures have become more complex and the data it has to handle also becomes huge which led to challenge the performance of an application.

Finding a smarter way to counter the performance issues becomes critical. Depends on the scenario one way to address this issue can be, reducing data retrieval and processing time. This is where caching comes to the rescue.

Cache

Caching is the process of storing data or files in a temporary location (Cache) so that it can be accessed faster by the application when needed instead of making an expensive data retrieval from the application’s storage layer.

There are few types of caches available such as,

  • In-memory caching
  • Database caching
  • Web caching
  • CDN caching

Azure Cache for Redis

Azure Cache for Redis provides an in-memory cache based on Redis software. Data in in-memory caching commonly uses key-value pair so each data can be identified with a unique key identifier. Redis improves the performance of an application which heavily uses the backend data.

As per Microsoft documentation, the Azure Cache for Redis offers both the Redis open-source (OSS Redis) and a commercial product from Redis Labs (Redis Enterprise) as a managed service. It provides secure and dedicated Redis server instances and full Redis API compatibility. The service is operated by Microsoft, hosted on Azure, and usable by any application within or outside of Azure.

Azure Cache for Redis can be used as a distributed data or content cache, a session store, a message broker, and more. It can be deployed as a standalone. Or, it can be deployed along with other Azure database services, such as Azure SQL or Cosmos DB.

Create and Configure Azure Cache for Redis in Portal

Step1: Login to Azure portal https://portal.azure.com and search for Azure Cache for Redis in search resource section

1.png

Step2: Click on Create to create a new instance of Redis cache.

2.jpg

Step3: In the Basics tab, provide the details such as

  • Subscription

  • Resource Group: create new or select existing resource group

  • DNS Name: Host name for the Redis cache instance

  • Location: Location desired to create Redis cache instance

  • Cache type: Basic (only for Dev/Test), Standard, Premium, Enterprise types are available. In this article, Standard C1 with 1GB cache is used

3.jpg

Step4: The Network and Advanced tab is left to default. If the user wants to create Redis cache with non-TLS port, then in Advanced tab, select the Non-TLS Port option.

4.jpg

Step5: Once all values are provided, click on Review + Create button to review the creation and once the validation is passed, click Create button to create the resource

5.jpg

The deployment will take some time and once it is completed, navigate to Azure Cache for Redis resource. The newly created instance can be viewed

6.jpg

Step6: Make a note of the host name and port of the instance by navigating to Overview section.

7.jpg

Step7: From the Access Keys which is under the Settings section, get the Primary key for this instance

8.jpg

Note: In the later part of this article, the hostname, port and access key will be used to make the Spring Boot and Azure cache for Redis integration

Create Spring Boot application to use with Azure Cache for Redis

Step8: Navigate to https://start.spring.io/ to create a demo application. Add Spring Web dependency and generate the application. The application will gets downloaded as a zip file to your local

9.jpg

Step9: Once downloaded, extract and open the project in IDE of choice.

Step10: Add the Jedis dependency to the pom.xml. The Jedis is one of the Redis Java Client

<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
            <type>jar</type>
            <scope>compile</scope>
</dependency>

Step11: In application.properties file, enter the hostname, port, ssl, access key of the created Azure Redis cache instance

# Specify the DNS URI of your Redis cache.
spring.redis.host=demo-labs.redis.cache.windows.net
# Specify the access key for your Redis cache.
spring.redis.password=<access_key>
# Specify that you want to use SSL.
spring.redis.ssl=true
# Specify the SSL port for your Redis cache.
spring.redis.port=6380

Step12: Creating a Jedis client in configuration class

@Configuration
public class ConfigJedis {
    @Value("${spring.redis.host}")
    private String hostName;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.ssl}")
    private boolean ssl;
    @Value("${spring.redis.password}")
    private String accessKey;

    @Bean
    public Jedis config() {
        JedisShardInfo jedisInfo = new JedisShardInfo(hostName, port, ssl);
        jedisInfo.setPassword(accessKey);
        Jedis jedis = new Jedis(jedisInfo);
        return jedis;
    }
}

Step13: The Spring Boot service exposes three endpoints as mentioned below

Endpoint.1 ) Add new product information to Azure Redis Cache

Endpoint: /addProductCatalogue

Method: POST

Description: A POST API which accepts list of products in a request body. This endpoint is used to insert product name and price of the respective product in Redis cache as a key value pair.

<productName>:<productPrice>

Once the insertion to cache is successful, a success message is returned with 200 OK response. If not, relevant exception is returned as a response.

@PostMapping("/addProductCatalogue")
public String addProductCatalogue(@RequestBody List<ProductCatalogue> productList) {
        return demoService.addProductCatalogue(productList);
}

Endpoint.2 ) Get total price of the products from Azure Cache for Redis

Endpoint: /getPurchaseAmount

Method: GET

Description: This GET API is used to fetch the total price of the list of products sent via request body. This endpoint retrieves the price of the individual product by accessing Redis cache and sums it and returns as a response. If the product requested is not available in the cache storage, then HTTP 404 error code is returned with relevant message as a response

@GetMapping("/getPurchaseAmount")
public String getPurchaseAmount(@RequestBody List<String> products) {
        return demoService.getPurchaseAmount(products);
}

Endpoint.3 ) Delete product information from Azure Cache for Redis

Endpoint: /deleteproducts

Method: DELETE

Description: DELETE API to delete the products which is sent via request body from Azure cache for Redis. Once the product information is deleted, success message is returned as a response

@DeleteMapping("/deleteProducts")
public String deleteProducts(@RequestBody List<String> products) {
        return demoService.deleteProducts(products);
}

Step14: Creating a service component to implement the above mentioned functionality

@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    Jedis config;
    private static final String ADD_PRODUCT_RESPONSE_MESSAGE = "Successfully Added Products to Cache";
    private static final String GET_PURCHASE_AMOUNT_RESPONSE_MESSAGE = "Total Purchase amount ";
    private static final String DELETE_PRODUCT_RESPONSE_MESSAGE = "Successfully deleted products ";
    private static final String PRODUCT_MISSING_RESPONSE_MESSAGE = "Product information is not available in cache storage for product ";

   //Method to add Product info
    public String addProductCatalogue(List<ProductCatalogue> productList) {
        try {
            // Setting the incoming catalogue items to cache
            for (ProductCatalogue product : productList) {
                config.set(product.getItemName(), product.getPrice());
            }
        } catch (JedisException jException) {
            return jException.getMessage();
        } catch (Exception exception) {
            return exception.getMessage();
        }
        return ADD_PRODUCT_RESPONSE_MESSAGE;
    }

   //Method to fetch the total price of the supplied products
   public String getPurchaseAmount(List<String> products) {
        int totalPurchaseAmount=0;
        try {
            for(String product: products) {
                if(config.exists(product)) {
                    totalPurchaseAmount+= Integer.parseInt(config.get(product));
                }else {
                    return PRODUCT_MISSING_RESPONSE_MESSAGE+product;
                }
            }
        }catch (JedisException jException) {
            return jException.getMessage();
        } catch (Exception exception) {
            return exception.getMessage();
        }
        return GET_PURCHASE_AMOUNT_RESPONSE_MESSAGE+totalPurchaseAmount;
    }

   //Method to delete product info
   public String deleteProducts(List<String> products) {
        try {
            for(String product: products) {
                config.del(product);
            }
        }catch (JedisException jException) {
            return jException.getMessage();
        } catch (Exception exception) {
            return exception.getMessage();
        }
        return DELETE_PRODUCT_RESPONSE_MESSAGE+products;
    }
}

Here the Jedis client is used to set product information to the cache storage, get the value of the product, delete the product from the cache storage using config.get(Key), config.set(Key), config.del(Key)

Step15: Product Catalogue Entity Class

@Component
public class ProductCatalogue {

    private String itemName;
    private String price;

    //Getters...
    //Setters...
}

Test the Integration

To test the Spring Boot service and Azure cache for Redis integration, POSTMAN tool is used.

Step16: Run the service locally. The service is running in localhost:8080

Step17: In POSTMAN, three endpoints for POST, GET, DELETE is tested

  • POST request to add the XYZ_TV and ABC_Refrigerator to the cache storage

10.jpg

  • GET request to fetch the total price of XYZ_TV and ABC_Refrigerator products

11.jpg

  • DELETE request to delete the XYZ_TV product from cache product

12.jpg

References