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

     

  • 相关阅读:
    spring(2)
    Android之滑动按钮实现Demo
    spring(1)
    spring(4)
    Android之ImageSwitch控件
    使用非阻塞ServerSocketChannel、SocketChannel代替ServerSocket和Socket
    Android之界面刷新(invalidate和postInvalidate使用)
    Android之改变控件的背景及形态
    Android之获得内存剩余大小与总大小
    OpenCV中矩阵的归一化
  • 原文地址:https://www.cnblogs.com/pasoraku/p/4673039.html
Copyright © 2011-2022 走看看