一、前言
- 使用redis实现
- 基于直播间业务场景
- 不阐述详细实现细节
二、相关Redis数据结构和命令
Redis 集合(Set)
- Sismember 命令判断成员元素是否是集合的成员。
Redis 有序集合(sorted set)
- Zrevrank 命令返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。
- Zincrby 命令对有序集合中指定成员的分数加上增量 increment
- Zrevrangebyscore 返回有序集中指定分数区间内的所有的成员。有序集成员按分数值递减(从大到小)的次序排列
- Zremrangebyrank 命令用于移除有序集中,指定排名(rank)区间内的所有成员。
其他
- 查找特定前缀key:scan命令
三、如何实现
榜单保存
- 使用 Redis 有序集合(sorted set)保存榜单数据
- 如果是按时间排序的榜单,把时间戳存到score字段;如果是按礼物数量排序,把数量存到score;其他排序场景同理
榜单添加数据操作幂等
- 使用数据库日志表(唯一索引) (最严格可靠)
- 使用一个set保存所有的消息ID,并使用sismember防止重复处理(并发场景可能不幂等)
数据清理
- 使用一个set保存现有所有在线的房间榜单;定时任务检查房间是否在播,不在线的进行清理(同时可以监听房间下播时间)
- 保存一定数量的redis榜单:Zremrangebyrank 命令用于移除有序集中,指定排名(rank)区间内的所有成员
- 使用scan命令 查找特定前缀key的榜单,同1或2操作进行清理
四、扩展
- 房间榜单的标识是房间id有时可能不够,因为通过榜单有时是和本场开播挂钩的,同一个房间多次开播,可能导致不同场次的数据导致榜单错误。
增加房间开播id标识可以解决。 - 老生常谈的哲学问题:二八定理。花费大量时间来得到较低的收益,实现时要从业务看是否值得。但不代表在做设计方案时不去考虑,这是严谨性的问题。
按极端的方式考虑,实际实现按业务需要进行选择折中。