其他分享
首页 > 其他分享> > 场景之在线人数或者粉丝查询实现

场景之在线人数或者粉丝查询实现

作者:互联网

直播间在线人数或者粉丝查询

一、主要功能

通常对于一些实时在线业务中,比如直播业务中的主播,希望让主播看到直播间实时在线粉丝数等数据,从而从数据方面提升主播的整体直播体验。

二、简单方案:

最简单的方案就是通过所有在线人数判断与主播是否构成粉丝关系,每个人进入直播间会产生记录,根据用户ID去遍历主播与用户的关系表,判断记录中is_follow关系是否为1,为1用户则为主播粉丝,记录下来,遍历整张表结束则可以统计出在线粉丝人数。
缺点:对于在线粉丝查询这一功能而言,是相对实时更新并且主播端请求频率比较高的操作,如果每次查询根据每个在线的用户再去扫描表,即使是扫描从库也是很耗时,因此是不可取的。而对于主播而言短暂的粉丝数量误差延迟是可以接受的,所以考虑引入redis进行缓存记录。

三、涉及场景

也就是记录在线粉丝功能中涉及到的主要接口

四、可选方案

利用redis的不同数据结构记录在线粉丝。

1、采用有序集合

用户上线时候,判断构成粉丝关系,则采用ZADD,将用户以及在线时间添加集合中,其中live_id是直播间id,用主播id或者直播id区分不同的在线粉丝集合。current_timestamp是进入直播间时间戳。

ZADD "online-fans:live_id"  <user_id> <current_timestamp>

通过ZCARD命令查看集合中的数量,也就是在线粉丝个数

ZCARD “online-fans:live_id”

通过ZCOUNT 查看某一时段进入直播间的粉丝。

COUNT "online-fans:live_id" <start_timestamp> <end_timestamp>

2、采用集合

使用有序集合能够同时储存粉丝的id以及上线时间戳, 但如果只想要记录在线的id, 而不想要储存上线时间, 那么也可以使用集合来代替有序集合进行记录。

当进入直播间,判断是否是粉丝, 执行 SADD 命令将它添加到在线记录中当中:

SADD "online-fans:live_id" <user_id>

通过使用 SISMEMBER 命令, 可以检查粉丝是否在直播间:

SISMEMBER "online-fans:live_id" <user_id>

统计在线粉丝数则可以通过执行 SCARD 命令来完成:

SCARD "online-fans:live_id"

与有序集合相同的是,都是集合类型,可以进行一些交集和并集的聚合操作,比如交集判断连续一周都在直播间的粉丝,并集可以查看一周之内出现在直播间的粉丝等数据。

3、采用Bitmap

使用有序集合或者集合能够储存具体的在线用户名单, 但是却在粉丝量在线大的时候需要消耗比较多的内存;
bitmap相对来说既能够获得在线用户名单, 又可以尽量减少内存消耗。Redis 的位图就是一个由二进制位组成的数组, 通过将数组中的每个二进制位与用户 ID 进行一一对应, 使用位图可以去记录每个粉丝是否在线。

当一个用户进入直播间时,判如果是粉丝,使用 SETBIT 命令, 将这个用户对应的二进制位设置为 1

SETBIT "online-fans:live_id <user_id> 1

通过使用 GETBIT 命令去检查一个二进制位的值是否为 1 , 判断粉丝是否在线:

GETBIT "online-fans:live_id" <user_id>

通过 BITCOUNT 命令, 统计出位图中有多少个二进制位被设置成了1,也即是有多少个粉丝直播间在线:

BITCOUNT "online-fans:live_id"

同样由于,bitmap是用0,1表示对应的粉丝是否在线,也可以多个记录的bitmap形成与或非运算,计算多个时段或者多个直播间在线的粉丝数。

五、实际方案

综合实际的情况和要求,采用集合记录在线粉丝人数。

1、定义redis集合

设置一个集合,具体如下

key = "online-fans:live_id"
value = {user_id1, user_id2, user_id3....}

其中live_id是直播间或者直播场次id,也用主播id定义,集合中记录用户的user_id即可

2、修改对应场景下的操作

具体操作包括

SADD "online-fans:live_id" <user_id>
EXPIRE "online-fans:live_id"  6*60*60 
SREM  "online-fans:live_id" <user_id>
DEL "online-fans:live_id" <user_id>
UNLINK  "online-fans:live_id" <user_id>

具体的redis删除集合的命令有两个,一个是del,一个是unlink,具体的是由于redis在执行命令操作的时候是一般是单线程的,因此如果是当在线粉丝人数过多导致集合很大的时候,业务流程中执行del操作,会有延迟。因此可以采用单开一个协程或者线程去异步非阻塞执行del操作或者直接使用unlink命令直接返回删除结果,让redis单开一个额外的线程去执行删除操作,不阻塞后端流程。

标签:场景,直播间,在线,查询,live,粉丝,id,主播
来源: https://www.cnblogs.com/welan/p/16516052.html