首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用BookSleeve维护开放的Redis连接

使用BookSleeve维护开放的Redis连接
EN

Stack Overflow用户
提问于 2011-12-27 14:53:21
回答 3查看 8.9K关注 0票数 26

有谁有通过BookSleeve库获取Redis的可靠模式吗?

我是说:

BookSleeve的作者@MarcGravell 建议不是每次打开和关闭连接,而是在整个应用程序中维护一个连接。但是你如何处理网络中断呢?也就是说,连接一开始可能会被成功地打开,但是当一些代码试图读/写到Redis时,连接可能已经断开,您必须重新打开它(如果它不打开,就会很优雅地失败--但这取决于您的设计需要)。

我寻找覆盖普通Redis连接打开的代码片段,以及在每次读/写之前使用的一般“活动”检查(+可选的“清醒”,如果不是活动的话)。

这个问题给出了一个很好的解决问题的态度,但是它只是部分的(例如,它不会恢复丢失的连接),而接受答案对这个问题的处理方法是正确的,但没有演示具体的代码。

我希望这个线程能够得到可靠的答案,并最终成为BookSleeve在.Net应用程序中使用的一种Wiki。

-----------------------------

重要更新(21/3/2014):

-----------------------------

MarcGravell (@MarcGravell) / Stack拥有最近发布StackExchange.Redis库最终取代了书包。除其他外,这个新库在内部处理重连接,并使我的问题变得多余(也就是说,它对于Booksleeve来说并不是多余的,下面的答案也不是多余的,但我想最好的方法是开始使用新的StackExchange.Redis库)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-08 13:38:14

由于我没有任何好的答案,我想出了这个解决方案(BTW感谢@Simon和@Alex为您的答案!)

我想与社会各界分享,作为参考。当然,任何更正都将不胜感激。

代码语言:javascript
复制
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;
            }
        }
    }
}
票数 29
EN

Stack Overflow用户

发布于 2011-12-28 13:45:56

对于其他系统(如ADO.NET),这是使用连接池实现的。您从来没有真正得到一个新的连接对象,但实际上是从池中获得的。

池本身独立于调用方代码管理新连接和死连接。这里的想法是有更好的性能(建立一个新的连接是草率的),并避免网络问题(当服务器关闭时调用者代码将失败,但当服务器恢复联机时继续运行)。事实上,每个AppDomain都有一个池,每种类型的连接。

当您查看ADO.NET连接字符串时,就会发现这种行为。例如,Server连接字符串(ConnectionString性质)具有“池”、“最大池大小”、“Min”等概念。这也是一种ClearAllPools方法,用于编程重置当前的AppDomain池(例如,需要时)。

我没有看到任何与BookSleeve代码密切相关的特性,但是它似乎是计划在下一个版本:BookSleeve RoadMap

同时,我认为您可以编写自己的连接池,因为RedisConnection有一个错误事件,您可以用来检测它何时死掉。

票数 2
EN

Stack Overflow用户

发布于 2012-01-06 23:24:51

我不是C#程序员,但我看待问题的方式如下:

  1. 我编写了一个泛型函数,它以redis连接和lambda表达式作为参数,表示Redis命令
  2. 如果尝试执行Redis命令会导致异常,指出连接问题,则重新初始化连接并重试操作。
  3. 如果没有引发异常,只需返回结果

下面是某种伪代码:

代码语言:javascript
复制
function execute(redis_con, lambda_func) {
    try {
        return lambda_func(redis_con)
    }
    catch(connection_exception) {
        redis_con = reconnect()
        return  lambda_func(redis_con)
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8645953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档