推荐去重优化方案

2022-09-06  本文已影响0人  shark没有辣椒

项目背景

项目在资源推荐时需要对用户已经看过的资源进行过滤,避免给用户重复推荐。在一次推荐请求中,会基于用户偏好信息拿到大约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硬盘,加上其多线程的优势,也能满足项目的性能要求。

需要解决的问题

整体流程

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

上一篇下一篇

猜你喜欢

热点阅读