zoukankan      html  css  js  c++  java
  • 记一次Redis和NetMQ的测试

    Redis是一个高速缓存K-V数据库,而NetMQ是ZeroMQ的C#实现版本,两者是完全不同的东西。

    最近做游戏服务器的时候想到,如果选择一个组件来做服务器间通信的话,ZeroMQ绝对是一个不错的选择,而我们的服务器是用C#的开发的,就这样,找到了NetMQ。

    NetMQ上手很简单。总结一下大致如下几个步骤:

    1. NuGet安装类库引用
    2. 创建NetMQContext
    3. 根据需要的通讯模型创建NetMQSocket
    4. 监听socket.Bind()或者连接socket.Connect()
    5. 发送socket.Send()或者接收socket.Receive()
    6. 释放NetMQSocket和NetMQContext

    简单的代码如下

    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 edis-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来存储的呢。

     

  • 相关阅读:
    Luogu 1080 【NOIP2012】国王游戏 (贪心,高精度)
    Luogu 1314 【NOIP2011】聪明的质检员 (二分)
    Luogu 1315 【NOIP2011】观光公交 (贪心)
    Luogu 1312 【NOIP2011】玛雅游戏 (搜索)
    Luogu 1525 【NOIP2010】关押罪犯 (贪心,并查集)
    Luogu 1514 引水入城 (搜索,动态规划)
    UVA 1394 And Then There Was One / Gym 101415A And Then There Was One / UVAlive 3882 And Then There Was One / POJ 3517 And Then There Was One / Aizu 1275 And Then There Was One (动态规划,思维题)
    Luogu 1437 [HNOI2004]敲砖块 (动态规划)
    Luogu 1941 【NOIP2014】飞扬的小鸟 (动态规划)
    HDU 1176 免费馅饼 (动态规划)
  • 原文地址:https://www.cnblogs.com/pasoraku/p/4673039.html
Copyright © 2011-2022 走看看