使用Stackexchange时,Redis正在创建数千个连接

时间:2015-11-16 23:05:44

标签: caching redis lazy-initialization stackexchange.redis

我们刚刚开始使用来自Web和辅助角色的Azure Redis缓存。我们发现在相当轻的情况下使用~2.5K连接。

我们正在使用包装在连接管理器中的StackExchange.Redis nuget包

  public class RedisConnManager
{
    private readonly IConfiguration configuration;

    public RedisConnManager(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public Lazy<ConnectionMultiplexer> LazyConnection
    {
        get
        {
            return new Lazy<ConnectionMultiplexer>(
                () => ConnectionMultiplexer.Connect(
                    this.configuration.SessionManagerRedisConnectionString));
        }
    }
    public ConnectionMultiplexer Connection => this.LazyConnection.Value;
}

然后使用Ninject作为单例

将类注入需要的依赖类中
           kernel.Bind<RedisConnManager>().To<RedisConnManager>().InSingletonScope();

然后消费如下

 var cache = this.redisConnManager.Connection.GetDatabase();
                key = cachable.GenerateKey();
                RedisValue result = cache.StringGet(key);

我已经检查过ConnectionManager的构造函数不会被多次调用

我们应该看到这么多联系吗?

2 个答案:

答案 0 :(得分:3)

每次使用LazyConnection属性时,都在创建Lazy对象。这是非常错误的。

您应该只创建一次Lazy对象,例如在构造函数中:

public class RedisConnManager
{
    private readonly IConfiguration configuration;

    public RedisConnManager(IConfiguration configuration)
    {
        this.configuration = configuration;
        lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(
                configuration.SessionManagerRedisConnectionString));
    }

    private Lazy<ConnectionMultiplexer> lazyConnection;

    public ConnectionMultiplexer Connection { get { return lazyConnection.Value; } }
}

但是,如果你多次创建类,你将拥有多个Lazy对象,ergo多个连接。 您应该静态编码:

public class RedisConnManager
{
    private readonly IConfiguration configuration;

    public RedisConnManager(IConfiguration configuration)
    {
        this.configuration = configuration;
        lock (locker)
        {
            if (lazyConnection == null)
            {
                lazyConnection = new Lazy<ConnectionMultiplexer>(() => new ConnectionMultiplexer(this.configuration));
            }
        }
    }
    private static Lazy<ConnectionMultiplexer> lazyConnection;
    private static readonly object locker = new object();
    public ConnectionMultiplexer Connection { get { return lazyConnection.Value; } }
}

现在lazyConnection是静态的,因此将在类的所有实例中共享,并且只创建一次。 额外的锁机制代码是为了避免让多个线程创建惰性对象。

还要考虑将configuration字段设为静态。

答案 1 :(得分:-1)

或者甚至更好,如果您使用 ioc configure It 来创建它的单个实例,而不是将其作为静态道具。这将使单元测试更容易