当前位置: 首页 > 科技观察

用户离线实时人像融合技术

时间:2023-03-19 18:31:15 科技观察

1.简介用户画像,即用户信息标注,本质上是对用户进行建模,可以帮助企业快速找到准确的用户群体、用户需求等,反馈信息在当今应用越来越广泛。本文主要描述了用户画像的离线和实时数据链路处理,以及基于特定场景需求的离线和实时画像在线融合的过程。2.背景目前的算法画像服务分为两部分,一部分是离线画像,即批量计算层,依赖于DataWorks每天的T+1调度处理。批处理层通过处理所有现有的历史数据来实现数据的准确性。这意味着它是基于完整的数据集重新计算的,可以修复数据错误;另一部分是实时画像,其数据处理依赖流计算层Flink。基于用户实时行为数据进行流处理,实时更新用户画像。由于两种模式提供的状态不同,我们需要为批处理和流处理提供不同的服务层,并在此之上进行合并。基于此,我们需要对离线和实时人像进行融合处理。整个数据链路大致如下:主要分为批处理层、流处理层、数据融合层三部分。接下来逐一解释每一层的数据链路处理。3.批处理层批处理层依托时序调度,根据用户日常行为数据,通过批处理过程精准计算出用户的离线画像。一方面,利用线下画像补充实时链路的数据;另一方面,在用户冷启动的时候如何补充用户画像,使得算法端请求的时候能够获取到这部分用户的画像。同时,离线画??像数据处理完成后,需要考虑及时将ODPS这部分的离线画像更新到用户画像服务中。这里我们采用懒加载的方式,将离线画像存储在HBASE中,然后根据用户当天第一次启动app的时间来加载用户的离线画像。下面将对这部分懒加载过程进行说明。数据链路如下:主要分为两部分:a.每天定时调度生成日活跃用户线下画像T+1,导入HBASE。b.在步骤1完成的基础上,向HBASE记录一条日志,表示当天T+1的离线画像已经成功写入。日志包括画像的数据量、画像的版本号和一天的完成时间。这里的Log其实是作为判断T+1画像完整性的标志。后续的懒加载过程会根据当天的Log来判断是否加载离线画像,加载多少次。4.流处理层这里的流处理层分为两部分,一个是实时画像,是Flink对订阅用户的实时行为数据进行处理得到的;另一种是实际处理批处理层提供的离线画像,根据用户的实时登录行为懒加载离线画像。上面提到,batch层将用户的离线画像导入HBASE后,通过懒加载的方式将离线画像加载到画像融合框架中。整个懒加载流程如下:大致分为以下几个步骤:订阅者的登录行为被埋在APPSTART中。b.根据订阅的用户登录行为在HBASE中加载离线画像。这里需要说明的一点就是上面提到的HBASE中的画像Log记录,Log是用来判断是否加载画像的。假设当天的T+1画像已经全部导入到HBASE中,当天用户第一次登录时,会加载离线画像,同时使用Flink的State进行记录即用户当天加载了T+1画像,后续用户当天再次登录时,用户再次登录时,不会再次加载离线画像,只加载T+1画像当天一次,减轻HBASE的访问压力;反之,如果用户当天登录,则T+1画像没有Log记录,State会在加载画像时记录用户当天。加载T+2画像后,只有T+1画像完成后用户再次登录时,才会获取最新的离线画像,同时状态记录会发生变化。C。读取标签配置表,根据对应标签的配置信息转换画像的格式和类型,满足算法端的使用。d.将转换后的人像统一成Action格式供人像帧消费,发送到消息队列供后续融合框架消费和实时人像融合。懒加载的整体流程如上所述,这里稍微补充一点,步骤1订阅用户登录埋点APPSTART。实践中,由于埋点上报延迟、网络等一系列原因,可能会导致部分用户离线画像加载延迟。离线画像在用户请求时未加载,导致画像覆盖率下降。基于此,我们通过订阅用户的Init数据(在推荐流请求之前)作为补充触发事件来加载离线画像,从而进一步提高画像的覆盖率。另外一个是Log中版本号的概念,主要是为了容错,防止同一天画像数据版本的迭代更新。我们要求每个迭代版本都对应+1,这样当用户登录时,如果当前版本发生变化,会重新加载最新版本的画像,从而保证用户加载的离线画像版本是最新的。接下来看实时人像的数据链接。整个流程如下:大致分为以下几个步骤:1)Flink订阅用户行为数据,根据画像的具体业务需求对行为数据进行处理。2)将处理后的行为数据发送给Kafka,构建画像框架统一的Action算子。Action包含标签名、标签值、标签对应的处理算子、动作时间等相关信息。3)人像框消费Action信息,根据配置的信息进行相应的operator类型处理。比如处理map、List、String等一系列类型。4)将处理后的实时画像写入Redis。离线画像的懒加载过程和实时画像的处理过程大致如上。最终目的是按照frameworkAction格式发送给Kafka进行画像框架的融合,从而实现离线画像和实时画像的结合。5.人像融合层基于批处理层和流处理层的人像数据。我们需要融合离线画像和实时画像。首先需要明确的是,离线和实时画像的数据格式一定要统一,否则就没有融合。同时,数据处理的口径也必须统一。这样做的好处是在校验数据的时候很容易追溯和定位问题。那么如何进行图像融合呢?这是特定标签的示例。如果标签a是用户的点击行为序列List,该序列包括用户点击的商品的cspuId、用户行为发生的时间、商品推荐渠道等信息。标签a的数据格式如下:[{"cspuId":111,"et":1663234014003,"channel":1},{"cspuId":222,"et":1663234030023,"channel":2},{"cspuId":333,"et":1663234050083,"channel":3},{"cspuId":444,"et":1663234085048,"channel":4}......]画像中配置表,我们首先会配置标签a的相关信息,比如sizeLimt为1000,排序字段为et,根据cspuId去重,et两个字段等。在实时画像层,我们知道用户的实时点击行为会产生实时的点击画像数据。假设生成的实时人像数据如下:{"cspuId":444,"et":1663234085048,"channel":4}基于这个实时人像数据,我们将构建一个统一的Action格式算子.一个配置处理算子的实时tag是list.rpush,也就是说List的add操作会在一个tag上进行。在懒加载层,加载离线标签a的数据格式如下:[{"cspuId":111,"et":1663234014003,"channel":1},{"cspuId":222,"et":1663234030023,"channel":2},{"cspuId":333,"et":1663234050083,"channel":3}]基于这个离线画像,我们还要构建一个统一的Action格式算子,处理算子配置通过离线标签a是list.rpushl,代表List对a标签的addAll操作。画像融合框架在消费Action消息队列时,由于TTL原因,假设用户在Redis中的a标签数据已经清空,画像框架会使用消费的离线标签数据和对应的操作算子来存储a标签数据当用户开始感冒时。使之完整。同时,用户后续生成上述实时人像。同理,实时人像根据对应的操作符添加到标签a中。当然,会根据标签a的配置信息,比如大小,排序字段,取最近的sizeLimit人像。另外,例如,用户的a标签中的数据是历史积累的。这时候可以使用离线画像进行数据恢复。人像融合框架在获取离线人像时,会结合已有的a-tag数据进行去重、sortbyet等一系列操作,以补充实时链路可能出现的数据丢失问题,最终得到完成上述a-tag数据。考虑到不同类型标签的操作差异,人像融合框架会根据需求定制不同的操作算子,从而在算法端灵活应对不同的标签需求。基于此,通过一个简单的标签示例,可以理解图像融合的整个过程。当然,还有更多实践中的细节可以在以后进一步分享。6.把上面描述的整个离线和实时画像的融合环节总结为一个整体。从数据准备、数据处理、数据融合到最后提供一个完整的画像,其实和Lambda架构类似。当然,在批处理层,我们考虑到不同业务领域对T+1日活人画像的完整性要求,采取了不同的处理方式。比如将这部分日常生活写真直接写到Redis中,而不是通过懒加载的方式进行更新,这样算法端本身就可以结合实际场景使用。还有一点是批处理层是否可以进一步优化,降低维护成本。比如HBASE的中间存储,目前正在探索基于每日生成离线画像的快照,直接从ODPS加载,也在进一步探索如何充分利用离线画像。同时降低开发成本。