功能需求:
最近app在做一个为用户自动推荐电台的功能,要求是
- 登录用户,根据用户不同,其听到的电台不同,且用户听的越频繁的电台在用户点击下一曲时出现的概率越大。
- 非登录用户,官方随机推荐。收听次数越多的电台越容易被推荐。
需求分析:
一开始可能会联想到创建两类池子,一类池子是官方推荐的电台的集合,另一类池子是每个用户自己的电台池子。假如,以每个电台的id
作为key
,以收听数作为权重值的话,要想满足收听数越多越容易被推荐有点复杂。
所以,我们可以考虑一下实现两类队列,一类队列用来存储官方电台,一类队列用来存储用户自己常听的电台。当用户点击下一曲的时候,按照一定概率决定是从官方队列里面取电台,还是从用户自己的队列里面取电台。决定好从哪一个队列中取数据,再从这个队列中随机的取出一个数据给用户。
- 如果用户完整的听完此电台,则将此电台加入用户的队列。
- 如果用户没有听完电台点击下一曲,则将此电台从用户的队列中移除。
这样既保证了每个用户很大概率不会听到同一个电台,有保证了再最开始让用户听到热门电台的概率比较大,同时听到自己喜欢的电台的概率也比较大
代码流程:
说了这么多还是直接看代码架构吧,细节就不展示了,我用的是redis
的list
来实现队列。123456789101112131415161718192021222324252627282930313233function getRandomNumber(){ #TODO:计算随机数}function buildRatio(){ #TODO:计算比例}function addAdminQueue(){ #TODO:为官方队列添加电台}function updateQueue(){ #TODO:更新队列}function randomGetFromQueue(){ #TODO:从用户或官方队列随机取数据}function showNext(){ #TODO:step1 获取下一首 #step2: 用户是否喜欢当前所听的电台,若喜欢添加到用户队列,否则从用户队列里面删除当前电台。 #step3:return next}