You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows环境下Redis缓存服务器故障时MVC应用的回退机制实现方案问询

Implementing Redis Failover Fallback to Database in Your MVC App

Absolutely! You can build a graceful fallback mechanism right into your RedisCacheService to handle Redis server failures—so when Redis goes down, your app silently switches to fetching data from the database instead of throwing errors. Here's how to adjust your existing code step by step:

Step 1: Track Redis Availability

First, add a simple flag to your service class to track whether Redis is currently available. This lets your methods quickly decide whether to use Redis or fall back:

public class RedisCacheService : IRedisCacheService 
{ 
    private readonly IConnectionMultiplexer _connectionMultiplexer; 
    private readonly IDatabase _redisCache;
    // Flag to track if Redis is operational
    private bool _isRedisAvailable = true;

    // ... rest of your constructor
}

Step 2: Update Connection Event Handlers

Use the existing connection event handlers to update the availability flag when Redis goes down or comes back up. Don’t forget to add logging here—it’s critical for debugging and monitoring:

private void _connectionMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
    _isRedisAvailable = false;
    // Log the failure details (e.g., failure type, exception message)
    // Example: _logger.LogError(e.Exception, "Redis connection failed: {FailureType}", e.FailureType);
}

private void _connectionMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
{
    _isRedisAvailable = true;
    // Log the successful restoration
    // Example: _logger.LogInformation("Redis connection restored successfully");
}

private void _connectionMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
{
    // Log any Redis error messages for visibility
    // Example: _logger.LogWarning("Redis error received: {Message}", e.Message);
}

Step 3: Add Fallback Logic to Cache Methods

Modify your cache read/write methods to check the availability flag first, and wrap Redis operations in try/catch blocks (to handle edge cases where the flag might not update immediately). If Redis is unavailable or throws an exception, skip it entirely—letting your app fall back to the database.

Here’s the updated version of your methods:

public T JsonGet<T>(RedisKey key, CommandFlags flags = CommandFlags.None)
{
    // Skip Redis if it's marked unavailable
    if (!_isRedisAvailable)
        return default;

    try
    {
        RedisValue cacheData = _redisCache.StringGet(key, flags);
        if (!cacheData.HasValue) 
            return default;

        return JsonConvert.DeserializeObject<T>(cacheData);
    }
    catch (RedisConnectionException ex)
    {
        // Mark Redis as unavailable on connection failures
        _isRedisAvailable = false;
        // Log the exception for debugging
        // Example: _logger.LogError(ex, "Redis JsonGet failed for key {Key}", key);
        return default;
    }
    catch (Exception ex)
    {
        // Log unexpected Redis errors
        // Example: _logger.LogError(ex, "Unexpected error in Redis JsonGet for key {Key}", key);
        return default;
    }
}

public RedisValue GetCacheData(RedisKey key, CommandFlags flags = CommandFlags.None)
{
    if (!_isRedisAvailable)
        return default;

    try
    {
        RedisValue cacheData = _redisCache.StringGet(key, flags);
        return cacheData.HasValue ? cacheData : default;
    }
    catch (RedisConnectionException ex)
    {
        _isRedisAvailable = false;
        // Log the exception
        return default;
    }
    catch (Exception ex)
    {
        // Log unexpected errors
        return default;
    }
}

public bool SetCacheData(RedisKey key, object value, TimeSpan? expiry = null, When when = When.Always, CommandFlags flags = CommandFlags.None)
{
    if (!_isRedisAvailable || value == null)
        return false;

    try
    {
        return _redisCache.StringSet(key, JsonConvert.SerializeObject(value), expiry, when, flags);
    }
    catch (RedisConnectionException ex)
    {
        _isRedisAvailable = false;
        // Log the exception
        return false;
    }
    catch (Exception ex)
    {
        // Log unexpected errors
        return false;
    }
}

Key Notes for Your Implementation

  • Logging is Non-Negotiable: Proper logging helps you track when Redis fails, when it recovers, and what errors occur—this is essential for maintaining your app’s reliability.
  • Cache Consistency: When Redis comes back online, your cache might be stale. You can either let it repopulate naturally as requests come in, or add a mechanism to refresh critical keys on restoration.
  • Layered Fallback: Typically, the logic to fall back to the database lives in your repository/service layer (e.g., "check cache first; if no result or cache is down, hit the database"). This implementation ensures the cache service doesn’t throw errors, making that layered logic work seamlessly.
  • StackExchange.Redis Retries: The client has built-in retry logic, but our fallback skips Redis entirely when it’s down—this prevents wasted time retrying failed connections when you know the server is unavailable.

内容的提问来源于stack exchange,提问作者nomad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:34:04