​周锦民:腾讯在线教育视频互动直播间技术实践 (3)

成员列表的初期版本,采用了代理加CKV存储的方式。CKV是腾讯内部的自研的key-value数据库。每个房间的成员列表用pb序列化后存入ckv,需要读取时是整体读出来再进行反序列化使用,这种方式存储几个问题。

第一,当房间用户量过多,频繁进出房间产生大量的网络IO。一个用户信息现在有40Bytes,如果有1万人的话,成员列表就有400多K。如果是使用高峰期的时候,大量的网络IO,网卡就成为了瓶颈。

第二,CAS冲突严重。因为对ckv服务进行频繁的更新、删除、修改操作,会造成大量cas冲突,这样会影响到服务性能。

第三,读写性能低。ckv get的方式,长列表反序列化耗时。总体上性能还打不到200qps,超时比较严重。目前我们的用户量已经高了很多,目前的架构已经无法满足现在的需求,新版我们做了改造。

​周锦民:腾讯在线教育视频互动直播间技术实践

新版的改造我们怎么做了? 我们调研了几种存储选型。

首先是redis,它是支持成员列表和排行榜存储。但我们的业务成员列表需要有定制化的查询需求,例如按照版本号查询,按照平台类型查询等,还需要支持分页。在这一块,redis的数据结构支持不够。

第二个是grocery,是腾讯内部自研的存储方案,采用的是多阶hash的方式,它完美支持现在成员列表的存储选型。问题是它的长度有限,最多支持5000人,现在QQ列表在用。但我们单房间现在人数已经超过w级别,所以这种方案现在也不适合。

第三个是分级ilst,用于微博的场景,它支持超长列表。主要用于离线paas,延时较高。

第四个是phxkv,phxkv是微信出的一个解决方案,基于phxkv协议,强一致性、性能好。这个方案我目前在调研中。

目前我们最终采用的是内存存储,多主同步的设计方案。它由如下几个特点:

全内存结构,使用二级hash_map结构,c++stl的标准数据结构,多主模式。最终一致性模型,写完就返回,性能好,靠心跳来修复。单set性能可到3w qps。

扩展性,按照业务bid来分档存储,按照proxy来中转,保证可扩展性。

内存列表数据每3分钟dump到虚拟磁盘,保证重启快速恢复。

一致性:

1)心跳修复, 保证最终一致性

2)同时提供强一致性的api能力, 通过多读方式实现。

消息push优化

消息push优化前,每个逻辑服务独自拉成员列表,还要制定对应的每个通道的push代理。此方案的缺点是代码非常冗余,没有统一的接口,模块间的强耦合。现在这个方案是无法满足我们的需求快速迭代开发,所以我们对这个方案进行了改造。

新版消息push改造方案,新版push主要分三块:push_proxy统一接入层,引入腾讯云的ckafka做消息缓冲, 引入redis做异步消息存储。

push_proxy支持多种业务定制push方式: 单播、广播、指定人、指定角色、指定端。

我们对push服务做了性能优化:

pushProxy采用的是进程级cache,缓存大房间(>2000人)成员列表,2s超时。 小房间实时啦成员列表,保证push实时性。 怎么使用cache的。全局还是进程级的?

消息分级:重要和非重要消息。如果消息比较少,那么就直接推送,过多就走消息合并机制。 这是msg_center能力,能够实时累计消息数,超过阀值采用合并推送

另外, 老师客户端也是提供直接禁言能力,防止恶意用户刷屏。

房间大班拆小班,分小班推送,避免聊天消息滚屏,增强用户体验。

容灾降级我们怎么做呢?

在正常情况下,老师端可以主动禁言。

另外支持全局流控,以时间戳(s)为单位,限制向下游push的消息总量。每当pushProxy的qps超过了3k/s,就反馈到edu_msg_center降低聊天消息频率, 以此保证重要消息正常push。

最后是消息可靠性的实践:

消息实时推送, 异步保存redis, 采用kafka消息队列能力缓解扩散写压力。

客户端如果丢消息怎么办? 处理方案:每个用户收到的push消息都带有严格自增的msgid,客户端维护已收到的最大msgid和缺失的msgid列表; 定时2s上报丢失的msgid列表和收到的最大msgid, 后台返回丢失的消息列表。通过这样的方式来解决丢消息问题。

获取更多详细资料,请戳以下链接:
周锦民:腾讯在线教育视频互动直播间技术实践.pdf

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjfxp.html