<p>选 Redis 还是 Memcached 取决于数据结构需求:Memcached 仅支持 string 且无持久化,Redis 支持多种数据类型及高级功能;C# 中推荐 StackExchange.Redis 连 Redis(全局单例复用 ConnectionMultiplexer),新项目勿用已停更的 Enyim.Caching 连 Memcached。</p>

Redis 和 Memcached 在 C# 中的本质区别
选 Redis 还是 Memcached,不是看哪个“更流行”,而是看你要存什么。Memcached 只支持 string 类型的键值对,且不支持持久化、没有原生集合操作;Redis 支持 string、hash、list、set、zset,还能做简单消息队列、带过期时间的分布式锁。如果你只需要高速缓存 JSON 字符串或二进制 blob,Memcached 足够轻量;但只要涉及对象结构、计数器、排行榜、延迟任务,Redis 是唯一合理选择。
用 StackExchange.Redis 连 Redis(推荐方式)
StackExchange.Redis 是目前 C# 生态最稳定、高性能、线程安全的 Redis 客户端。它默认使用连接池,不建议每次操作都 new ConnectionMultiplexer。常见错误是把 ConnectionMultiplexer 声明为局部变量,导致频繁重建连接、CPU 升高、出现 SocketFailure 或 TimeoutException。
正确做法:
- 全局单例复用
ConnectionMultiplexer(用static readonly或 DI 注册为 Singleton) - 用
IDatabase获取数据库实例(它是无状态的,可随时获取) - 避免在
async方法里混用.Wait()或.Result,会引发死锁
示例片段:
private static readonly Lazy<ConnectionMultiplexer> LazyConnection =
new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect("localhost:6379"));
<p>public static ConnectionMultiplexer Connection => LazyConnection.Value;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/ai/758" title="Nanonets"><img
src="https://img.php.cn/upload/ai_manual/001/503/042/68b6db6adbfa5954.png" alt="Nanonets" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/ai/758" title="Nanonets">Nanonets</a>
<p>基于AI的自学习OCR文档处理,自动捕获文档数据</p>
</div>
<a href="/ai/758" title="Nanonets" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p>// 使用时
var db = Connection.GetDatabase();
await db.StringSetAsync("user:1001", JsonSerializer.Serialize(user), TimeSpan.FromMinutes(30));
用 Enyim.Caching 连 Memcached(仅限遗留项目)
Enyim.Caching 是 .NET Framework 时代主流的 Memcached 客户端,但已多年未更新,不支持 .NET 5+ 的 Span<byte> 优化,且配置复杂、日志不透明。新项目不要选它。如果必须维护老系统,请注意:
-
MemcachedClient不是线程安全的,不能全局单例 —— 必须每个请求/作用域新建,或用ObjectPool<MemcachedClient>管理 - 所有值都会被序列化为
byte[],默认用BinaryFormatter(已废弃且不安全),务必替换为System.Text.Json或Newtonsoft.Json实现自定义ITranscoder - Memcached 不支持 key 的命名空间或批量删除,清缓存只能靠 key 前缀 + 扫描(不推荐)或设短 TTL
缓存穿透、雪崩、击穿的 C# 应对思路
这些不是 Redis/Memcached 自带的功能,得靠代码层兜底。比如缓存穿透(查不到还反复打 DB),不能只靠“缓存空值”,还要加随机过期时间防集中失效:
- 空结果也缓存,但 TTL 设为
TimeSpan.FromSeconds(60 + new Random().Next(30)) - 热点 key 击穿:用
MemoryCache做本地二级缓存(如Microsoft.Extensions.Caching.Memory),配合GetOrCreateAsync+lock或SemaphoreSlim控制回源并发 - 避免 Redis 雪崩:不同业务 key 的过期时间别对齐,可用
DateTimeOffset.UtcNow.AddSeconds(ttlSeconds + new Random().Next(120))
真正容易被忽略的是:Redis 连接超时和重试策略。默认 ConnectTimeout=5000ms,网络抖动时大量请求卡住。应在 ConfigurationOptions 中显式设置 ConnectRetry = 3、ReconnectDelay = TimeSpan.FromMilliseconds(500),并监听 ConnectionFailed 事件做告警。









