欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用@Cacheable注解Redis時(shí)Redis宕機(jī)或其他原因連不上繼續(xù)調(diào)用原方法的解決方案

 更新時(shí)間:2025年05月22日 11:42:25   作者:牛肉胡辣湯  
在Spring Boot應(yīng)用中,我們經(jīng)常使用??@Cacheable??注解來(lái)緩存數(shù)據(jù),以提高應(yīng)用的性能,本文將探討如何在Redis不可用時(shí),讓??@Cacheable??注解繼續(xù)調(diào)用原方法,確保服務(wù)的可用性和穩(wěn)定性,感興趣的朋友一起看看吧

@Cacheable注解Redis時(shí),Redis宕機(jī)或其他原因連不上,繼續(xù)調(diào)用原方法的解決方案

在Spring Boot應(yīng)用中,我們經(jīng)常使用??@Cacheable??注解來(lái)緩存數(shù)據(jù),以提高應(yīng)用的性能。當(dāng)選擇Redis作為緩存存儲(chǔ)時(shí),如果Redis服務(wù)因某種原因不可用(如宕機(jī)、網(wǎng)絡(luò)問(wèn)題等),默認(rèn)情況下,??@Cacheable??注解會(huì)拋出異常,導(dǎo)致整個(gè)請(qǐng)求失敗。本文將探討如何在Redis不可用時(shí),讓??@Cacheable??注解繼續(xù)調(diào)用原方法,確保服務(wù)的可用性和穩(wěn)定性。

1. 問(wèn)題背景

1.1 ??@Cacheable??注解的基本使用

??@Cacheable??是Spring框架提供的一個(gè)注解,用于標(biāo)識(shí)一個(gè)方法的結(jié)果需要被緩存。當(dāng)該方法被調(diào)用時(shí),Spring會(huì)先檢查緩存中是否存在對(duì)應(yīng)的數(shù)據(jù),如果存在,則直接返回緩存中的數(shù)據(jù);如果不存在,則執(zhí)行方法并將結(jié)果存入緩存。

1.2 Redis宕機(jī)的影響

當(dāng)Redis服務(wù)宕機(jī)或網(wǎng)絡(luò)連接出現(xiàn)問(wèn)題時(shí),??@Cacheable??注解嘗試訪(fǎng)問(wèn)Redis時(shí)會(huì)拋出異常,例如??org.springframework.data.redis.RedisConnectionFailureException??。這會(huì)導(dǎo)致方法調(diào)用失敗,影響用戶(hù)體驗(yàn)和系統(tǒng)穩(wěn)定性。

2. 解決方案

2.1 使用自定義異常處理器

可以通過(guò)自定義異常處理器來(lái)捕獲Redis連接異常,并在捕獲到異常時(shí)繼續(xù)調(diào)用原方法。具體步驟如下:

2.1.1 創(chuàng)建自定義異常處理器

首先,創(chuàng)建一個(gè)自定義異常處理器類(lèi),用于處理Redis連接異常。

import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheErrorHandler;
public class CustomCacheErrorHandler implements CacheErrorHandler {
    @Override
    public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
        // 處理讀取緩存時(shí)的異常
        System.out.println("Cache get error: " + exception.getMessage());
    }
    @Override
    public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
        // 處理寫(xiě)入緩存時(shí)的異常
        System.out.println("Cache put error: " + exception.getMessage());
    }
    @Override
    public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
        // 處理清除緩存時(shí)的異常
        System.out.println("Cache evict error: " + exception.getMessage());
    }
    @Override
    public void handleCacheClearError(RuntimeException exception, Cache cache) {
        // 處理清空緩存時(shí)的異常
        System.out.println("Cache clear error: " + exception.getMessage());
    }
}

2.1.2 配置自定義異常處理器

在Spring Boot配置文件中,配置自定義的異常處理器。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.annotation.EnableCaching;
@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CustomCacheErrorHandler customCacheErrorHandler() {
        return new CustomCacheErrorHandler();
    }
}

2.2 使用??@Cacheable??的??unless??屬性

??@Cacheable??注解提供了一個(gè)??unless??屬性,可以在緩存操作成功后決定是否將結(jié)果存入緩存。雖然這個(gè)屬性不能直接解決Redis宕機(jī)的問(wèn)題,但可以結(jié)合其他邏輯來(lái)實(shí)現(xiàn)類(lèi)似的效果。

2.3 使用??@Cacheable?的??cache-null-values??屬性

設(shè)置??@Cacheable??注解的??cache-null-values??屬性為??false??,這樣即使Redis不可用,也不會(huì)將??null??值存入緩存。

@Cacheable(value = "myCache", cacheNullValues = false)
public User getUserById(Long id) {
    return userRepository.findById(id).orElse(null);
}

2.4 使用降級(jí)策略

在Redis不可用時(shí),可以采用降級(jí)策略,例如從數(shù)據(jù)庫(kù)中直接獲取數(shù)據(jù)。這可以通過(guò)自定義的緩存管理器來(lái)實(shí)現(xiàn)。

import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Optional;
@Configuration
public class CustomCacheManager {
    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("myCache") {
            @Override
            public Cache getCache(String name) {
                Cache cache = super.getCache(name);
                if (cache == null) {
                    // 如果Redis不可用,使用本地緩存
                    cache = new ConcurrentMapCache(name);
                }
                return cache;
            }
        };
    }
}

我們可以在Redis不可用時(shí),確保??@Cacheable???注解繼續(xù)調(diào)用原方法,從而提高系統(tǒng)的穩(wěn)定性和可用性。具體實(shí)現(xiàn)方式包括自定義異常處理器、使用??unless???和??cache-null-values??屬性、以及降級(jí)策略。在使用Spring框架結(jié)合Redis實(shí)現(xiàn)緩存功能時(shí),如果Redis宕機(jī)或由于其他原因?qū)е逻B接不上Redis,可以通過(guò)配置??CacheManager??來(lái)實(shí)現(xiàn)當(dāng)緩存不可用時(shí)自動(dòng)回退到原始方法的調(diào)用。這樣可以保證系統(tǒng)的可用性和穩(wěn)定性。

以下是一個(gè)具體的實(shí)現(xiàn)示例:

添加依賴(lài):首先確保你的項(xiàng)目中已經(jīng)添加了Spring Boot和Redis的相關(guān)依賴(lài)。

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

配置Redis連接:在application.properties中配置Redis連接信息。

spring.redis.host=localhost
spring.redis.port=6379

自定義CacheManager:創(chuàng)建一個(gè)自定義的CacheManager,在其中處理Redis不可用的情況。

import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
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.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1)) // 設(shè)置默認(rèn)過(guò)期時(shí)間
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
        cacheConfigurations.put("myCache", config);
        return new FallbackRedisCacheManager(redisConnectionFactory, config, cacheConfigurations);
    }
}

實(shí)現(xiàn)FallbackRedisCacheManager:創(chuàng)建一個(gè)自定義的CacheManager,在Redis不可用時(shí)回退到內(nèi)存緩存。

import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFailureException;
import java.util.Arrays;
import java.util.List;
public class FallbackRedisCacheManager extends RedisCacheManager {
    private final CacheManager fallbackCacheManager;
    public FallbackRedisCacheManager(RedisConnectionFactory connectionFactory, RedisCacheConfiguration defaultCacheConfiguration, Map<String, RedisCacheConfiguration> initialCacheConfigurations) {
        super(connectionFactory, defaultCacheConfiguration, initialCacheConfigurations);
        SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
        simpleCacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("fallbackCache")));
        simpleCacheManager.afterPropertiesSet();
        this.fallbackCacheManager = simpleCacheManager;
    }
    @Override
    public Cache getCache(String name) {
        try {
            return super.getCache(name);
        } catch (RedisConnectionFailureException e) {
            return fallbackCacheManager.getCache(name);
        }
    }
}

使用@Cacheable注解:在需要緩存的方法上使用@Cacheable注解。

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
    @Cacheable(value = "myCache", key = "#id")
    public String getData(String id) {
        // 模擬數(shù)據(jù)獲取過(guò)程
        System.out.println("Fetching data from database for ID: " + id);
        return "Data for ID: " + id;
    }
}

通過(guò)上述配置,當(dāng)Redis不可用時(shí),??FallbackRedisCacheManager??會(huì)捕獲到??RedisConnectionFailureException??異常,并回退到內(nèi)存緩存。這樣可以確保即使Redis宕機(jī),系統(tǒng)仍然能夠正常運(yùn)行并返回?cái)?shù)據(jù)。在使用Spring Cache與Redis結(jié)合時(shí),如果Redis出現(xiàn)宕機(jī)或連接問(wèn)題,可以通過(guò)配置??CacheManager??和實(shí)現(xiàn)自定義的??CacheErrorHandler??來(lái)確保即使緩存不可用,業(yè)務(wù)邏輯也能正常運(yùn)行。以下是一個(gè)詳細(xì)的解決方案示例:

1. 添加依賴(lài)

首先,確保你的項(xiàng)目中已經(jīng)添加了Spring Boot Starter Cache和Spring Boot Starter Data Redis的依賴(lài):

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

2. 配置RedisTemplate

配置??RedisTemplate??以使用JSON序列化方式存儲(chǔ)對(duì)象:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
}

3. 配置CacheManager

配置??CacheManager??以使用Redis作為緩存存儲(chǔ):

import org.springframework.cache.CacheManager;
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.RedisConnectionFactory;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(60)) // 設(shè)置緩存過(guò)期時(shí)間為60分鐘
                .disableCachingNullValues();
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .build();
    }
}

4. 實(shí)現(xiàn)自定義的CacheErrorHandler

實(shí)現(xiàn)自定義的??CacheErrorHandler??,以便在緩存操作失敗時(shí)進(jìn)行處理:

import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueException;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.CacheErrorHandler;
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    @Override
    public CacheErrorHandler errorHandler() {
        return new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
                // 處理緩存讀取錯(cuò)誤
                System.out.println("Cache get error: " + exception.getMessage());
            }
            @Override
            public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
                // 處理緩存寫(xiě)入錯(cuò)誤
                System.out.println("Cache put error: " + exception.getMessage());
            }
            @Override
            public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
                // 處理緩存刪除錯(cuò)誤
                System.out.println("Cache evict error: " + exception.getMessage());
            }
            @Override
            public void handleCacheClearError(RuntimeException exception, Cache cache) {
                // 處理緩存清除錯(cuò)誤
                System.out.println("Cache clear error: " + exception.getMessage());
            }
        };
    }
}

5. 使用@Cacheable注解

在需要緩存的方法上使用??@Cacheable??注解:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    @Cacheable(value = "users", key = "#userId")
    public User getUserById(String userId) {
        // 模擬從數(shù)據(jù)庫(kù)獲取用戶(hù)信息
        System.out.println("Fetching user from database: " + userId);
        return new User(userId, "John Doe");
    }
}

6. 測(cè)試

你可以通過(guò)模擬Redis宕機(jī)或斷開(kāi)連接來(lái)測(cè)試上述配置是否生效。例如,可以臨時(shí)關(guān)閉Redis服務(wù),然后調(diào)用??getUserById??方法,查看是否能夠正常返回?cái)?shù)據(jù)。

總結(jié)

通過(guò)以上配置,當(dāng)Redis不可用時(shí),??CacheErrorHandler??會(huì)捕獲到緩存操作的異常,并打印錯(cuò)誤信息。同時(shí),由于??@Cacheable??注解的默認(rèn)行為是當(dāng)緩存不可用時(shí)直接調(diào)用原方法,因此業(yè)務(wù)邏輯不會(huì)受到影響。這樣可以確保系統(tǒng)的高可用性和穩(wěn)定性。

到此這篇關(guān)于使用@Cacheable注解Redis時(shí)Redis宕機(jī)或其他原因連不上繼續(xù)調(diào)用原方法的解決方案的文章就介紹到這了,更多相關(guān)@Cacheable注解 Redis宕機(jī)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于Java的對(duì)象序列化流和反序列化流詳細(xì)解讀

    關(guān)于Java的對(duì)象序列化流和反序列化流詳細(xì)解讀

    這篇文章主要介紹了關(guān)于Java的對(duì)象序列化流和反序列化流,對(duì)象序列化:就是將對(duì)象保存到磁盤(pán)中,或者在網(wǎng)絡(luò)中傳輸對(duì)象,反之,自己序列還可以從文件中讀取回來(lái),重構(gòu)對(duì)象,對(duì)它進(jìn)行反序列化,需要的朋友可以參考下
    2023-05-05
  • JAVA使用Ip2region獲取IP定位信息的操作方法

    JAVA使用Ip2region獲取IP定位信息的操作方法

    這篇文章主要介紹了JAVA使用Ip2region獲取IP定位信息,ip2region?-?是國(guó)內(nèi)開(kāi)發(fā)者開(kāi)發(fā)的離線(xiàn)IP地址定位庫(kù),針對(duì)國(guó)內(nèi)IP效果較好,國(guó)外的部分IP只能顯示國(guó)家,對(duì)java獲取IP定位信息操作過(guò)程感興趣的朋友一起看看吧
    2022-05-05
  • 基于springboot實(shí)現(xiàn)redis分布式鎖的方法

    基于springboot實(shí)現(xiàn)redis分布式鎖的方法

    這篇文章主要介紹了基于springboot實(shí)現(xiàn)redis分布式鎖的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java 查找字符串所在的位置代碼

    java 查找字符串所在的位置代碼

    這篇文章主要介紹了java 查找字符串所在的位置代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • java裁剪圖片并保存的示例分享

    java裁剪圖片并保存的示例分享

    在這篇文章中我們將學(xué)習(xí)如何用Java 對(duì)圖像進(jìn)行剪裁并將剪裁出來(lái)的部分單獨(dú)保存到文件中
    2014-01-01
  • VerifyCodeServlet(一次性驗(yàn)證碼)

    VerifyCodeServlet(一次性驗(yàn)證碼)

    這篇文章主要介紹了VerifyCodeServlet一次性驗(yàn)證碼的使用方法
    2017-05-05
  • 詳解Java并發(fā)包中線(xiàn)程池ThreadPoolExecutor

    詳解Java并發(fā)包中線(xiàn)程池ThreadPoolExecutor

    ThreadPoolExecutor是Java語(yǔ)言對(duì)于線(xiàn)程池的實(shí)現(xiàn)。線(xiàn)程池技術(shù)使線(xiàn)程在使用完畢后不回收而是重復(fù)利用。如果線(xiàn)程能夠復(fù)用,那么我們就可以使用固定數(shù)量的線(xiàn)程來(lái)解決并發(fā)問(wèn)題,這樣一來(lái)不僅節(jié)約了系統(tǒng)資源,而且也會(huì)減少線(xiàn)程上下文切換的開(kāi)銷(xiāo)
    2021-06-06
  • Java中的圖形界面重繪方式

    Java中的圖形界面重繪方式

    這篇文章主要介紹了Java中的圖形界面重繪方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Java實(shí)現(xiàn)鼠標(biāo)隨機(jī)移動(dòng)效果的示例代碼

    Java實(shí)現(xiàn)鼠標(biāo)隨機(jī)移動(dòng)效果的示例代碼

    有的時(shí)候我們需要鼠標(biāo)一直滑動(dòng)的情況,為了節(jié)省時(shí)間,本文用Java語(yǔ)言寫(xiě)了一個(gè)腳本,可以實(shí)現(xiàn)鼠標(biāo)隨機(jī)移動(dòng),感興趣的小伙伴可以了解一下
    2022-05-05
  • Java實(shí)現(xiàn)在Word模板指定位置添加二維碼并生成?PDF

    Java實(shí)現(xiàn)在Word模板指定位置添加二維碼并生成?PDF

    在實(shí)際業(yè)務(wù)場(chǎng)景中,我們常常需要在?Word?模板的指定位置貼上二維碼,然后將其轉(zhuǎn)換為?PDF?電子憑證文檔,下面我們就來(lái)看看具體實(shí)現(xiàn)方法吧
    2025-02-02

最新評(píng)論