深度学习推荐系统实战_14_10_存储模块如何用Redis解决推荐系统特征的存储问题
你好,我是王哲啊,今天我们来解决推荐系统特征存储的问题。
在特征工程编中我们说过,在推荐系统这个大饭馆中啊,特征工程就是负责配料和食材的厨师。
那我们上堂课搭建的推荐服务器就是准备做菜的大厨,配料和食材准备好了,做菜的大厨也已经开火,热锅了。
那这时候我们得把食材及时传到大厨那儿啊,那这个传菜的过程就是推荐系统特征的存储和食取的过程。
可是我们知道类似embedding这样的特征是在离线环境下生成的,而推荐服务器是在线上环境中运行的那这些离线的特征数据是如何导入到线上让推荐服务器使用的呢?今天我们就先NEFLIX的推荐系统架构为例,来讲一讲存储模块在整个系统中的位置,来详细说说推荐系统存储方案的设计原则。
最后以REDS为核心,搭建起spell acxes的存储模块。
好,那我们先来看推荐系统存储模块的设计原则。
我在第一节课的课后题中贴出过netflix推荐系统的架构图,你还记得吗啊? Netflix采用了非常经典的offline nearline和online三层推荐系统。
架构架构图中最核心的位置就是我们在图中用红框标注的部分,它们是三个数据库。
Connra mysql和EV、 cash.这三个数据库就是netflix解决特征和模型参数存储问题的钥匙。
你可能会觉得存储推荐特征和模型这件事情一点都不难啊。
不就是找一个数据库把离线的特征存起来,然后再给推荐服务器,写几个circle,把它们取服器器一定行吗?为什么还要像NEFFS这样兴师动众的搞三个数据库呢?想要弄明白这个问题,我们就得搞清楚设计推荐系统存储模块的原则。
对于推荐服务器来说,由于线上的QPS压力巨大,每次有推荐请求到来,推荐服务器都需要把相关的特征取出,这就要求推荐服务器一定要快。
不仅如此,对于一个成熟的互联网应用来说,它的用户数和物品数一定是巨大的。
几千万上亿的规模是十分常见的,所以对于存储模块来说,这么多用户和特征所需的存储量会特别大。
这个时候事情就难办了,又要存储量大,又要查询快,还要面对高QPS的压力。
很不幸,没有一个独立的数据库,能够经济有高效的单独完成这样复杂的任务。
因此,几乎所有的工业级推荐系统都会做一件事,就是把特征的存储做成分级存储。
把越频繁访问的数据放到越快的数据库甚至缓存中,把海量的全量数据放到便宜。
但是查询速度较慢的数据库中举个不恰当的例子。
如果你把特征数据放到了HDFS的h base中,虽然你可以轻松的放下所有的特征数据,但要让你的推荐服务器直接访问HBAS,进行特征查询。
等到查询完成,这边用户的请求早就超时中断了,而NEFIX的三个数据库正好满足了这样分级存储的需求。
比如说啊NEFIS使用的COSNRA,它作为流行的NO sql数据库,具备大数据存储信息,甚至于它它服服务器高QPS的需求。
我们还需要把最常用的特征和模型参数存入EV cache这样的内存数据库中。
而对于常常用数据据,我们可以把它们储储在高cch等等服务器内器的信息,甚至是服务器的内息总总。
对对于一工程程来来说,我们经需需要在技术上的进行权衡,达成一个在它们存储器上衡衡务器技技方案。
而对对mmyql来说,由于它是一个强强一性的关系型数据库,一般存储的是比比关关的的求强强致性的信息。
比如物品是否可以被推荐这种控制类的信息。
总之,分类的层数系息用户户注注信信息息息品类信息一般是由推荐服务器进行阶段性的拉取,或者利用分级缓存进行阶段性的更新,避免因为过于频繁的访问而压垮mysql.总的来说,推荐系统存储模块的设计原则就是分级存储。
把越频繁访问的数据放到越快的数据库,甚至缓存中,把海量的全量数据放到廉价。
但是查询速度较慢的数据库中,那在我们要实现的项目中,存储模块的设计原则又是怎么应用的呢?那在sprr resets中,我们把存储模块的设计问题进行了一些简化,避免由于系统设计的过于复杂,导致你不易上手。
我们使用基础的文件系统,保存全量的离线特征和模型数据,用REIS保存线上所需的特征和模型数据,使用服务器内存缓存频繁访问的特征。
在实现技术方案之前,对于问题的整体分析永远都是最重要的。
我们需要先确定具体的存储方案。
那这个方案必须精确到哪几存储,对应哪些具体特征和模型数据存储的工具已经知道了。
那特征和模型数据分别是什么呢?这里我们直接应用特征,工程篇为spare bres准备好的一些特征就可以了。
我把他们的具体含义和数据量级整理成了表格,放在了文稿中。
通过初步分析表格中的特征数据,我们得到了三个结论。
首先是用户特征的总数比较大,他们很难全部载入到服务器内存中。
所以我们把用户特征载入到REDIS之类的内存数据库中是合理的。
其次是物品特征的总数比较小。
最后每次用户请求一般只会用到一个用户的特征。
但为了物品推荐推荐服务器,需要访问几乎所有候选物品的特征。
针对这个特点,我们完全可以把所有物品特征阶段性的载入到服务器内存中,大大减少REDIS的线上压力。
最后我们还要找一个地方去存储历史特征数据、样本、数据等体量比较大,但不要求由实时获取的数据。
这个时候分布式文件系统往往是最好的选择。
由于类似HDFS之类的分布式文件系统,具有近乎无限的存储空间。
我们可以把每次处理的全量特征、经次训练的embedding全部保存到分布式文件系统中,方便离线评估时使用。
经过这些分析,我们就得到了具体的存储方案。
主要可以分为三类,一是我们可以用分布式文件系统存储、历次处理得出的全量特征。
二是用内存数据库存储当前版本的所有用户物品的特征。
三是用服务器内存阶段性的全量载入物品特征。
因为文件系统的存储操作非常简单,在spare wes中就是利用spark的输出功能实特征,我们就不重点介绍了。
而服务器内部的存储操作主要是跟REDIS进行交互。
所以接下来我们重点讲讲REDS的特性,以及写入和读取的方法,是当今业界最主流的内存数据库。
那在使用它之前,我们应该清楚REDIS的两个主要特点,一是所有的数据都是以key value的形式存储的那其中key是只能是字符串value可支持的数据结构,包括字符串链表集合、有序集合和哈希。
这个特点决定了REDIS的使用方式。
无论是存储还是获取,都应该以键值队的形式进行,并且根据你的数据特点设计value的数据结构。
二是所有的数据都存储在内存中,磁盘只是在持久化备份或恢复数据时起作用。
那这个特点决定了REDS的特性,一是QPS峰值可以很高,二是数据一丢失。
所以我们在维护REDIS时要充分考虑数据的备份问题,或者说不应该把关键的业务数据唯一的放到REDI中。
但对于可恢复不关乎关键业务逻辑的推荐特征,数据就非常适合利用REDIS提供高效的存储和查询服务。
那在实际的项目中的REDIS部分,我们用到REDIS最基本的操作set get和kids value的数据类型用到了string.接下来就到了实践的部分。
那REDIS的实践流程还是符合我们把大象装冰箱的三部曲,只不过这三步变成了安装REDIS.那把数据写进去,把数据读出来下面,我们逐一来讲一讲。
对对对啊,首先是安装REDI,那REDIS的安装过程在linux环境下非常简单,你可以参照官方网站的步骤依次执行就好。
而windows环境下的安装过程稍微复杂一些,那你可以参考文稿中的这篇文章进行安装。
那在启动REDX之后,如果没有特殊的设置,REDS服务会默认运行在六三七九端口。
那没有特殊的情况呢,可以保留这个默认的设置就可以了。
因为我们的spell rexes也是默认从六三七九端口存储和读取REDIS数据,然后是运行离线程序,通过jealice客户端写入REDIS.在REDIS运行起来之后,我们就可以在离线spar环境下把数据特征写入REDS.那这里我们以第八节课中生成的embedding数据为例,来实现REDIS的特征存储过例。
实际的过程非常简单。
我们利用最常用的REDS java客户端jedice生成REDIC lient最后遍历训练好的embedding向量,将embedding向量以字符串的形式存入REDIS,并设设置过期间。
那具体实现你可以参考文稿中的代码。
最后是在推荐服务器中,把REDIS数据读取出来。
在服务器端,根据刚才梳理出的存储方案,我们希望服务器能够把所有物品embedding阶段性的全部缓存在服务器内部,用户embedding则进行实时查询。
这里缓存物品embedding代码。
那具体实现你可以参考文稿中的代码,你可以看到它的实现过程也并不复杂。
就是先用kease操作,把所有物品embedding前缀的key找出来,然后依次将embedding存入内存。
啊,这样一来,在具体为用户推荐的过程中,我们在利用相似的接口查询出用户的embedding与内存中的物品,embedding进行相似度的计算,就可以得到最终的推荐列表了。
那如果你已经安装好了REDIS,我非常推荐你运行spare x中offline部分的embedding主函数。
先把物品和用户embedding生成,并且插入REDI,然后再运行online部分的rexcess server,看一下推荐服务器有没有正确的。
从REDS中读取用户和物品的embedding,并且产生正确的推荐结果。
那当然在这个过程中要注意把呃online部分server里边的config改成啊data source REDIS.当然除了REDIS,我们还提到了很多不同的缓存和数据库。
那比如ksandra、 EV、 cash、 gov、 ccash等等,他们都是业界非常流行的存储特征的工具。
你有兴趣的话,也可以在课后查询相关的资料进行进一步的学习。
在掌握了我们特征存储的基本原则之后,你也可以在业余时间尝试思考一下每个数据库的不同和他们最合适的应用场景。
好了,今天的内容讲完了,我们一起来做个总结。
那今天我们学习了推荐系统存储模块的设计原则和具体的解决方案,并且利用spare US进行了实战。
啊,在设计推荐系统存储方案的时候,我们一般要遵循分级存储的原则,在开销和性能之间取得权衡。
那在实战中我们安装并操作了内存数据库REDIS啊,你要记住REDI的两个特点就是啊以key value的形式存储,以及啊它是一个纯内存的数据库。
在具体的特征存取过程中,我们应该熟悉利用jealice执行set get等REDIS常用的操作方法。
呃,我也把重点的知识点总结在了文稿中。
你可以再回顾一下,对于搭建一套完整的推荐服务来说,我们已经迈过了两大难关,分别是jackty server搭建推荐服务器,以及用REDIS解决特征存储的问题。
下节课我们会一起来挑战线上服务中召回层的设计问题。
课程的最后我们一起来看到思考题。
呃,你觉得课程中存储embedding的方式还有优化的空间吗?除了string,我们是不是还可以用其他reallies value的数据结构存储ebedding数据?那从效率的角度来考虑,使用string和使用其他的数据结构的优缺点有哪些呢?为什么?欢迎你把你的思考和答案写在留言区,也欢迎你把这节课分享给你的朋友,我们下节课见。