StackExchange.Redis ConnectionMultiplexer推荐配置

时间:2016-11-15 18:23:18

标签: c# redis stackexchange.redis

我在StackExchange.Redis中使用锁功能(LockTake和LockRelease),但需要保持基本上不断轮询。我让它从0到10毫秒的随机间隔睡觉然后再试一次。我打赌这基本上会阻碍连接。

我发现的文档建议(几乎)总是只使用1个ConnectionMultiplexer,它只能与Redis建立1个连接,但我也认为推荐是由于该连接的预期可用性。我最多可以说125个可能需要同时调用Redis的潜在线程。我可以使用连接池,但在这种情况下,池中应该有多少ConnectionMultiplexers?

修改

在下面的评论中与Marc讨论后,切换到Pub / Sub,但仍然使用连接池,这里是代码:

这是TakeLock方法

private Task TakeLockAsync(string key, string value)
    {
        TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
        var task = taskCompletionSource.Task;
        var db = _dbFactory.GetDatabase();
        //if we can get the lock, do it and return
        bool gotLockTry1 = db.LockTake(key, value, _redisLockConfig.RedisLockMaxAgeTimeSpan);
        if (gotLockTry1)
        {
            taskCompletionSource.SetResult(true);
            return task;
        }

        // if we failed to get the lock, 
        // set up a subscriber to listen for lock release publish
        var subscriber = db.Multiplexer.GetSubscriber();
        Action<RedisChannel, RedisValue> handler = null;
        handler = (redisChannel, redisValue) =>
        {
            bool gotLockTry3 = db.LockTake(key, value, _redisLockConfig.RedisLockMaxAgeTimeSpan);
            if (gotLockTry3)
            {
                subscriber.Unsubscribe(_subscriptionChannelName, handler);
                taskCompletionSource.SetResult(true);
            }
        };
        subscriber.Subscribe(_subscriptionChannelName, handler);

        // double check to make sure a release didn't come through while subscribing
        bool gotLockTry2 = db.LockTake(key, value, _redisLockConfig.RedisLockMaxAgeTimeSpan);
        if (gotLockTry2)
        {
            subscriber.Unsubscribe(_subscriptionChannelName, handler);
            taskCompletionSource.SetResult(true);
            return task;
        }
        return task;
    }

和Dispose:

public void Dispose()
    {
        if (string.IsNullOrEmpty(_key) || string.IsNullOrEmpty(_value))
        {
            return;
        }

        var db = _dbFactory.GetDatabase();

        //nested transactions not allowed, so can't call LockReleaseAsync
        var trans = db.CreateTransaction();
        // http://redis.io/topics/distlock
        // remove the key only if it exists and the value matches key's value
        trans.AddCondition(Condition.StringEqual(_key, _value));
        trans.KeyDeleteAsync(_key);
        trans.PublishAsync(_subscriptionChannelName, "something else here");
        //runs only when execute called
        trans.Execute();
    }

0 个答案:

没有答案