6

我正在连接到 Azure Redis,它们向我显示了与我的 redis 服务器的打开连接数。我有以下 c# 代码,其中包含我所有的 Redis 集和获取。这应该是泄漏连接吗?

       using (var connectionMultiplexer = ConnectionMultiplexer.Connect(connectionString))
        {

            lock (Locker)
            {
                redis = connectionMultiplexer.GetDatabase();
            }

            var o = CacheSerializer.Deserialize<T>(redis.StringGet(cacheKeyName));
            if (o != null)
            {
                return o;
            }
            lock (Locker)
            {
                // get lock but release if it takes more than 60 seconds to complete to avoid deadlock if this app crashes before release
                //using (redis.AcquireLock(cacheKeyName + "-lock", TimeSpan.FromSeconds(60)))

                var lockKey = cacheKeyName + "-lock";
                if (redis.LockTake(lockKey, Environment.MachineName, TimeSpan.FromSeconds(10)))
                {
                    try
                    {
                        o = CacheSerializer.Deserialize<T>(redis.StringGet(cacheKeyName));
                        if (o == null)
                        {
                            o = func();
                            redis.StringSet(cacheKeyName, CacheSerializer.Serialize(o),
                                TimeSpan.FromSeconds(cacheTimeOutSeconds));
                        }
                        redis.LockRelease(lockKey, Environment.MachineName);
                        return o;
                    }
                    finally
                    {
                        redis.LockRelease(lockKey, Environment.MachineName);
                    }
                }
                return o;
            }

        }
    }
4

2 回答 2

5

您可以将 connectionMultiplexer 保留在静态变量中,而不是为每个 get/set 创建它。这将保持与 Redis 的连接始终打开并更快地进行操作。

更新:请看一下 StackExchange.Redis 的基本用法: https ://github.com/StackExchange/StackExchange.Redis/blob/master/Docs/Basics.md

“请注意,ConnectionMultiplexer 实现了 IDisposable 并且可以在不再需要时进行处理,但我故意不展示 using 语句的用法,因为您想要短暂使用 ConnectionMultiplexer 的情况非常罕见,因为它的想法是重用这个对象。

它对我来说很好,保持与 Azure Redis 的单一连接(有时,创建 2 个连接,但这是设计使然)。希望它会帮助你。

于 2016-02-26T08:50:40.240 回答
0

我建议尝试显式使用 Close(或 CloseAsync)方法。在测试设置中,您可能对不同的测试用例使用不同的连接,并且不想共享单个多路复用器。使用 Redis 客户端搜索公共代码会显示 Close 后跟 Dispose 调用的模式。

注意在 Redis 客户端的 XML 方法文档中,close 方法被描述为做更多事情:

    //
    // Summary:
    //     Close all connections and release all resources associated with this object
    //
    // Parameters:
    //   allowCommandsToComplete:
    //     Whether to allow all in-queue commands to complete first.
    public void Close(bool allowCommandsToComplete = true);
    //
    // Summary:
    //     Close all connections and release all resources associated with this object
    //
    // Parameters:
    //   allowCommandsToComplete:
    //     Whether to allow all in-queue commands to complete first.
    [AsyncStateMachine(typeof(<CloseAsync>d__183))]
    public Task CloseAsync(bool allowCommandsToComplete = true);

...

//
// Summary:
//     Release all resources associated with this object
public void Dispose();

然后我查找了客户端的代码,在这里找到了它:

https://github.com/StackExchange/StackExchange.Redis/blob/master/src/StackExchange.Redis/ConnectionMultiplexer.cs

我们可以看到调用 Close 的 Dispose 方法(不是通常的可覆盖受保护的 Dispose(bool)),此外,等待连接关闭设置为 true。它似乎是一种非典型的 dispose 模式实现,因为通过尝试所有闭包并等待它们,它可能会遇到异常,而 Dispose 方法合约应该永远不会抛出异常。

于 2019-12-18T00:10:04.330 回答