大规模业务数据延迟落地,以及实时IM消息通知



遇到的问题:

目前流行的直播行业中,产品会鼓励用户多与主播互动,而互动火热的体现,则是通过上图最右方的人气值体现。

目前常规的互动为聊天,送礼,点赞,关注,宋星星,分享。其中聊天,送礼,点赞,都是频率较高的互动。

系统要根据这些互动计算图右侧的人气值,并返回给用户,而且人气值需要持久处理。

笔者所遇到的问题是,实时计算互动,并存储时,能否降低写库的次数,以及推送IM的次数。

如果当前房间十分火热,

聊天tps500  送礼tps300 点赞tps500 我不希望我每秒会为了更新人气,更新1000多次,并且IM推送上行1000多次,IM下行是给房间里的

每一个人推送,那么次数更是不可设想。

如何减轻库的写压力,以及IM服务的压力,是这次要解决的问题。

总体图:



上图是该业务的总体结构图,每个业务有自己的业务消息总线,如发言,点赞等,消息中间件采用kafka,比如我现在是需要接受消息更新人气,用户经验等,所以我定义了一个新的消费组community-esb,消费组收到各业务线的消息后,通过调用人气服务,以及经验服务来更新主播的人气值,互动发生源用户的经验值。消息body基本都是这样的,比如聊天:

{userId:<userId>,targetUserId<targetUserId>,roomId<roomId>,message<message>}

消费者会根据消息体内的详细内容进行加人气处理,比如送礼会看礼物个数,点赞会看点赞次数等,这里不再赘述。

上述规划图中,这个部分是要解决的问题

起初想到的三种解决方式:

A,

//增加人气值,用户进入房间获取,或推送都从这里获取

Long total=Increase(AnchorPopularKey,value);

//获取锁

String timeStamp = getAnchorLockKey(anchor)  1

如果锁存在,并且未失效,则直接返回

If(value!=null && System.currentTime-value<15s){Return;}

//这里有并发问题

//锁不存在,则设置锁,并更新db 推送IM

setAnchorLockKey(anchor,random(3,12)s)

Insert DB total

sendIM total

A方式的大致思路为:缓存中存储主播的总人气值,业务需要读取时也从这里读取,人气服务计算好需要增加的人气值时,

直接调用redis increase操作,那么什么时候进行落地呢?设置另外一个ttl key,失效时间为3~10秒,当key失效时,则进行落地操作,

以及推送IM操作,如果希望前端更新快,则时间可设置短一些。

优点:这种方式网络开销相对较少,策略验证是否需要落地只用了一次网络IO

缺点:

        1,因为redis存的是人气总值,而需要保证redis里的总值与数据库总值完全相同较难。而且最后落地时,是将redis的总值

              直接做覆盖操作,很有可能总值之前是100,覆盖后变98

         2,最后的落地操作,以及推送IM操作,存在并发问题,因为为了达到较大吞吐量,增加消费消息效率,

               消费组的进程数与kafka设置的patition数量相同,当多个进程同时消费时,可能会同时进行落地操作,

               以及推送IM操作,比较浪费。

B,

//增加人气值,//增加人气值,用户进入房间获取,或推送都从这里获取

Long total=Increase(AnchorPopularKey,value);

//获取锁

Boolean set = setIfAbsent(anchorLock2(anchor),System.currentTime);  1

If(set){

//获取到了锁,入库,推IM

Insert DB total;

sendIM total;

重新设置锁(3~12秒)失效

setExpire(anchorLock2(anchor),random(3,12)s);

}else{

//获取锁的设置时间

timeStamp = get(anchorLock2(anchor));  2

//如果锁设置时间已过15秒,说明锁已经失效,之前设置失效失败,删除锁

if(System.currentTime-timeStamp>15s){

delete(anchorLock2);

}

}

方式B算是方式A的改进,为了解决并发数据落地的问题,不过这种方式,增加了一个分布式锁,多了一次网络IO消耗。


C,

TASK 60秒一次。。。或10秒一次

for(Room room:ShowingRoomList){

//获取缓存中的人气值

Popular p = popularService.get(room);

//上次推送至今,房间人气值有变化,给予推送更新

if(redis.get(room)!=p.getPopular()){

insertDb;

sendIm

redis.set(room)

}

}


C方式与A B方式完全不同,C是通过另起一个进程跑task,然后异步将人气值落地,以及推送IM,但是

还是需要消费者做redis.increase操作,只是消费者不再负责数据落地,以及推送了。

结论:

1,起初设置一个缓存总人气值是为了顺便抗读压力,不过上述几种方式经过反复推演,首先难以解决的问题就是,如果你在缓存中存储一个总值,那么你用数据库覆盖缓存可以,如果用缓存覆盖数据库,将十分危险,而且难以保证准确性。

2,A,B方式均存在很多不必要的网络开销或数据库开销,需要在两者之间做均衡。C方式另起进程,使得业务不聚合,消费组不能自己

完成任务,需要依赖另一个进程。而且,单进程存在单点问题。不过C方式相对来讲,更可控些,因为单进程,所以不存在过多的数据库开销,以及网络开销。

最后决定,弃用缓存存人气总值的方式,通过增量更新人气总值。

设计图如下:



代码如下:


这种方式的思路是,将一分钟时间分为30个时间片,线程将根据当前系统时间,将人气值累加存储到当前时间片内,

落地时则是存储上一个时间片的累加值,并且为增量更新。这样可控制一个房间内的落地以及推送IM频率,最多为30次。

通过redis的原子操作,选取leader,来进行落地,推送,失效操作,防止并发问题。同时,当房间内互动频率不高时,

则实时落地推送,增强用户体验。

当然,我们现在的业务量还不大~服务上线后监控图如下:

由图可见,互动产生累加人气操作tps在晚上比较高,可以达到90左右,而那时,实时落地的tps为2.5。也就是说房间内就算互动再频繁,

右上角的人气变化大约是2秒一变。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,285评论 25 707
  • 这一趟要去的是越南版的“大上海”胡志明,以前没去过,坦白地说,此行主要是去看美女的,当然还有那么一点小小的目的.....
    吉娃文创阅读 280评论 0 0
  • 百度云盘新增了文件夹属性,实际上是对用户做了什么假定? 11月份百度云盘进行了改版升级,本次升级新增文件夹属性,图...
    临岸观潮雨阅读 1,329评论 0 51
  • 今天是考研的第一天,但我没有走进考场,我不知道怎么面对你们,却有好多话想对你们说 这段日子的糟糕,你们应该隐约感觉...
    景昕阅读 236评论 0 0
  • “ 世事如书,我偏爰你这一句,愿做个逗号,呆在你脚边。但你有自己的朗读者,而我只是个摆渡人。” (一)你还是你,一...
    豆四吧阅读 226评论 0 1