===============================================
ccb_warlock
===============================================
最近有较多的时间给我做框架优化的工作,之所以会关注到redis连接池则是因为框架的数据路由层在redis连接异常时的处理有可以优化的地方,于是针对redis连接池的功能做了学习和测试。
一、价值
1.1 池子的价值
这里简单提下池子设计的价值在于当某类连接需要反复创建,且创建的开销远远大于复用的开销时,可以选择引入池子来优化这块的设计。
一般来说,池子初始化时需要限定池子的大小。
最初池子里没有一个对象,当需要对象时,从池子里获取(没有时会自动创建一个跟踪的对象后提供你使用),当对象用完后并不做真正的释放,而是将该对象放回池子里等待下一个业务需要时取用。
1.2 redis池子的价值
一般在C#的项目中主要用StackExchange.Redis作为操作redis的轮子,而StackExchange.Redis通过创建TCP连接redis后对其进行一系列操作。
既然通过tcp,我们知道需要做3次握手后才能进行后续的业务,当业务并发执行时,池子就可以更好的降低创建连接的开销,提高连接效率。
二、NuGet包
StackExchange.Redis.ConnectionPool
PS.当前使用的版本为1.0.1
三、将redis连接池引入项目
3.1 前提
我只在基于asp.net core(2.2、3.1)的项目中测试过相关功能。
3.2 添加redis的配置信息
开发过asp.net core项目的应该知道,系统提供了用appsettings.json记录配置项、并通过依赖注入在项目中获取配置信息的方案。
假设appsettings.json的内容如下:
{
"Redis": {
"Host": "localhost",
"Port": 6379,
"Password": "123456",
"PoolSize": 20
}
}
3.3 创建接收配置的实体定义
public class RedisConfig
{
public string Host { get; set; }
public int Port { get; set; }
public string Password { get; set; }
public int PoolSize { get; set; }
}
3.4 添加连接池的依赖注入
这里先不考虑代码结构的问题,紧接着在Startup.cs中,添加下面的内容:
public class Startup
{
private IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//todo
// 根据实际的业务量来设置最小线程数
ThreadPool.SetMinThreads(200, 200);
var redisConfig = Configuration.GetSection("Redis").Get<RedisConfig>();
var redisOptions = new ConfigurationOptions
{
EndPoints =
{
{redisConfig.Host, redisConfig.Port}
},
Password = redisConfig.Password,
};
services.AddRedisConnectionPool(redisOptions, redisConfig.PoolSize);
//todo
}
}
通过调用StackExchange.Redis.ConnectionPool提供的方法,就已经将redis连接池的实体注入到了整个项目中。
四、redis连接池的使用
由于我优化的框架是在数据路由层的拦截器里去使用连接池,故以此为例来做描述。
public class RouteInterceptor : BaseInterceptor
{
private ObjectPool<PooledConnectionMultiplexer> Pool { get; set; }
public RouteInterceptor(ObjectPool<PooledConnectionMultiplexer> pool)
{
Pool = pool;
}
protected override void Handler(IInvocation invocation)
{
var db = 1;
//todo(获取要操作的db)
PooledConnectionMultiplexer client = null;
try
{
client = Pool.GetObject();
var clientDb = redis.GetDatabase(db)
//todo
}
catch (Exception e)
{
//todo
}
try
{
invocation.Proceed();
}
catch (Exception e)
{
//todo
}
finally
{
client?.Dispose();
}
}
}
接着就根据StackExchange.Redis的使用方法对redis进行操作就可以了。