实时排序-topN排行榜
需求
根据规则实时排序,比如根据焦点主频,共享屏幕,开关麦,开关视频,角色,声音等状态实时排序,返回topN用户。
因为我这边项目是视频会议,所以状态都是通过RTC回调通知我的,当然还有一部分是客户端回调我的,另外一小部分是通过信令实现的。因此我要根据这些回调,信令实时触发topN的计算。
设计方案
因为涉及到实时排序,第一个想到的就是redis
的zset
。那么接下来就应该设计key和score。
key:screen:{roomID}
score: 19位 [音频1位][音量3位][视频1位][角色1位][时间戳(ms)13位]
- 音频:1:关 2:开
- 音量:0-999【3位,数字越大,音量越大;取值[0-999]】
- 视频:1:关 2:开
- 角色:4:主持人 3:联席主持人 2:嘉宾 1:学员(播控、挑屏、会议助理不参与排序,按照角色id从大到小排序)
- 时间戳:回调时间戳
每个人会有一个分数,会利用19位组成一个分数,利用redis
zset
进行排序,取分数最高的N个人。比如:用户1234的分是2100141111111111111(主持人1234,开了音频,音量是100,关了视频,在1111111111111这个时间)。
当客户端或者RTC回调或者信令到达的时候,不断计算分数实现实时计算排序。
架构图
因为是几万人的会议,回调数据量非常大,就用kafka作为消息中间件
优化
因为每次根据回调实时计算排序的结果不同,那么导致会议中topN窗口中的人会实时切换画面,导致体验不好。因此要实现一个相对稳定排序算法。
稳定性排序算法步骤如下:稳定性算法(6步骤):
- 通过排序之后获取top 7成员存储到redis中
- 等下次排序计算之后获取新的top 7成员 我们记为B
- 从redis获取最后一次top 7的成员 我们记为A
- 通过排序算法计算A&B的的相对稳定集合 我们记为C
- 存储C到最后一次top 7缓存中
- 返回C
步骤4排序算法核心思想:两个有序集合A,B,如果成员存在A中但不存在B中,那么删除A中的此成员;如果成员既存在A中也存在B中,那么删除B中的此成员。等这两个步骤执行完成之后,将A中有空位的地方用B去填充,切记B中的元素是有序地按照A中空缺的位置挨个填充的。如果A中没有剩余位置,那么代表结果已经满足top 7,可以正常结束算法了。
总结
技术细节如下:
- 计算排序规则✅
- 接受信令以及所有回调✅
- 所有的回调按照WAL技术先落地日志✅
- 实现统一的回调转发服务,所有信息透传✅
- 根据room_id区分是线上 测试 灰度还是demo✅
- 布局以及其他录制参数存储到redis中或者本地代码中✅
- 多人点击录制/关闭按钮,只有一个人是成功的,加分布式锁✅
- 回调都是进入kafka,然后按需消费✅
- kafka topic区分线上 测试 demo 灰度✅
- 监控kafka topic 队列状况,防止回调信息处理不及时✅
- 异常情况统一归并处理✅