保存到Redis缓存时性能不佳(使用ServiceStack.Redis)

时间:2015-03-29 18:18:02

标签: caching azure redis azure-caching servicestack.redis

在将数据保存到Redis缓存时,我的性能非常差。

情景:

1)使用Redis缓存服务(由Microsoft Azure提供) 2)在Azure上创建的虚拟机中运行代码。
3)VM和Cache服务都在相同的位置上创建

代码段:

    public void MyCustomFunction()
    {
        Stopwatch totalTime = Stopwatch.StartNew();

        RedisEndpoint config = new RedisEndpoint();
        config.Ssl = true;
        config.Host = "redis.redis.cache.windows.net";
        config.Password = Form1.Password;
        config.Port = 6380;
        RedisClient client = new RedisClient(config);

        int j = 0;

        for (int i = 0; i < 500; i++)
        {
            var currentStopWatchTime = Stopwatch.StartNew();
            var msgClient = client.As<Message>();

            List<string> dataToUpload = ClientData.GetRandomData();
            string myCachedItem_1 = dataToUpload[1].ToString();

            Random ran = new Random();
            string newKey = string.Empty;
            newKey = Guid.NewGuid().ToString();

            Message newItem = new Message
            {
                Id = msgClient.GetNextSequence(), // Size : Long variable
                //Id = (long)ran.Next(),
                Key = j.ToString(),             // Size: Int32 variable
                Value = newKey,                 // Size : Guid string variable
                Description = myCachedItem_1    // Size : 5 KB
            };

            string listName = ran.Next(1, 6).ToString();
            msgClient.Lists[listName].Add(newItem);
            //msgClient.Store(newItem);

            Console.WriteLine("Loop Count : " + j++ + " , Total no. of items in List : " + listName + " are : " + msgClient.Lists[listName].Count);

            Console.WriteLine("Current Time: " + currentStopWatchTime.ElapsedMilliseconds + " Total time:" + totalTime.ElapsedMilliseconds);

            Console.WriteLine("Cache saved");
        }
    }

性能(保存时):

注意:(所有时间均以毫秒为单位)

循环次数:0,总数。列表中的项目:2是:1 当前时间:310总时间:342 缓存已保存 循环次数:1,总数。列表中的项目:3是:1 当前时间:6总时间:349 缓存已保存 循环次数:2,总数。列表中的项目:5是:1 当前时间:3总时间:353 缓存已保存 循环次数:3,总数。列表中的项目:5是:2 当前时间:3总时间:356 缓存已保存 循环次数:4,总数。列表中的项目:5是:3 当前时间:3总时间:360 缓存已保存

。 。 。 。

循环次数:330,总数。列表中的项目:4是:69 当前时间:2总时间:7057 缓存已保存
循环次数:331,总数。列表中的项目:4是:70 当前时间:3总时间:7061 缓存已保存
循环次数:332,总数。列表中的项目:4是:71 当前时间:2总时间:7064 缓存已保存

表演(取得时)

清单:1 项目数量:110 时间:57

清单:2 项目数量:90 时间:45

清单:3 项目数量:51 时间:23

清单:4 项目数量:75 时间:32

清单:5 项目数量:63 时间:33

1 个答案:

答案 0 :(得分:0)

如果您正在批量处理,您应该考虑减少正在进行的同步网络请求的数量,以减少延迟,这将成为与网络服务通信时的主要性能问题。

对于此示例,您在致电时正在阅读:

msgClient.GetNextSequence();

和你写的时候写:

msgClient.Lists[listName].Add(newItem);

在单个线程中总共有1000个同步请求/回复网络请求,其中每个操作都是依赖的,必须在下一个操作发送之前完成,这就是网络延迟将成为性能问题的主要原因的原因你应该考虑优化。

批处理请求

如果您正在处理批处理请求,可以通过在单个请求中提取所有ID并使用AddRange()批处理操作存储它们来减少读写次数来大大优化,例如:

var redisMessages = Redis.As<Message>();
const int batchSize = 500;

//fetch next 500 sequence of ids in a single request
var nextIds = redisMessages.GetNextSequence(batchSize); 

var msgBatch = batchSize.Times(i => 
    new Message {
        Id = nextIds - (batchSize - i) + 1,
        Key = i.ToString(), 
        Value = Guid.NewGuid().ToString(),
        Description = "Description"
    });

//Store all messages in a single multi operation request
redisMessages.Lists[listName].AddRange(msgBatch);

这会将1000次redis操作压缩为2次操作。

如果您需要,可以使用以下方式获取所有消息:

var allMsgs = redisMessages.Lists[listName].GetAll();

或使用GetRange(startingFrom,endingAt) API的特定范围。