基於async/non-blocking高性能redis組件庫BeetleX.Redis


BeetleX.Redis是基於async/non-blocking模式實現的高性能redis組件庫,組件支持redis基礎指令集,並封裝更簡便的List,HashsetSubscribe操作。除了在基礎操作功能上,組件還提供多服務備份方式和多連接池機制,從而讓組件提供高可用和高性能的訪問方案;在數據格式上組件默認集成了jsonprotobuf可以根據自己的需求來選擇相應的存儲格式。接下來大概看一下組件的性能和應用功能。

性能

針對Order結構進行一個GET/SET性能測試,分別測試BeetleXStackExchange在這兩個操作下不同線程的壓測,由於在8以上線程數測試StackExchange經常拋timeout錯誤....,所以只測了1,2和4線程情況。詳細測試代碼:https://github.com/IKende/BeetleX.Redis/tree/master/PerformanceTest(代碼里集成了一個輕巧的性能測試功能類,用起來非常方便,只需要簡單編寫測試用例就可以列表出測試時間和並發等相關數據,以下測試結果列表由這個測試類輸出。)

  • 測試數據結構
{"OrderID":10255,"CustomerID":"RICSU","EmployeeID":9,"OrderDate":"1996-07-12T00:00:00","RequiredDate":"1996-08-09T00:00:00","ShippedDate":"1996-07-15T00:00:00","ShipVia":3,"Freight":148.33,"ShipName":"Richter Supermarkt","ShipAddress":"Starenweg 5","ShipCity":"Genève","ShipPostalCode":"1204","ShipCountry":"Switzerland"}
  • Beetlex
1  await RedisDB.Set(item.OrderID.ToString(), item);
2  await RedisDB.Get<Order>(i.ToString());
  • StackExchange
1   await RedisDB.StringSetAsync(item.OrderID.ToString(), Newtonsoft.Json.JsonConvert.SerializeObject(item));
2   var data = await RedisDB.StringGetAsync(i.ToString());
3   var item = Newtonsoft.Json.JsonConvert.DeserializeObject<Northwind.Data.Order>(data);
  • 測試結果
-------------------------------------------------------------------------------
|Name                          | Round| Threads|     Count| Use time(s)|   Sec|
-------------------------------------------------------------------------------
|BeetleX_SET                   |     1|       1|    100000|        5.22| 19157|
-------------------------------------------------------------------------------
|StackExchange_SET             |     1|       1|    100000|        6.97| 14357|
-------------------------------------------------------------------------------
|StackExchange_Sync_SET        |     1|       1|    100000|        6.62| 15103|
-------------------------------------------------------------------------------
|BeetleX_GET                   |     1|       1|    100000|        5.41| 18487|
-------------------------------------------------------------------------------
|StackExchange_GET             |     1|       1|    100000|        7.48| 13378|
-------------------------------------------------------------------------------
|StackExchange_Sync_GET        |     1|       1|    100000|        7.09| 14105|
-------------------------------------------------------------------------------
|BeetleX_MGET                  |     1|       1|    100000|        7.03| 14216|
-------------------------------------------------------------------------------
|StackExchange_MGET            |     1|       1|    100000|        8.69| 11504|
-------------------------------------------------------------------------------
|StackExchange_Sync_MGET       |     1|       1|    100000|        8.36| 11963|
-------------------------------------------------------------------------------
|BeetleX_SET                   |     1|       2|    100000|        2.55| 39246|
-------------------------------------------------------------------------------
|StackExchange_SET             |     1|       2|    100000|        3.97| 25199|
-------------------------------------------------------------------------------
|StackExchange_Sync_SET        |     1|       2|    100000|        3.56| 28069|
-------------------------------------------------------------------------------
|BeetleX_GET                   |     1|       2|    100000|        2.78| 35946|
-------------------------------------------------------------------------------
|StackExchange_GET             |     1|       2|    100000|         4.1| 24364|
-------------------------------------------------------------------------------
|StackExchange_Sync_GET        |     1|       2|    100000|        3.72| 26907|
-------------------------------------------------------------------------------
|BeetleX_MGET                  |     1|       2|    100000|        3.59| 27871|
-------------------------------------------------------------------------------
|StackExchange_MGET            |     1|       2|    100000|        4.75| 21035|
-------------------------------------------------------------------------------
|StackExchange_Sync_MGET       |     1|       2|    100000|        4.55| 21976|
-------------------------------------------------------------------------------
|BeetleX_SET                   |     1|       4|    100000|        2.04| 48956|
-------------------------------------------------------------------------------
|StackExchange_SET             |     1|       4|    100000|        2.37| 42220|
-------------------------------------------------------------------------------
|StackExchange_Sync_SET        |     1|       4|    100000|        2.15| 46541|
-------------------------------------------------------------------------------
|BeetleX_GET                   |     1|       4|    100000|        2.14| 46822|
-------------------------------------------------------------------------------
|StackExchange_GET             |     1|       4|    100000|        2.58| 38789|
-------------------------------------------------------------------------------
|StackExchange_Sync_GET        |     1|       4|    100000|        2.24| 44619|
-------------------------------------------------------------------------------
|BeetleX_MGET                  |     1|       4|    100000|        2.49| 40238|
-------------------------------------------------------------------------------
|StackExchange_MGET            |     1|       4|    100000|        3.06| 32708|
-------------------------------------------------------------------------------
|StackExchange_Sync_MGET       |     1|       4|    100000|        2.76| 36264|
-------------------------------------------------------------------------------

組件使用

組件默認就支持數據對象操作,而數據存儲的格式則由相應創建的DB數據類型決定,所以在使用和處理數據上都比較方便。

創建數據庫

RedisDB DB = new RedisDB();
DB.AddWriteHost("192.168.2.19");
// set password
DB.AddWriteHost("192.168.2.19").Password="123456";

Json 數據庫

RedisDB DB = new RedisDB(0, new JsonFormater());

Protobuf 數據庫

RedisDB DB = new RedisDB(0, new ProtobufFormater());

基礎操作

await DB.Decr("mykey")
await DB.Decrby("mykey", 5);
await DB.Del("mykey");
await DB.Dump("mykey");
await DB.Exists("mykey", "order");
await DB.Expire("mykey", 10);
await DB.Expireat("mykey", 1293840000);
await DB.Get<string>("mykey");
await DB.GetBit("mykey", 0);
await DB.GetRange("mykey", -3, -1);
await DB.GetSet<string>("mycounter", 0);
await DB.Incr("mykey");
await DB.Incrby("mykey", 10);
await DB.IncrbyFloat("mykey", 0.1f);
await DB.Keys("t??");
await DB.MGet<string, string>("key1", "key2");
await DB.MGet<string, string, string>("key1", "aaa", "key2");
await DB.MSet(m => m["key1", "hello"]["key2", "world"]);
await DB.MSetNX(m => m["key1", "hello"]["key2", "there"]);
await DB.Move("one", 9);
await DB.PSetEX("mykey", 1000, "hello");
await DB.Persist("mykey");
await DB.Pexpire("mykey", 1500);
await DB.Pexpireat("mykey", 1555555555005);
await DB.Ping();
await DB.PTtl("mykey");
await DB.Randomkey();
await DB.Rename("mykey", "myotherkey");
await DB.Renamenx("mykey", "myotherkey");
await DB.Set("test", "henryfan");
await DB.SetBit("mykey", 7, false);
await DB.SetEX("mykey", 10, "hello");
await DB.SetNX("mykey", "hello");
await DB.SetRange("key1", 6, "redis");
await DB.Strlen("key1");
await DB.Type("key2");

列表操作

創建列表

 var list = DB.CreateList<Employee>("employees");

列表操作

await list.BLPop();
await list.BRPop();
await list.BRPopLPush("List2");
await list.Index(0);
await list.Insert(true, GetEmployee(2), GetEmployee(3));
await list.Len();
await list.Pop();
await list.Push(GetEmployee(1));
await list.Push(GetEmployee(1), GetEmployee(2));
await myotherlist.PushX(GetEmployee(2));
await list.Rem(-2, GetEmployee(1));
await list.Set(-2, GetEmployee(5));
await list.Trim(1, -1);
await list.RPop();
await list.RPopLPush("myotherlist");
await list.RPush(GetEmployee(3));
await list.RPush(GetEmployee(1), GetEmployee(2));
await list.RPushX(GetEmployee(2));
await list.Range(-3, 2);

HashTable結構

創建

var table = DB.CreateHashTable("myhash");

相關操作

await table.Del("emp1");
await table.Exists("emp1");
await table.Get<Employee>("emp1");
await table.Keys();
await table.Len();
await table.Get<Employee, Order>("emp", "order");
await table.Get<Employee, Order, Customer>("emp", "order", "customer");
await table.MSet(m => m["field1", GetEmployee(1)]["field2", GetCustomer(1)]);
await table.Set("field1", GetEmployee(1));
await table.SetNX("field", GetEmployee(1));

訂閱

創建訂閱

            var sub = db.Subscribe();
            sub.Register<Employee>("test1");
            sub.Receive = (o, e) =>
            {
                Console.WriteLine($"[{DateTime.Now}]{e.Channel}-{e.Type}:{e.Data}");
            };
            sub.Listen();

通過Retister方法注冊訂閱頻道,在注冊的時候必須指定數據類型,對象反序列化的格式依據庫數據的格式類型。

await DB.Publish("test1", GetEmployee(i));

以上是發布消息到頻道

總結

以上是BeetleX.Redis現有版本的功能,集群功能暫沒有實現;但提供主備功能可以根據自己的需要添加多個WriteHost或ReadHost,默認連接池機制隨意應對高並發應用;組件希望打造一個高性能簡便的Redis .net core組件,但要發揮組件的性能特色就要適應完全基於await的方法進行組件操作。 項目開源地址:https://github.com/IKende/BeetleX.Redis


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM