最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

1. 問題背景

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

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

1.2 Redis宕機(jī)的影響

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

2. 解決方案

2.1 使用自定義異常處理器

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

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

首先,創(chuàng)建一個自定義異常處理器類,用于處理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) {
        // 處理讀取緩存時的異常
        System.out.println("Cache get error: " + exception.getMessage());
    }
    @Override
    public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
        // 處理寫入緩存時的異常
        System.out.println("Cache put error: " + exception.getMessage());
    }
    @Override
    public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
        // 處理清除緩存時的異常
        System.out.println("Cache evict error: " + exception.getMessage());
    }
    @Override
    public void handleCacheClearError(RuntimeException exception, Cache cache) {
        // 處理清空緩存時的異常
        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??注解提供了一個??unless??屬性,可以在緩存操作成功后決定是否將結(jié)果存入緩存。雖然這個屬性不能直接解決Redis宕機(jī)的問題,但可以結(jié)合其他邏輯來實(shí)現(xiàn)類似的效果。

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

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

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

2.4 使用降級策略

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

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

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

<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)建一個自定義的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)過期時間
                .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)建一個自定義的CacheManager,在Redis不可用時回退到內(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ù)獲取過程
        System.out.println("Fetching data from database for ID: " + id);
        return "Data for ID: " + id;
    }
}

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

1. 添加依賴

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

<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序列化方式存儲對象:

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作為緩存存儲:

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è)置緩存過期時間為60分鐘
                .disableCachingNullValues();
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .build();
    }
}

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

實(shí)現(xiàn)自定義的??CacheErrorHandler??,以便在緩存操作失敗時進(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) {
                // 處理緩存讀取錯誤
                System.out.println("Cache get error: " + exception.getMessage());
            }
            @Override
            public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
                // 處理緩存寫入錯誤
                System.out.println("Cache put error: " + exception.getMessage());
            }
            @Override
            public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
                // 處理緩存刪除錯誤
                System.out.println("Cache evict error: " + exception.getMessage());
            }
            @Override
            public void handleCacheClearError(RuntimeException exception, Cache cache) {
                // 處理緩存清除錯誤
                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ù)庫獲取用戶信息
        System.out.println("Fetching user from database: " + userId);
        return new User(userId, "John Doe");
    }
}

6. 測試

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

總結(jié)

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

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

相關(guān)文章

  • Spring?Bean獲取方式的實(shí)例化方式詳解

    Spring?Bean獲取方式的實(shí)例化方式詳解

    工作中需要對一個原本加載屬性文件的工具類修改成對數(shù)據(jù)庫的操作當(dāng)然,ado層已經(jīng)寫好,但是需要從Spring中獲取bean,然而,工具類并沒有交給Spring來管理,所以需要通過方法獲取所需要的bean。于是整理了Spring獲取bean的幾種方法
    2023-03-03
  • Java實(shí)現(xiàn)跳躍表(skiplist)的簡單實(shí)例

    Java實(shí)現(xiàn)跳躍表(skiplist)的簡單實(shí)例

    這篇文章主要介紹了Java編程中跳躍表的概念和實(shí)現(xiàn)原理,并簡要敘述了它的結(jié)構(gòu),具有一定參考價值,需要的朋友可以了解下。
    2017-09-09
  • Intellij 下 mybatis 插件 MyBatisCodeHelperPro破解步驟詳解

    Intellij 下 mybatis 插件 MyBatisCodeHelperPro破解步驟詳解

    這篇文章主要介紹了Intellij 下 mybatis 插件 MyBatisCodeHelperPro破解步驟,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • JAVA實(shí)現(xiàn)Token自動續(xù)期機(jī)制的示例代碼

    JAVA實(shí)現(xiàn)Token自動續(xù)期機(jī)制的示例代碼

    本文主要介紹了JAVA實(shí)現(xiàn)Token自動續(xù)期機(jī)制的示例代碼,通過動態(tài)調(diào)整會話生命周期平衡安全性與用戶體驗(yàn),解決固定有效期Token帶來的風(fēng)險(xiǎn)與不便,感興趣的可以了解一下
    2025-09-09
  • Java執(zhí)行hadoop的基本操作實(shí)例代碼

    Java執(zhí)行hadoop的基本操作實(shí)例代碼

    這篇文章主要介紹了Java執(zhí)行hadoop的基本操作實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Struts2通過自定義標(biāo)簽實(shí)現(xiàn)權(quán)限控制的方法

    Struts2通過自定義標(biāo)簽實(shí)現(xiàn)權(quán)限控制的方法

    這篇文章主要介紹了Struts2通過自定義標(biāo)簽實(shí)現(xiàn)權(quán)限控制的方法,介紹了定義Struts2的自定義標(biāo)簽的三個步驟以及詳細(xì)解釋,需要的朋友可以參考下。
    2017-09-09
  • IDEA中Maven Dependencies出現(xiàn)紅色波浪線的原因及解決方法

    IDEA中Maven Dependencies出現(xiàn)紅色波浪線的原因及解決方法

    在使用 IntelliJ IDEA 開發(fā) Java 項(xiàng)目時,尤其是基于 Maven 的項(xiàng)目,您可能會遇到 Maven Dependencies 中出現(xiàn)紅色波浪線的問題,這通常意味著項(xiàng)目的依賴無法被正確解析或下載,本文將詳細(xì)介紹該問題的原因及解決方法,并附有圖文說明,需要的朋友可以參考下
    2025-06-06
  • win10和win7下java開發(fā)環(huán)境配置教程

    win10和win7下java開發(fā)環(huán)境配置教程

    這篇文章主要為大家詳細(xì)介紹了win7下Java開發(fā)環(huán)境配置教程,win10下Java開發(fā)環(huán)境配置,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • SpringMVC框架REST架構(gòu)體系原理分析

    SpringMVC框架REST架構(gòu)體系原理分析

    REST:Representational State Transfer,資源表現(xiàn)層狀態(tài)轉(zhuǎn)換,是目前&#12112;較主流的&#12032;種互聯(lián)網(wǎng)軟件架構(gòu),它結(jié)構(gòu)清晰、標(biāo)準(zhǔn)規(guī)范、易于理解、便于擴(kuò)展
    2021-09-09
  • java實(shí)現(xiàn)多數(shù)據(jù)源切換方式

    java實(shí)現(xiàn)多數(shù)據(jù)源切換方式

    本文介紹實(shí)現(xiàn)多數(shù)據(jù)源切換的四步方法:導(dǎo)入依賴、配置文件、啟動類注解、使用@DS標(biāo)記mapper和服務(wù)層,通過注解實(shí)現(xiàn)數(shù)據(jù)源動態(tài)切換,適用于實(shí)際開發(fā)中的多數(shù)據(jù)源場景
    2025-08-08

最新評論

巩义市| 万源市| 万山特区| 黑龙江省| 阳西县| 千阳县| 元阳县| 新晃| 西充县| 万州区| 义马市| 那曲县| 绥阳县| 遂川县| 舟曲县| 衡南县| 额尔古纳市| 沅陵县| 凤山市| 临沭县| 塘沽区| 板桥市| 德兴市| 龙川县| 扶余县| 宁津县| 涞水县| 长海县| 成都市| 永定县| 建德市| 永济市| 黄龙县| 云南省| 江西省| 曲松县| 甘南县| 隆林| 祥云县| 和顺县| 大石桥市|