美文网首页
推荐去重优化方案

推荐去重优化方案

作者: shark没有辣椒 | 来源:发表于2022-09-06 20:34 被阅读0次

    项目背景

    项目在资源推荐时需要对用户已经看过的资源进行过滤,避免给用户重复推荐。在一次推荐请求中,会基于用户偏好信息拿到大约5000条数据,然后过滤用户已经看过的资源,再根据排序值返回匹配度较高的资源。

    之前策略

    之前推荐是服务端将播放埋点上报的资源和下发给客户端的资源分别以不同的Key写入Redis ZSet,在推荐程序中,直接读取Redis里对应用户的播放和下发记录(整个ZSet),基于内存中的Set结构实现去重。

    资源去重本身是基于用户实际看过的资源进行过滤,但考虑到实际看的资源是通过客户端埋点上报,存在一定的时延,因此服务端会保存用户最近100条下发记录用于去重,这样就保证了即使客户端埋点还未上报上来,也不会给用户推荐了已经看过的资源。

    方案主要问题是占用Redis内存非常大,因为资源Id是以原始字符串形式存在Redis Zset中,虽然将单用户最大存储长度保留为5000,但实际占用仍然非常高,每个资源id八位数,在zset中5000条大约占用500k,500k * 2000万用户 / 1024 /1024 ≈ 10000G,最大可能需要占用将近10T的空间。随着用户增多,为了避免redis内存失控,在占用将近redis内存10G的时候,及时进行了调整。

    具体方案

    存储形式

    去重场景是典型的只需要判断是否存在即可,因此并不需要把原始的资源ID存储下来,目前比较常用的方案是使用布隆过滤器(之前有介绍过https://www.jianshu.com/p/bbc66c2708e3)存储视频的多个Hash值,可降低存储空间数倍甚至十几倍
    通过比较发现,同样5000个id,放到自定义布隆过滤器中,然后再存储到redis中,占用了约10kb,相比于之前的500kb,节约了大约98%的空间。

    存储介质

    即使修改了存储形式,但是Redis存储容量仍然非常大,需要占用很多内存资源,所以修改为使用pika(基于rocksDB)进行存储,虽然pika性能不如redis,但是其使用的是磁盘资源,相比内存在容量上优势非常明显,而且pika搭配ssd硬盘,加上其多线程的优势,也能满足项目的性能要求。

    需要解决的问题

    • 布隆过滤器无法删除的问题:布隆过滤器数据无法删除,无法实现推荐过资源过期策略,经与产品协议,修改为过期时间为一个月,这样可以把用户一个月的推荐数据分为三份存储,每份10天,每次取最近三个10天周期的数据,加上当前未满10天的数据,超过此周期的数据可以删除,就解决了布隆过滤器无法删除的问题。
    • 布隆过滤器读写IO多的问题:因为用户是在不断拉取推荐数据,客户端也不断上报看过的数据,这就导致IO非常多,影响性能,优化方案是客户端上报的数据,先暂存到redis,然后每隔十分钟,将redis里的数据批量加入到布隆过滤器,这样可以减少非常多的io消耗。

    整体流程

    获取用户推荐数据 -> pika中拿到该用户近30天布隆过滤器数据 -> 下发客户端 -> 客户端记录用户看过资源,并上报 -> 上报的数据暂存到redis -> 系统定时从redis拿到上报数据,然后加入布隆过滤器

    相关文章

      网友评论

          本文标题:推荐去重优化方案

          本文链接:https://www.haomeiwen.com/subject/fomgnrtx.html