有谁有通过BookSleeve库获取Redis的可靠模式吗?
我是说:
BookSleeve的作者@MarcGravell 建议不是每次打开和关闭连接,而是在整个应用程序中维护一个连接。但是你如何处理网络中断呢?也就是说,连接一开始可能会被成功地打开,但是当一些代码试图读/写到Redis时,连接可能已经断开,您必须重新打开它(如果它不打开,就会很优雅地失败--但这取决于您的设计需要)。
我寻找覆盖普通Redis连接打开的代码片段,以及在每次读/写之前使用的一般“活动”检查(+可选的“清醒”,如果不是活动的话)。
这个问题给出了一个很好的解决问题的态度,但是它只是部分的(例如,它不会恢复丢失的连接),而接受答案对这个问题的处理方法是正确的,但没有演示具体的代码。
我希望这个线程能够得到可靠的答案,并最终成为BookSleeve在.Net应用程序中使用的一种Wiki。
-----------------------------
重要更新(21/3/2014):
-----------------------------
MarcGravell (@MarcGravell) / Stack拥有最近发布,StackExchange.Redis库最终取代了书包。除其他外,这个新库在内部处理重连接,并使我的问题变得多余(也就是说,它对于Booksleeve来说并不是多余的,下面的答案也不是多余的,但我想最好的方法是开始使用新的StackExchange.Redis库)。
发布于 2012-01-08 13:38:14
由于我没有任何好的答案,我想出了这个解决方案(BTW感谢@Simon和@Alex为您的答案!)
我想与社会各界分享,作为参考。当然,任何更正都将不胜感激。
using System;
using System.Net.Sockets;
using BookSleeve;
namespace Redis
{
public sealed class RedisConnectionGateway
{
private const string RedisConnectionFailed = "Redis connection failed.";
private RedisConnection _connection;
private static volatile RedisConnectionGateway _instance;
private static object syncLock = new object();
private static object syncConnectionLock = new object();
public static RedisConnectionGateway Current
{
get
{
if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)
{
_instance = new RedisConnectionGateway();
}
}
}
return _instance;
}
}
private RedisConnectionGateway()
{
_connection = getNewConnection();
}
private static RedisConnection getNewConnection()
{
return new RedisConnection("127.0.0.1" /* change with config value of course */, syncTimeout: 5000, ioTimeout: 5000);
}
public RedisConnection GetConnection()
{
lock (syncConnectionLock)
{
if (_connection == null)
_connection = getNewConnection();
if (_connection.State == RedisConnectionBase.ConnectionState.Opening)
return _connection;
if (_connection.State == RedisConnectionBase.ConnectionState.Closing || _connection.State == RedisConnectionBase.ConnectionState.Closed)
{
try
{
_connection = getNewConnection();
}
catch (Exception ex)
{
throw new Exception(RedisConnectionFailed, ex);
}
}
if (_connection.State == RedisConnectionBase.ConnectionState.Shiny)
{
try
{
var openAsync = _connection.Open();
_connection.Wait(openAsync);
}
catch (SocketException ex)
{
throw new Exception(RedisConnectionFailed, ex);
}
}
return _connection;
}
}
}
}发布于 2011-12-28 13:45:56
对于其他系统(如ADO.NET),这是使用连接池实现的。您从来没有真正得到一个新的连接对象,但实际上是从池中获得的。
池本身独立于调用方代码管理新连接和死连接。这里的想法是有更好的性能(建立一个新的连接是草率的),并避免网络问题(当服务器关闭时调用者代码将失败,但当服务器恢复联机时继续运行)。事实上,每个AppDomain都有一个池,每种类型的连接。
当您查看ADO.NET连接字符串时,就会发现这种行为。例如,Server连接字符串(ConnectionString性质)具有“池”、“最大池大小”、“Min”等概念。这也是一种ClearAllPools方法,用于编程重置当前的AppDomain池(例如,需要时)。
我没有看到任何与BookSleeve代码密切相关的特性,但是它似乎是计划在下一个版本:BookSleeve RoadMap。
同时,我认为您可以编写自己的连接池,因为RedisConnection有一个错误事件,您可以用来检测它何时死掉。
发布于 2012-01-06 23:24:51
我不是C#程序员,但我看待问题的方式如下:
下面是某种伪代码:
function execute(redis_con, lambda_func) {
try {
return lambda_func(redis_con)
}
catch(connection_exception) {
redis_con = reconnect()
return lambda_func(redis_con)
}
}https://stackoverflow.com/questions/8645953
复制相似问题