X組件緩存架構以ICache接口為核心,包括MemoryCache、Redis和DbCache實現,支持FX和netstandard2.0!
后續例程與使用說明均以Redis為例,各緩存實現類似。
Redis組件:Nuget包NewLife.Redis,源碼 https://github.com/NewLifeX/NewLife.Redis
X組件:Nuget包NewLife.Core,源碼 https://github.com/NewLifeX/X
一、內存緩存 MemoryCache
MemoryCache核心是並行字典ConcurrentDictionary,由於省去了序列化和網絡通信,使得它具有千萬級超高性能(普通台式機實測1600萬tps)。
MemoryCache支持過期時間,默認容量10萬個,未過期key超過該值后,每60秒根據LRU清理溢出部分。
常用於進程內千萬級以下數據緩存場景。
// 緩存默認實現Cache.Default是MemoryCache,可修改 //var ic = Cache.Default; //var ic = new MemoryCache();
二、基礎 Redis
Redis實現標准協議以及基礎字符串操作,完整實現由獨立開源項目NewLife.Redis提供。
采取連接池加同步阻塞架構,具有超低延遲(200~600us)以及超高吞吐量(實測222萬ops/900Mbps)的特點。
在物流行業大數據實時計算中廣泛應有,經過日均100億次調用量驗證。
// 實例化Redis,默認端口6379可以省略,密碼有兩種寫法 //var ic = Redis.Create("127.0.0.1", 7); var ic = Redis.Create("pass@127.0.0.1:6379", 7); //var ic = Redis.Create("server=127.0.0.1:6379;password=pass", 7); ic.Log = XTrace.Log; // 調試日志。正式使用時注釋
三、數據庫 DbCache
DbCache屬於實驗性質,采用數據庫存儲數據,默認SQLite。
四、基本操作
在基本操作之前,我們先做一些准備工作:
新建控制台項目,並在入口函數開頭加上 XTrace.UseConsole(); ,這是為了方便查看調試日志
具體測試代碼之前,需要加上前面MemoryCache或Redis的實例化代碼
准備一個模型類User
class User { public String Name { get; set; } public DateTime CreateTime { get; set; } }
添刪改查:
var user = new User { Name = "NewLife", CreateTime = DateTime.Now }; ic.Set("user", user, 3600); var user2 = ic.Get<User>("user"); XTrace.WriteLine("Json: {0}", ic.Get<String>("user")); if (ic.ContainsKey("user")) XTrace.WriteLine("存在!"); ic.Remove("user");
執行結果:
14:14:25.990 1 N - SELECT 7 14:14:25.992 1 N - => OK 14:14:26.008 1 N - SETEX user 3600 [53] 14:14:26.021 1 N - => OK 14:14:26.042 1 N - GET user 14:14:26.048 1 N - => [53] 14:14:26.064 1 N - GET user 14:14:26.065 1 N - => [53] 14:14:26.066 1 N - Json: {"Name":"NewLife","CreateTime":"2018-09-25 14:14:25"} 14:14:26.067 1 N - EXISTS user 14:14:26.068 1 N - => 1 14:14:26.068 1 N - 存在! 14:14:26.069 1 N - DEL user 14:14:26.070 1 N - => 1
保存復雜對象時,默認采用Json序列化,所以上面可以按字符串把結果取回來,發現正是Json字符串。
Redis的strings,實質上就是帶有長度前綴的二進制數據,[53]表示一段53字節長度的二進制數據。
五、集合操作
GetAll/SetAll 在Redis上是很常用的批量操作,同時獲取或設置多個key,一般有10倍以上吞吐量。
批量操作:
var dic = new Dictionary<String, Object> { ["name"] = "NewLife", ["time"] = DateTime.Now, ["count"] = 1234 }; ic.SetAll(dic, 120); var vs = ic.GetAll<String>(dic.Keys); XTrace.WriteLine(vs.Join(",", e => $"{e.Key}={e.Value}"));
執行結果:
MSET name NewLife time 2018-09-25 15:56:26 count 1234 => OK EXPIRE name 120 EXPIRE time 120 EXPIRE count 120 MGET name time count name=NewLife,time=2018-09-25 15:56:26,count=1234
集合操作里面還有 GetList/GetDictionary/GetQueue/GetSet 四個類型集合,分別代表Redis的列表、哈希、隊列、Set集合等。
基礎版Redis不支持這四個集合,完整版NewLife.Redis支持,MemoryCache則直接支持。
六、高級操作
- Add 添加,當key不存在時添加,已存在時返回false。
- Replace 替換,替換已有值為新值,返回舊值。
- Increment 累加,原子操作
- Decrement 遞減,原子操作
高級操作:
var flag = ic.Add("count", 5678); XTrace.WriteLine(flag ? "Add成功" : "Add失敗"); var ori = ic.Replace("count", 777); var count = ic.Get<Int32>("count"); XTrace.WriteLine("count由{0}替換為{1}", ori, count); ic.Increment("count", 11); var count2 = ic.Decrement("count", 10); XTrace.WriteLine("count={0}", count2);
執行結果:
SETNX count 5678 => 0 Add失敗 GETSET count 777 => 1234 GET count => 777 count由1234替換為777 INCRBY count 11 => 788 DECRBY count 10 => 778 count=778
七、性能測試
Bench 會分根據線程數分多組進行添刪改壓力測試。
rand 參數,是否隨機產生key/value。
batch 批大小,分批執行讀寫操作,借助GetAll/SetAll進行優化。
Redis默認設置AutoPipeline=100,無分批時打開管道操作,對添刪改優化。
Redis性能測試[隨機],批大小[100],邏輯處理器 40 個 2,400MHz Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz 測試 100,000 項, 1 線程 賦值 100,000 項, 1 線程,耗時 418ms 速度 239,234 ops 讀取 100,000 項, 1 線程,耗時 520ms 速度 192,307 ops 刪除 100,000 項, 1 線程,耗時 125ms 速度 800,000 ops 測試 200,000 項, 2 線程 賦值 200,000 項, 2 線程,耗時 548ms 速度 364,963 ops 讀取 200,000 項, 2 線程,耗時 549ms 速度 364,298 ops 刪除 200,000 項, 2 線程,耗時 315ms 速度 634,920 ops 測試 400,000 項, 4 線程 賦值 400,000 項, 4 線程,耗時 694ms 速度 576,368 ops 讀取 400,000 項, 4 線程,耗時 697ms 速度 573,888 ops 刪除 400,000 項, 4 線程,耗時 438ms 速度 913,242 ops 測試 800,000 項, 8 線程 賦值 800,000 項, 8 線程,耗時 1,206ms 速度 663,349 ops 讀取 800,000 項, 8 線程,耗時 1,236ms 速度 647,249 ops 刪除 800,000 項, 8 線程,耗時 791ms 速度 1,011,378 ops 測試 4,000,000 項, 40 線程 賦值 4,000,000 項, 40 線程,耗時 4,848ms 速度 825,082 ops 讀取 4,000,000 項, 40 線程,耗時 5,399ms 速度 740,877 ops 刪除 4,000,000 項, 40 線程,耗時 6,281ms 速度 636,841 ops 測試 4,000,000 項, 64 線程 賦值 4,000,000 項, 64 線程,耗時 6,806ms 速度 587,716 ops 讀取 4,000,000 項, 64 線程,耗時 5,365ms 速度 745,573 ops 刪除 4,000,000 項, 64 線程,耗時 6,716ms 速度 595,592 ops
Redis組件:Nuget包NewLife.Redis,源碼 https://github.com/NewLifeX/NewLife.Redis
X組件:Nuget包NewLife.Core,源碼 https://github.com/NewLifeX/X
如果你喜歡我們的開源項目,到github賞個star唄^_^