如何将Redis Value []转换为反序列化对象c#?

问题描述

我正在研究Webjob中的列表排序。 当我使用c#List时,它工作正常。但是为了提高性能,我将数据以列表的形式保存到Redis缓存中。

我的最终目标是仅提取最近5分钟的最新数据。

有效的c#代码-

public class MyObject
    {
        public uint InstrumentID { get; set; }
        public decimal Close { get; set; }
        public decimal High { get; set; }
        public decimal Low { get; set; }
        public decimal Open { get; set; }
        public DateTime TimeStamp { get; set; }
        public uint Volume { get; set; }

        public DateTime Created { get; } = DateTime.Now;
        public DateTime Ttl { get; } = DateTime.Now.AddMinutes(5);
        public DateTime? Persisted { get; set; }

        public bool IsDead => DateTime.Now > Ttl;
        public bool IsPersisted => Persisted.HasValue;
        public bool TimetoPersist => IsPersisted == false && DateTime.Now > Created.AddMinutes(5);

        public DateTime GetStartOfPeriodByMins(int numMinutes)
        {
            int oldMinutes = TimeStamp.Minute;
            int newMinutes = (oldMinutes / numMinutes) * numMinutes;

            DateTime startOfPeriod = new DateTime(TimeStamp.Year,TimeStamp.Month,TimeStamp.Day,TimeStamp.Hour,newMinutes,0);

            return startOfPeriod;
        }
    }

var inputList = new SortedSet<MyObject>(new MyObjectComparer());

            inputList.Add(new MyObject() { TimeStamp = DateTime.Now,Open = 9,High = 12,Low = 8,Close = 11,InstrumentID = 2526 });
            Thread.Sleep(10000);
            inputList.Add(new MyObject() { TimeStamp = DateTime.Now,InstrumentID = 2526 });
            Thread.Sleep(50000);
            inputList.Add(new MyObject() { TimeStamp = DateTime.Now,InstrumentID = 2526 });

            var resultSet = inputList
                .GroupBy(i => i.GetStartOfPeriodByMins(5))
                .Select(gr =>
               new
               {
                   StartOfPeriod = gr.Key,Min = gr.Min(item => item.Open),Max = gr.Max(item => item.Open),Open = gr.OrderBy(item => item.TimeStamp).First().Open,Close = gr.OrderBy(item => item.TimeStamp).Last().Open
               });

现在我正在不断将相同的记录插入Redis缓存中。并且虽然尝试获取最后5分钟的数据,但我还是想使用相同的GetStartOfPeriodByMins概念,但是它需要MyObject类的列表,并且redis返回RedisValue []。

Redis代码-使用StackExchange.Redis程序包

var cache = RedisConnectorHelper.Connection.GetDatabase();

            //int i = 0;
            for (int i = 0; i < 10000; i++)
            {
                var tickDataHis = new MyObject()
                {
                    InstrumentID = 2526,Close = 14 + i,High = 16 + i,Low = 11 + i,Open = 12 + i,TimeStamp = DateTime.Now,Volume = 11111
                };

                // insert into redis
                cache.ListRightPush("tickData",JsonConvert.SerializeObject(tickDataHis));

                Thread.Sleep(3000);
            }

            var inputList = cache.ListRange("tickData");

还是有其他方法可以从Redis获取最新的5分钟数据 缓存?

enter image description here

解决方法

我过去使用Redis存储时间序列数据。为了优化数据检索,我使用了一个排序的集合(在这种情况下,有多个集合,但是概念是相同的),其中分数是记录数据的unix时间戳,我使用{ {1}}库。

代码是这样的:

Newtonsoft.Json

通过这种方式,如果您只想检索 最近5分钟的数据,则可以使用var myData = new MyObject() { SomeProperty = "my text" }; long dataTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); string serializedData = Newtonsoft.Json.JsonConvert.Convert(myData); redisDb.SortedSetAdd("mySortedSet",dataTimestamp,serializedData); 方法并通过传递“ now- 5分钟”作为起始分数,这样您就可以只对需要的内容进行反序列化(这当然比对整个列表进行反序列化要便宜):

SortedSetRangeByScore

之后,您可以在linq的帮助下轻松地反序列化数据(考虑到var minutesToTake = 5; long startingTime = DateTimeOffset.Now.AddMinutes(-minutesToTake).ToUnixTimeMilliseconds(); RedisValue[] redisData = redisDb.SortedSetRangeByScore("mySortedSet",startingTime); 实现了运算符到字符串的转换):

RedisValue

编辑:我没有使用@Hasan EmrahSüngü建议的软件包。也许它更有效,我只是在解释我当时的工作。

编辑2 MyObject[] myData = redisData.Select(d => JsonConvert.DeserializeObject<MyObject>(d)).ToArray(); 是我的redisDb实例。

编辑3 :有用的参考链接: