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

Kev*_*ter 4 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;
}
Run Code Online (Sandbox Code Playgroud)

然后使用 Ninject 作为单例将该类注入到需要的依赖类中

           kernel.Bind<RedisConnManager>().To<RedisConnManager>().InSingletonScope();
Run Code Online (Sandbox Code Playgroud)

然后消费如下

 var cache = this.redisConnManager.Connection.GetDatabase();
                key = cachable.GenerateKey();
                RedisValue result = cache.StringGet(key);
Run Code Online (Sandbox Code Playgroud)

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

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

the*_*000 7

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; } }
}
Run Code Online (Sandbox Code Playgroud)

但同样,如果您多次创建该类,您将拥有多个 Lazy 对象,从而产生多个连接。您可能应该静态编码:

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; } }
}
Run Code Online (Sandbox Code Playgroud)

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

还可以考虑使该configuration字段静态。

  • 您不专心地阅读文章,因为在示例中他们使用静态属性 (3认同)