一、为什么需要分布式缓存高可用
在互联网应用中,缓存是提升性能的利器。想象一下,每次用户请求都要从数据库查询数据,数据库的压力会有多大?尤其是高并发场景下,数据库很容易成为瓶颈。而分布式缓存可以将热点数据存放在内存中,减少数据库访问,提高响应速度。
但问题来了——如果缓存挂了怎么办?比如 Redis 某个节点宕机,或者网络抖动导致缓存不可用,这时候如果没有高可用方案,系统可能会直接崩溃。所以,我们需要一套高可用的分布式缓存架构,确保即使部分节点故障,系统仍能正常运行。
二、DotNetCore 中常用的分布式缓存方案
在 .NET Core 生态中,常用的分布式缓存方案有:
- Redis(最主流,支持集群和哨兵模式)
- Memcached(简单高效,但功能较少)
- SQL Server 分布式缓存(基于数据库,适合小规模应用)
- NCache(商业方案,性能优秀)
这篇文章我们以 Redis 为例,因为它功能强大、社区活跃,并且天然支持高可用架构。
三、Redis 高可用方案选型
Redis 的高可用方案主要有两种:
Redis Sentinel(哨兵模式)
- 自动监控主从节点,主节点宕机时自动切换
- 适合中小规模应用
- 配置简单,但集群管理能力较弱
Redis Cluster(集群模式)
- 数据分片存储,支持横向扩展
- 自动故障转移,适合大规模应用
- 配置复杂,但扩展性强
我们选择 Redis Sentinel 作为示例,因为它更贴合大多数 .NET Core 应用的需求。
四、在 DotNetCore 中集成 Redis Sentinel
4.1 环境准备
假设我们已经搭建了 Redis Sentinel 环境:
- 1 个主节点(Master)
- 2 个从节点(Slave)
- 3 个哨兵节点(Sentinel)
4.2 安装必要的 NuGet 包
dotnet add package StackExchange.Redis
4.3 配置 Redis Sentinel 连接
using StackExchange.Redis;
using System;
public class RedisService
{
private static ConnectionMultiplexer _redis;
public static IDatabase GetDatabase()
{
if (_redis == null || !_redis.IsConnected)
{
// Sentinel 节点地址
var sentinelEndPoints = new[]
{
new { Host = "sentinel1", Port = 26379 },
new { Host = "sentinel2", Port = 26379 },
new { Host = "sentinel3", Port = 26379 }
};
// 配置连接
var options = new ConfigurationOptions
{
ServiceName = "mymaster", // Sentinel 监控的主节点名称
TieBreaker = "", // 禁用 TieBreaker
DefaultVersion = new Version("6.2.0"), // Redis 版本
CommandMap = CommandMap.Sentinel, // 使用 Sentinel 模式
AbortOnConnectFail = false, // 连接失败不抛出异常
AllowAdmin = true // 允许执行管理命令
};
// 添加 Sentinel 节点
foreach (var ep in sentinelEndPoints)
{
options.EndPoints.Add(ep.Host, ep.Port);
}
_redis = ConnectionMultiplexer.Connect(options);
}
return _redis.GetDatabase();
}
}
4.4 使用示例
// 写入缓存
var db = RedisService.GetDatabase();
db.StringSet("user:1001", "John Doe", TimeSpan.FromMinutes(10));
// 读取缓存
var userName = db.StringGet("user:1001");
Console.WriteLine($"User name: {userName}");
五、高可用架构的优化策略
5.1 多级缓存(本地缓存 + Redis)
如果 Redis 不可用,可以短暂降级到本地缓存:
using Microsoft.Extensions.Caching.Memory;
public class HybridCacheService
{
private readonly IDatabase _redis;
private readonly IMemoryCache _localCache;
public HybridCacheService(IDatabase redis, IMemoryCache localCache)
{
_redis = redis;
_localCache = localCache;
}
public string GetUser(string userId)
{
// 先查本地缓存
if (_localCache.TryGetValue($"user:{userId}", out string userName))
{
return userName;
}
// 本地缓存没有,查 Redis
userName = _redis.StringGet($"user:{userId}");
if (userName != null)
{
// 写入本地缓存,有效期 1 分钟
_localCache.Set($"user:{userId}", userName, TimeSpan.FromMinutes(1));
}
return userName;
}
}
5.2 缓存雪崩防护
大量缓存同时失效会导致数据库压力激增,解决方案:
// 设置随机过期时间,避免同时失效
var random = new Random();
var expiry = TimeSpan.FromMinutes(10).Add(TimeSpan.FromSeconds(random.Next(0, 60)));
db.StringSet("cache_key", "value", expiry);
六、应用场景与注意事项
6.1 适用场景
- 电商秒杀:高并发读取商品信息
- 社交网络:热点数据(如用户资料)缓存
- 实时排行榜:利用 Redis 的 SortedSet 实现
6.2 技术优缺点
✅ 优点
- 高性能(微秒级响应)
- 高可用(Sentinel 自动故障转移)
- 支持丰富的数据结构
❌ 缺点
- 内存成本高
- 集群配置较复杂
6.3 注意事项
- 监控:使用
INFO命令监控 Redis 状态 - 持久化:配置
RDB或AOF防止数据丢失 - 内存优化:使用
Hash结构节省内存
七、总结
分布式缓存高可用是 .NET Core 应用的必备技能。通过 Redis Sentinel,我们可以构建一个自动容错的缓存系统,再结合多级缓存、雪崩防护等策略,让系统更加健壮。
如果你的应用还在裸奔式使用单机 Redis,是时候考虑升级到高可用架构了!
评论