DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Enterprise AI Trend Report: Gain insights on ethical AI, MLOps, generative AI, large language models, and much more.

2024 Cloud survey: Share your insights on microservices, containers, K8s, CI/CD, and DevOps (+ enter a $750 raffle!) for our Trend Reports.

PostgreSQL: Learn about the open-source RDBMS' advanced capabilities, core components, common commands and functions, and general DBA tasks.

AI Automation Essentials. Check out the latest Refcard on all things AI automation, including model training, data security, and more.

Related

  • Quick Start: How to Use Spring Cache on Redis
  • Enhancing Performance With Amazon Elasticache Redis: In-Depth Insights Into Cluster and Non-Cluster Modes
  • That Can Not Be Tested!: Spring Cache and Retry
  • Simple Sophisticated Object Cache Service Using Azure Redis

Trending

  • Code Complexity in Practice
  • The Impact of Biometric Authentication on User Privacy and the Role of Blockchain in Preserving Secure Data
  • Spring Boot 3.2: Replace Your RestTemplate With RestClient
  • Building Safe AI: A Comprehensive Guide to Bias Mitigation, Inclusive Datasets, and Ethical Considerations
  1. DZone
  2. Data Engineering
  3. Data
  4. How to Connect Redis Sentinel With Spring

How to Connect Redis Sentinel With Spring

In this article, we see a basic example of how to connect to a “Redis Sentinel” configuration in a Spring Application. Read this tutorial to find out more.

By 
Volkan Gungor user avatar
Volkan Gungor
·
Updated Jun. 30, 21 · Tutorial
Like (5)
Save
Tweet
Share
40.6K Views

Join the DZone community and get the full member experience.

Join For Free

Image title

Redis Sentinel


In this article, I am going to make a basic example of how to connect to a “Redis Sentinel” configuration in a Spring application.

You might also enjoy the following article: Introduction to Spring Data Redis.

First of all, for Maven dependencies, “spring-boot-starter-data-redis” is needed in our pom.xml file. This library includes LettuceConnectionFactory, which we will use to connect “Redis Sentinel”.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>


We will use application.yml file for connection and cache configurations. Below there is an example of application.yml file. Under cache.config.defaultConfig there is a list of predefined cache configurations. You can map these configurations to service cache definitions which are defined under cache.appCaches.appCacheMap.

cache:
    config:
        defaultConfigs:
        -  cacheName: ONE_HOUR_CACHE         
           timeToLiveSeconds: 3600 
        -  cacheName: TEN_MINUTES_CACHE
           timeToLiveSeconds: 600

  appCaches:
    appCacheMap:
        serviceOne_cache: ONE_HOUR_CACHE
        serviceTwo_cache: TEN_MINUTES_CACHE   

spring:
  cache:
    type: redis
  redis:
    port: 6666
    password: 123pwd
    sentinel:
      master: masterredis
      nodes:
        - 10.0.0.16
        - 10.0.0.17
        - 10.0.0.18
    lettuce:
      shutdown-timeout: 200ms             


In order to read these configuration parameters easily, we will need a CacheSettingsModel and two classes annotated with ConfigurationProperties. One for the defaultConfigs and another for the appCacheMap. For Redis configs, which are under spring.redis, we will use RedisProperties class, which is included in spring-boot-starter-data-redis. You can see these classes below:

package com.example.sentinel.config.model;

public class CacheSettingsModel {
private String cacheName;
private String timeToLiveSeconds;

public final String getCacheName() {
return cacheName;
}

public final void setCacheName(String cacheName) {
this.cacheName = cacheName;
}

public final String getTimeToLiveSeconds() {
return timeToLiveSeconds;
}

public final void setTimeToLiveSeconds(String timeToLiveSeconds) {
this.timeToLiveSeconds = timeToLiveSeconds;
}
}

 

package com.example.sentinel.config;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import com.example.sentinel.config.model.CacheSettingsModel;

@Component
@ConfigurationProperties( prefix="cache.config")
public class CacheSettings {

private List<CacheSettingsModel> defaultConfigs;

public List<CacheSettingsModel> getDefaultConfigs() {
return defaultConfigs;
}

public void setDefaultConfigs(List<CacheSettingsModel> defaultConfigs) {
this.defaultConfigs = defaultConfigs;
}

public Map<String,CacheSettingsModel> getCacheConfigAsMap() {
return CollectionUtils.emptyIfNull(defaultConfigs).stream().
          collect(Collectors.toMap(CacheSettingsModel::getCacheName, c -> c));
}
}


package com.example.sentinel.config;

import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties( prefix="cache.appCaches")
public class AppCacheSettings {

private Map<String,String> appCacheMap;


public Map<String, String> getAppCacheMap() {
return appCacheMap;
}


public void setAppCacheMap(Map<String, String> appCacheMap) {
this.appCacheMap = appCacheMap;
}
}


Now, we are going to create a connection to “Redis Sentinel” with the help of those configuration classes. As I told you before, we are going to use Lettuce to connect to Redis. We are going to create a new instance of RedisSentinelConfiguration class with the help of RedisProperties class and use it in the constructor of LettuceConnectionFactory.

package com.example.sentinel.config;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

import com.example.sentinel.config.AppCacheSettings;
import com.example.sentinel.config.CacheSettings;
import com.example.sentinel.config.model.CacheSettingsModel;

@Configuration
@EnableCaching
public class CacheConfig {

    @Inject
    private CacheSettings cacheSettings;
    @Inject
    private AppCacheSettings appCacheSettings;
    @Inject
    private RedisProperties redisProperties;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {

        RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
                .master(redisProperties.getSentinel().getMaster());

        redisProperties.getSentinel().getNodes().forEach(s -> sentinelConfig.sentinel(s, Integer.valueOf(redisProperties.getPort())));
        sentinelConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));

        return new LettuceConnectionFactory(sentinelConfig);
    }

    @Bean
    public RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .disableCachingNullValues();
    }

    private RedisCacheConfiguration buildRedisCacheConfig(CacheSettingsModel cachesProperties) {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(Long.parseLong(cachesProperties.getTimeToLiveSeconds())))
                .disableCachingNullValues();
    }

    @Bean
    public RedisCacheManager cacheManager() {

        Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>();

        Map<String, CacheSettingsModel> cacheConfigMap = cacheSettings.getCacheConfigAsMap();
        Map<String, String> appCacheMap = appCacheSettings.getAppCacheMap();

        appCacheMap.forEach((key, value) -> cacheConfigs.put(key, buildRedisCacheConfig(cacheConfigMap.get(value))));

        return RedisCacheManager.builder(redisConnectionFactory())
                .cacheDefaults(cacheConfiguration())
                .withInitialCacheConfigurations(cacheConfigs)
                .transactionAware()
                .build();
    }
}


In the end, we are going to create a CacheManager bean. We are going to use RedisCacheManager.builder. With the help of AppCacheSettings and CacheSettings classes, we are going to set the initial cache configurations of cacheManager bean. If you want to enable transactional operations on caches you should set transactionAware to true (default is false). I'll just copy the definition of transactionAware from the Spring API document.

Set this to "true" to synchronize cache put/evict operations with ongoing Spring-managed transactions, performing the actual cache put/evict operation only in the after-commit phase of a successful transaction.

We are almost done. To use Redis cache in our application, we only need to put @Cacheable (org.springframework.cache.annotation.Cacheable) annotation to the services that we want to cache. As a Value parameter, you can use one of the predefined cache names under appCacheMap properties (in application.yml file) to set cache properties like timeToLive.

 @Cacheable("serviceOne_cache")
 public List<String> serviceOne(String param) {
 ...
 }


That's it. Spring will do the rest!

Further Reading

 Getting Started With Redis

Java-Distributed Caching in Redis

Redis (company) Spring Framework Cache (computing)

Opinions expressed by DZone contributors are their own.

Related

  • Quick Start: How to Use Spring Cache on Redis
  • Enhancing Performance With Amazon Elasticache Redis: In-Depth Insights Into Cluster and Non-Cluster Modes
  • That Can Not Be Tested!: Spring Cache and Retry
  • Simple Sophisticated Object Cache Service Using Azure Redis

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: