.net core 2.0 redis驅動效能比拼
今天來了三位主角,他們分別是大名鼎鼎的 StackExchange.Redis,無敵輕巧的 CSRedis,中通日處理80億訪問的 NewLife.Redis。
作者從2016年學習.netcore以來,接觸StackExchange.Redis遇到Timeout,這個問題坑了好多人。有人說2.0重構會解決了這個問題,碰巧本次測試發現2.0版本已經發布,本次測試版本為:2.0.505,期待StackExchange.Redis2.0重構版的測試表現。
NewLife.Redis 號稱日處理80億訪問,程式碼簡潔功能不多,能解決特定的業務場景,看看效能到底有多強勁。
ps: NewLife.Redis 不支援非同步方法,所以本次只測試同步方法。
測試程式碼 |
CSRedis.CSRedisClient csredis = new CSRedis.CSRedisClient("127.0.0.1:6379,password=,defaultDatabase=0,poolsize=100,ssl=false,writeBuffer=20480,prefix="); StackExchange.Redis.ConnectionMultiplexer seredis = StackExchange.Redis.ConnectionMultiplexer.Connect("127.0.0.1:6379,password="); StackExchange.Redis.IDatabase seredisDb = seredis.GetDatabase(); var nlredis = Redis.Create("127.0.0.1:6379", 4); nlredis.Password = ""; var nlredisClient = nlredis.Pool.Get(); Task.Run(() => { var times = new[] { 1000, 10000, 100000 }; foreach (var time in times) { var dt_csredis_set = DateTime.Now; for (var a = 0; a < time; a++) { csredis.Set($"benchmark_csredis_{a}", Guid.NewGuid().ToString()); } var ts_csredis_set = DateTime.Now.Subtract(dt_csredis_set); var dt_seredis_set = DateTime.Now; for (var a = 0; a < time; a++) { seredisDb.StringSet($"benchmark_seredis_{a}", Guid.NewGuid().ToString()); } var ts_seredis_set = DateTime.Now.Subtract(dt_seredis_set); var dt_nlredis_set = DateTime.Now; for (var a = 0; a < time; a++) { nlredisClient.Set($"benchmark_nlredis_{a}", Guid.NewGuid().ToString()); } var ts_nlredis_set = DateTime.Now.Subtract(dt_nlredis_set); var dt_csredis_get = DateTime.Now; for (var a = 0; a < time; a++) { csredis.Get($"benchmark_csredis_{a}"); } var ts_csredis_get = DateTime.Now.Subtract(dt_csredis_get); var dt_seredis_get = DateTime.Now; for (var a = 0; a < time; a++) { seredisDb.StringGet($"benchmark_seredis_{a}"); } var ts_seredis_get = DateTime.Now.Subtract(dt_seredis_get); var dt_nlredis_get = DateTime.Now; for (var a = 0; a < time; a++) { nlredisClient.Get<string>($"benchmark_nlredis_{a}"); } var ts_nlredis_get = DateTime.Now.Subtract(dt_nlredis_get); Console.WriteLine([email protected]" 迴圈次數: {time} csredis set: {ts_csredis_set.TotalMilliseconds}ms statckexchange.redis StringSet: {ts_seredis_set.TotalMilliseconds}ms newlife.redis set: {ts_nlredis_set.TotalMilliseconds}ms csredis get: {ts_csredis_get.TotalMilliseconds}ms statckexchange.redis StringGet: {ts_seredis_get.TotalMilliseconds}ms newlife.redis get: {ts_nlredis_get.TotalMilliseconds}ms "); } });
測試這段程式碼,對 csredis 其實不公平的,因為內部使用的連線池有一點消耗,支援單例定義使用,支援併發使用
另外,StackExchange.Redis.IDatabase 事先就初始化了,迴圈內沒有多次 GetDatabase()。
測試結果 |
優化指南 |
上面的對比結果不難發現,幾個驅動的效能大同小異,StackExchange.Redis 偏慢一點點。
NewLife.Redis 高效能優化的方向之一PipeLine,redis-server 支援管道模式,即指將一批命令打包,一次提交給 redis-server,減少來往消耗。
NewLife.Redis 通過 rds.AutoPipeLine = 100,設定 rds 集滿 100 條命令時 flush 打包提交一次。需要注意這是特定場景優化,比如你的專案訪問率低並且用到了快取,集滿 AutoPipeLine 條命令如果需要5秒,及有可能影響快取更新時間。
CSRedis 也支援 PipeLine 的,程式碼如下:
var ret1 = RedisHelper.StartPipe().Set("a", "1").Get("a").EndPipe(); var ret2 = RedisHelper.StartPipe(p => p.Set("a", "1").Get("a")); var ret3 = RedisHelper.StartPipe().Get("b").Get("a").Get("a").EndPipe(); //與 RedisHelper.MGet("b", "a", "a") 效能相比,經測試差之毫釐