c# StackExchange.Redis 异步API的使用和最佳实践

来源:这里教程网 时间:2026-02-21 17:40:18 作者:

异步方法命名和返回类型必须匹配
Task
Task<t></t>

StackExchange.Redis 的异步 API 全部以

Async
结尾,且返回值是
Task
Task<t></t>
,不是
ValueTask
,也不是同步方法的包装。误用
.Result
.Wait()
会导致线程阻塞、死锁(尤其在 ASP.NET Core 同步上下文里)。

正确写法:
await db.StringGetAsync("key")
await conn.GetDatabase().HashGetAllAsync("hash")
错误写法:
db.StringGetAsync("key").Result
(可能死锁)、
db.StringGet("key")
(同步调用,浪费连接池资源)
注意:所有
IConnectionMultiplexer
IDatabase
的异步方法都遵循此约定,没有例外

IDatabase
实例不能跨请求长期缓存

IDatabase
是轻量级、无状态的“视图”,每次调用
conn.GetDatabase()
都返回新实例,但底层复用同一个连接池。很多人误以为要单例缓存它,其实没必要;更危险的是把它当成线程安全对象长期持有并复用——它本身线程安全,但其行为依赖底层
IConnectionMultiplexer
的生命周期。

推荐做法:在 Web API 中,从 DI 容器获取
IConnectionMultiplexer
单例,每次请求内按需调用
GetDatabase(db: int?)
避免:把
IDatabase
存在静态字段或 Scoped 服务中供多次使用(除非明确控制 db index 和配置)
特别注意:
GetDatabase(0)
GetDatabase(1)
返回不同逻辑数据库,混用会出数据错乱

批量操作优先用
StringSetAsync
Pipeline
而非循环 await

对多个 key 执行独立异步操作时,逐个

await
不仅慢,还放大网络往返开销。StackExchange.Redis 支持原子批量(如
StringSetAsync
接收
KeyValuePair<rediskey redisvalue>[]</rediskey>
)和管道(
ISubscriber
IDatabase.Multiplex
级别的 pipeline),但要注意适用场景。

var pairs = new[]
{
    new KeyValuePair<RedisKey, RedisValue>("k1", "v1"),
    new KeyValuePair<RedisKey, RedisValue>("k2", "v2")
};
await db.StringSetAsync(pairs, When.Always, CommandFlags.HighPriority);
StringSetAsync(pairs[])
是原子写入,适合同一批 key 的简单 set
复杂混合命令(比如 set + expire + publish)要用
IBatch
:调用
db.CreateBatch()
,添加多个操作,再
await batch.ExecuteAsync()
别用
Task.WhenAll
包裹多个独立
StringGetAsync
—— 默认启用 pipelining,但并发数受
ConnectionMultiplexer
ConnectTimeout
ResponseTimeout
影响,容易触发超时

连接异常处理必须监听
ConnectionFailed
和重连逻辑

StackExchange.Redis 不抛出连接异常到业务层,而是静默重连或进入失败状态。如果只 catch

RedisException
,会漏掉连接断开、DNS 失败、认证失败等早期问题。

必须订阅:
conn.ConnectionFailed
事件,记录日志并触发告警
检查状态:
conn.IsConnected
是只读快照,不保证下一毫秒有效;真正可靠的是执行一次
await db.PingAsync()
并捕获异常
重连后,旧的
IDatabase
实例仍可继续用(内部自动重绑定),但若自定义了
CommandMap
Features
,需确保初始化逻辑幂等
常见错误现象:
RedisConnectionException: No connection is available...
,通常是因为连接池耗尽或未配置
AbortOnConnectFail=false

连接池大小、超时时间、重试策略这些参数没设对,比代码写错更容易导致线上雪崩。别跳过

ConfigurationOptions
的细调。

相关推荐