前言

最近遇到一个问题,就是接收第三方数据的时候,

redis set 冲突怎么办 redis如何解决set数据量大_mysql

类似这种直播数据,由于业务的缘故,导致对方给的数据每次都是全量的,

而且请求很频繁,有时候一秒好几十次。直播数据一般都是刷刷刷的,这个大家或多或少有看比赛,会知道。

对方给数据的模式

第一次100条数据,第二次只是多了1条,但是下发的101条。。。,

第n次可能会把前面的数据改了或者删除。。。

如果仅仅只是接收数据,那其实没什么大问题。

问题

我们的业务需求是接收到数据立马要增量呈现给客户,而且必须要快。

大家都知道,直播一旦延迟了 ,那么数据的意义就不大了,尤其是那种重要的比赛。

那么问题来了

对方给的是全量的,而且数据是没有对应排序id、时间之类的,说的白一点就是一条条字符串,但是我们呈现给自己客户的是要增量数据,所以进行全量比对是不行的,因为太慢了。

所以通过入库加索引去重这种方式是不可行的。

那么怎么做到,既快速判断,又增量提取数据呢

思路

这里我们借助redis  set 来实现

下面来看下set概念

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

集合对象的编码可以是 intset 或者 hashtable。

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

借助set  我们先去判断数据是否存在。

if (startflag && IsSetContainsItem(textLive, GetCalcMD5(textLive)))
                    {
                        //存在
                        continue;
                    }
                    else
                    {
                        startflag = false;
                        //不存在
                        tmaxOrder++;
                        textLive.Order = tmaxOrder;


                        textLiveList.Add(textLive);
                        SetAddSet(textLive);
                        TextLiveBll.InsertQueue(textLive);
                    }
public bool IsSetContainsItem(MatTextLive textLive, string value)
        {
            try
            {
                string setId = textLive.MatchId + textLive.Round;
                return MatchRedisManager.IsSetContainsItem(setId, value);
            }
            catch (Exception ex)
            {
                _Logger.Error(ex.ToString());
                return false;
            }
        }

存在的话,说明之前处理过了,不在处理。

if (startflag && IsSetContainsItem(textLive, GetCalcMD5(textLive)))
                    {
                        //存在
                        continue;
                    }

不存在,就添加进去set,然后直接返回客户,在异步入库。

else
                    {
                        startflag = false;
                        //不存在
                        tmaxOrder++;
                        textLive.Order = tmaxOrder;


                        textLiveList.Add(textLive);
                        SetAddSet(textLive);
                        TextLiveBll.InsertQueue(textLive);
                    }
/// <summary>
        /// 添加 set
        /// </summary>
        /// <param name="textLive"></param>
        public void SetAddSet(MatTextLive textLive)
        {
            try
            {
                MatTextLive info = new MatTextLive
                {
                    HomeScore = textLive.HomeScore,
                    MatchId = textLive.MatchId,
                    Round = textLive.Round,
                    TeamPosition = textLive.TeamPosition,
                    Text = textLive.Text,
                    TimeText = textLive.TimeText,
                    VisitScore = textLive.VisitScore
                };
                string setId = textLive.MatchId + textLive.Round;
                string value = MD5Helper.CalcMD5(JsonConvert.SerializeObject(info));
                MatchRedisManager.AddSet(setId, value);
                RedisManager.ExpireEntryAt(setId, DateTime.Now.AddHours(6));
            }
            catch (Exception ex)
            {
                _Logger.Error(ex.ToString());
            }
        }

这样,就避免了过多的数据拆分计算或者入库之类造成的数据延迟之类的,在几毫秒的时间内就能把数据处理完成,达到业务需求。