全民K歌是一款K歌软件,是少数几个已经做到上市的K歌软件,当然还有一款唱吧。那么我们就从全民K歌的业务层来展示如何学习Redis。
首先全民K歌在消息机制中用了生产者-消费者模型, 客户端是消费者消费服务器发送过来的消息,应该是用了Kafka这样的消息队列。业务代码采用PHP或Golang这类支持热更新的语言。
首先,先介绍Redis有哪些结构, 然后全民K歌中如何使用这些数据结构。
-
字符串类型 string
-
哈希类型 hash
-
列表类型 list
-
集合类型 set
-
有序集合类型 zset (哈希表和跳表实现)
首先,今日任务:听歌赢大奖、每日播放歌曲10分钟、分享歌曲、延长一首歌、公开发布一首歌、给好友送鲜花、给他人送K币礼物、观看15秒广告。
直播歌房任务: 观看任意直播间3分钟、 观看欢唱、或多麦歌房10分钟, 在自己的公开歌房上麦3次、 在5个不同的公开歌房上麦5分钟、好友歌房拿麦唱2首歌。
客户端登录后会向服务端获取今日任务和直播歌房任务的配置信息:
PHP代码大致如下(很久没有写PHP了,目前也没有应用场景):
$task = [
"play_music" => [35, 54],
"sing" => [1, 10],
"sending_flower" => [1, 5],
"sending_coin_gift" => [1, 15],
]
大致会有任务次数限制以及奖励的积分。存储的表名一般为 活动名+用户UID。 比如说万圣节活动那么表名为halloween_00001, 那么再用hash去存储用户的任务进度,那么就用hash可以将Redis中存储的数据给取出来。
hset halloween__00001 play_music 1
hget halloween__00001 play_music
具体怎么样防止用户通过工具乱篡改数据以及防止错误输出,那就是逻辑代码的事了。
播放记录和充值记录都是用list来存放。
这里有一个签到记录, 用list来记录。一般表名也是活动名+用户UID。list存储的数据是时间戳+签到金额。例如2021年2月10日对应的时间戳为1612886400, 因为该活动只需要年月日,那么对于时分秒可以忽略不计,那么时间戳可以舍去后面两位,只计16128864,用来节省内存空间, 签到金额为0.53元,那么存储进Redis的数据为16128864_0.53。
2月10日签到
rpush sign_0001 16128864_0.53
2月11日签到
rpush sign_0001 16129728_0.68
2月12日签到
rpush sign_0001 16130592_1.68
如果说只显示20条签到记录
lrange sign_0001 0 20
播放历史也和上面的签到记录同理, 只不过需要记录歌曲ID以及时间戳。
积分榜, 一般都是用zset, 然后用分数+时间戳组成的score,来排序。 不过需要区分日榜、月榜以及年榜等。用时间戳的原因是因为分数一定的情况下,有可能有部分用户一样的分数,但是到达这个分数有时间先后。
举个例子,万圣节活动积分排行榜。表名halloween_rank。利用zset来存储。其中如果是日榜的话, 可以舍去前几位,来减少内存的使用,比如说一天84600s,那么5位相对于10位, 减少了50%的内存占用,周榜和月榜同理。
UID为0001的用户在2021年2月10日13时0分0秒获取了100分
zdd halloween_daily_rank 1001613106000 0001
UID为0043的用户在2021年2月10日15时3分43秒获取了90分
zdd halloween_daily_rank 901613113423 0034
最后用zrange获取排行榜前10名
zrange halloween_daily_rank 0 100
下一次,讲解如何使用HiRedis来调用Redis以及Redis结构的实现。