===============================================
2020/3/28_第1次修改 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進行操作就可以了。