Redis是一個高速緩存K-V數據庫,而NetMQ是ZeroMQ的C#實現版本,兩者是完全不同的東西。
最近做游戲服務器的時候想到,如果選擇一個組件來做服務器間通信的話,ZeroMQ絕對是一個不錯的選擇,而我們的服務器是用C#的開發的,就這樣,找到了NetMQ。
NetMQ上手很簡單。總結一下大致如下幾個步驟:
簡單的代碼如下
using (var context = NetMQContext.Create()) using (var socket = context.CreatePullSocket()) { socket.Bind("ipc://111");//socket.Connect("ipc://111"); string msg = socket.ReceiveFrameString(Encoding.UTF8); }
測試NetMQ的時候,發現如果開啟了VS的異常捕獲,在Connect的時候會收到不少異常,不過這些異常NetMQ都捕獲處理了,似乎不會導致程序問題,當然強迫症患者就不好辦了。
而且當消化隊列的服務器吃緊的時候隊列中的積壓數量的查看、保存等等的確也是需要不少工作量的。
於是想到不如再加個中間件,這個時候Redis就冒出來了。
Redis的list也可以用來做隊列,而且配套的工具也多了,感覺不錯的樣子。那就不如測試下性能吧。
因為手頭的Linux機在阿裡雲上,本地測試的話只有Windows可以用,所以,安裝了Redis的Windows版,地址在這裡:https://github.com/MSOpenTech/redis
直接下載Release版的就可以了,創建service-redis.exe的快捷方式,右鍵屬性,在目標的路徑後面追加配置文件,就像這樣:D:\Redis\redis-server.exe redis.windows.conf
(懶漢不願意操作命令行的簡便方式)
然後雙擊運行,看到漂亮的文字圖形之後,Redis就開動了。
接著是C#的對接,創建項目工程之後NuGet安裝Redis的Client驅動,流行的是Service.Stack.Redis,但Service.Stack在v4之後商業化了,免費使用有限制,隨手測下add1000次就出現了每小時只能add 6000的異常。所以不用它,換NServiceKit.Redis,有介紹是免費分支。
簡單的Add示例如下
using (RedisClient redisClient = new RedisClient(host)) { redisClient.Add("key1", "hello world!"); }
而我要使用的是list的Enqueue和Dequeue,就是這樣:
redisClient.EnqueueItemOnList("testList", "hello"); string msg = redisClient.DequeueItemOnList("testList");
測試是醬紫的:
首先開一個線程專注生產消息,生產的就是當時的時間。然後當前線程專注消費消息,獲取到消息生產的時間和消費到的時間,算出時間差,保存。
最後輸出消息總數、發送和接收用的平均時間。
我測試了10000個消息,差不多是這樣的代碼:
int time = 0; while (true) { redisClient.RemoveAllFromList("list"); Thread thread = new Thread(() => { using (RedisClient redisClient2 = new RedisClient(host)) { for (int i = 0; i < 10000; i++) { var now = DateTime.Now; string v = now.ToString("O"); redisClient2.EnqueueItemOnList("list", v); } } }); thread.Start(); List<TimeSpan> intervalArr = new List<TimeSpan>(); int index = 0; while (index < 10000) { string item = redisClient.DequeueItemFromList("list"); if (item != null) { index++; DateTime from = DateTime.Parse(item); var interval = DateTime.Now - from; intervalArr.Add(interval); } } Console.WriteLine("第{1}次,平均耗時:{0}, 數量:{2}", intervalArr.Average(x => x.TotalMilliseconds), time, intervalArr.Count); time++; Console.ReadLine(); }
使用NetMQ的代碼也差不多這個意思。
using (var context = NetMQContext.Create()) using (var socket = context.CreatePullSocket()) { socket.Bind("ipc://111"); Thread t = new Thread(() => { using (var context2 = NetMQContext.Create()) { using (var socket2 = context2.CreatePushSocket()) { socket2.Connect("ipc://111"); for (int i = 0; i < 10000; i++) { socket2.Send(DateTime.Now.ToString("O"), Encoding.UTF8); //socket.Receive(); } Thread.Sleep(1); } } }); t.Start(); List<TimeSpan> intervalArr = new List<TimeSpan>(); for (int i = 0; i < 10000; i++) { string word = socket.ReceiveFrameString(Encoding.UTF8); var from = DateTime.Parse(word); var to = DateTime.Now; var interval = to - from; intervalArr.Add(interval); } Console.WriteLine("第{1}次,平均耗時:{0}, 數量:{2}", intervalArr.Average(x => x.TotalMilliseconds), time, intervalArr.Count); time++; Console.ReadLine(); } View Code預想的毫無疑問應該是ZeroMQ系的NetMQ更快,點對點的通訊和本地緩存比使用Redis少了和第三方(Redis)的交互,但實際測試下來,發現在數量級上沒有多大的區別,而且隱隱還是使用Redis比較快。
測試做到這裡,雖然不是很精確,也不知道NetMQ缺了啥,總之這樣的比較結果堅定了我使用Redis的心,何況游戲數據也有很多地方需要仰仗Redis來存儲的呢。