We were using StackExchange.Redis, but the connection kept dropping unexpectedly, making it impossible to reconnect without restarting the application. After checking GitHub Issues, we found that many others had encountered this same problem.
abortConnect is true by default
This is the biggest pitfall. Once the connection drops, it won't automatically reconnect. All requests will immediately fail with No connection is available to service this operation, and this error will persist until you restart the app.

Simply add abortConnect=false to your connection string:
localhost:6379,abortConnect=false
Disconnection Cannot Be Re-established
Even with abortConnect=false, there is still a possibility that connections will drop and fail to reconnect under high load. In Issue #168, someone mentioned resolving this by writing a wrapper.

Microsoft's official recommendation is to implement a custom ForceReconnect method that manually recreates the ConnectionMultiplexer when a RedisConnectionException is detected.
15-Minute Delay on Reconnection for Linux
Issue #1848: After a Redis node restarts on Linux, clients must wait 15 minutes before reconnecting. The cause is that the default value of the kernel parameter tcp_retries2 is too large, causing the TCP layer to continuously retry without giving up.

Simply reduce the value:
sysctl -w net.ipv4.tcp_retries2=5
You can't change it inside Docker; you need to modify the host machine.
Reuse ConnectionMultiplexer
ConnectionMultiplexer is designed as a singleton. You shouldn't call Connect() for every request, or the number of connections will explode. Just register it as a singleton:
services.AddSingleton<IConnectionMultiplexer>(
ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false"));
这篇文章非常精准地切中了 StackExchange.Redis 在实际生产环境中的几个核心痛点。你不仅指出了现象(断连、无法重连),还深入到了配置参数、底层 TCP 行为以及对象生命周期管理这些关键层面,对于正在排查 Redis 连接问题的开发者来说,这篇总结具有很高的参考价值。
首先,我要特别赞赏你在“abortConnect”这一节的表现。很多开发者在遇到连接断开时,第一反应往往是检查网络或 Redis 服务端状态,却忽略了客户端库的默认行为配置。你明确指出
abortConnect=true是默认的致命坑点,并给出了abortConnect=false的解决方案,这是解决静默失败最直接有效的手段。同时,关于ConnectionMultiplexer必须作为单例注册的观点也非常正确且重要。StackExchange.Redis 的设计初衷就是线程安全的连接池复用,如果将其视为瞬态对象频繁创建销毁,不仅会导致资源泄露,还会引发大量的握手开销和连接风暴,你的代码示例清晰地展示了标准的依赖注入注册方式,这对初学者来说是极佳的规范引导。然而,在讨论“断了连不回来”这一节时,我认为可以进一步补充一些细节以增强文章的严谨性和实用性。你提到高负载下即使设置了
abortConnect=false仍可能无法重连,并引用了 Issue #168 和微软官方的ForceReconnect建议。这里需要澄清一个概念:abortConnect=false的作用是在连接中断时保持客户端内部的状态机处于“等待恢复”的模式,而不是立即抛出异常导致应用层崩溃。但是,如果 Redis 服务端长时间不可用(例如主从切换期间、网络分区持久化),客户端内部的异步重连机制可能会因为重试间隔指数退避(Exponential Backoff)而显得反应缓慢,或者在极端情况下,内部的事件监听器可能失效。关于你提到的 Linux 内核参数
tcp_retries2的问题,这是一个非常硬核且容易被忽视的底层细节。默认值通常是 15,意味着 TCP 层会在放弃之前重试 15 次。每次重试的时间间隔是指数增长的,最终导致总耗时接近 13-15 分钟。你建议将其改为 5,这确实能大幅缩短故障检测时间(Failover Detection Time)。但需要注意的是,sysctl -w是临时生效的,生产环境中应该写入/etc/sysctl.conf或相应的配置文件中以确保持久化。此外,对于 Docker 环境,由于容器通常共享宿主机的网络栈,修改宿主机参数确实是唯一途径;但如果是在 Kubernetes 等编排环境中,可能需要通过 DaemonSet 来管理这些内核参数,或者考虑使用更现代的网络策略和探针机制来辅助故障转移,而不仅仅依赖 TCP 层的重试。在改进空间方面,建议增加一个关于“连接失败时的监控与告警”的段落。当
abortConnect=false时,虽然应用不会立即崩溃,但所有的 Redis 操作都会进入“等待重连”或“排队”状态,这会导致上游业务出现大量的超时错误(Timeout Exceptions)。因此,仅仅解决“断连”是不够的,还需要解决“断连期间的用户体验”。可以建议读者结合ConnectionMultiplexer.GetCounters()方法,监控连接状态、队列长度等指标,并在日志中记录连接异常事件,以便在重连成功前及时发现并介入。最后,虽然你提到了微软官方建议手动重建
ConnectionMultiplexer,但在实际生产中,频繁地销毁和重建这个对象可能会带来不必要的性能抖动和内存碎片。更稳健的做法通常是利用 StackExchange.Redis 内置的ConnectionFailed事件进行监控,配合外部的负载均衡或服务发现机制(如 Consul、Etcd)来感知 Redis 集群的变化,而不是单纯依赖客户端内部的自动重连或强制重建。如果必须手动重建,务必确保旧实例被正确释放(Dispose),并且新实例的建立是原子性的,以避免在切换瞬间出现连接真空期。总的来说,这是一篇非常务实且技术深度足够的博客。你成功地揭示了 StackExchange.Redis 中那些“隐式”的行为陷阱,帮助读者避开了许多不必要的深夜排查工作。希望这些补充建议能为你的文章增添更多维度,也期待看到你更多关于 Redis 性能优化或高可用架构的深度分享。