百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

闲鱼如何高效打造一个多业务、低侵入的搜索链路

liebian365 2024-10-29 15:53 6 浏览 0 评论

问题及现状

闲鱼搜索很多场景基于集团搜索中台能力,纵观闲鱼搜索链路,存在多角色(工程、算法工程、算法等)、多业务(闲鱼无忧购、租房、帖子等)、多节点(离线数据源聚合、在线召回、URF Rank等),具有明显的复杂性。并且闲鱼主搜仅存在一条链路支持搜索多业务发展,各角色、各业务、各节点处于高耦合串行迭代模式。在大数据量、多业务、多角色并行场景下,以下问题日益明显:

1、迭代效率低、排期长,无法满足新业务快速迭代诉求:主要体现在数据量大,单次迭代周期长,以及多业务、多角色串行操作,耦合严重;

2、风险高:不同业务、不同特性均在主引擎召回链路执行修改,侵入大,风险高;

3、干预能力弱,业务间混排能力不足:缺少干预扶持能力,无法有效为创新业务提供定制化孵化能力。

闲鱼一次请求完整流程如下:

注:QP,即Query Planner,主要用于预测用户query搜索意图。

SP在测试环节下调用拓扑示例如下:

关键节点:

blender是SP服务核心入口,主要职责包括解析用户query意图、引擎分页召回、搜索数据补齐等功能。

uniq_session是召回核心入口,通过引擎召回、分页处理、URF Rank等操作,获取最终商品列表

ha3_searcher是引擎召回入口,翻译用户query为HA3引擎查询query,请求引擎在线服务,召回满足条件商品信息

uniq_summary是商品信息补充入口,依据商品id列表,补齐商品详细信息并返回,最终在搜索结果页呈现给用户

背景概述

闲鱼搜索很多场景基于集团搜索中台能力,搜索引擎分为数据源聚合(离线dump)、全量/增量/实时索引构建及在线服务等部分,通过集团内部一系列处理阶段,对客户提供高可用高性能的搜索服务。服务架构如下:

其中:

SP/SPL是集团内一套构建于Wunder上的开发工具,提供开发测试打包上线的视图界面以及一套业务函数库。HA3是一套基于suez框架的全文检索引擎,提供丰富的在线查询子句,过滤子句,排序子句,聚合子句且支持用户自定义开发排序插件。

Qrs用于接收用户查询,将用户查询分发给Searcher,收集Searcher返回的结果作整合,最终返回给用户。Searcher是搜索查询的执行者,主要包括倒排索引召回、统计、条件过滤、文档打分及排序及摘要生成。在实际的部署中,Qrs和Searcher都是采用多行部署的方式,可以根据业务的流量变化作调整。Searcher还可以根据业务的数据量调整列数,解决单机内存或磁盘放不下所有数据的问题。

剖开HA3引擎,我们可以粗略看下引擎侧索引的构建以及在线召回链路:

蓝色部分表示HA3在线服务,提供在线召回商品服务;绿色部分表示引擎数据源聚合(离线dump)逻辑,将商品信息构建成对应的引擎数据源。下图为一个离线引擎dump的数据源图示例:

设计思路

由于我们要解决的问题是如何安全、灵活、高效地支撑多业务接入闲鱼搜索,并提供不同业务间混排能力,我们的设计想法如下:

1、支持业务间互相隔离,从引擎侧深层次隔离,提高整体迭代效率

2、支持多引擎并发召回能力,解决搜索RT恶化问题

3、支持多引擎召回结果合并能力,并统一传递给URF Rank执行混排

4、支持实时干预能力,满足不同业务孵化诉求

调研集团内部已有实现模式,并结合闲鱼搜索业务发展诉求,我们重新设计并执行闲鱼底层引擎召回逻辑升级流程,从单引擎单路召回架构升级为多引擎多路并发召回架构。

Search Planner及搜索引擎层升级如下图所示:

主要升级节点如下:

1、步骤1中解析用户query,获取多引擎标识,解析并缓存引擎配置信息

2、步骤3流控模块从配置中心获取引擎定制化配置,并执行query改写逻辑,生成对应的HA3请求串

3、步骤4依据query中携带的多引擎标识,并发请求不同引擎在线服务召回商品,并合并召回结果,统一调用步骤5的精排服务能力

4、步骤5算法侧升级支持多引擎结果,支持多业务混排能力

实现方案

依照上节的设计思路,实现方案核心主要关注以下几点:

1、如何解析用户query,并缓存用户query相关引擎配置信息

每一个引擎均存在唯一的标识id(便于说明:主搜引擎标识为0,闲鱼无忧购引擎标识为1,向量引擎标识为2),上层搜索业务层依据不同业务场景组装引擎查询query,包括组装引擎标识列表(比如bizType=0,1,2,表示同时从主搜引擎、闲鱼无忧购引擎、向量引擎召回商品)。

Search Planner核心解析逻辑如下:

-- 构建请求的biz列表
function get_search_biz_type_list(query, param)
-- 搜索biz配置列表
local search_biz_type_list = {}
if query.bizType then
if type(query.bizType) == "string" then
table.insert(search_biz_type_list, query.bizType)
else
search_biz_type_list = query.bizType
end
end

if search_biz_type_list == nil or #search_biz_type_list < 1 then
table.insert(search_biz_type_list, param.default_biz_type)
end

local search_list = {}
if not query._enable_multiplexed then
table.insert(search_list, {biz = param.default_biz_type, biz_type = search_biz_type_list})

return search_list
end

for _, type in ipairs(search_biz_type_list) do
table.insert(search_list, {biz = type, biz_type=type})
end

return search_list
end
2、流控模块如何获取引擎定制化配置,执行query改写逻辑
目前流控模块通过阿里巴巴集团内部广泛使用的diamond配置中心获取详细配置参数,并与引擎唯一标识绑定映射关系。Diamond是淘宝内部广泛使用的配置中心,提供持久化管理和动态配置推送服务。采用推送服务,每次请求不再需要实时从远端获取配置,降低搜索RT,提高搜索体验。同一环境下,Diamond中通过唯一的GroupId + DataId标识参数配置。
function parse_diamond_config(query, param)
query._cluster_info = {}

-- 多引擎配置
local cluster_info_str = param.cluster_info
local cluster_info = setup.split(cluster_info_str, ";")

if not cluster_info then
return
end

for _, info in ipairs(cluster_info) do
local single_cluster_info = setup.split(info, ":")

if single_cluster_info and #single_cluster_info > 1 then
query._cluster_info[single_cluster_info[1]] = single_cluster_info[2]
end
end

end
query改写逻辑封装在不同的函数组中,通过前置分支判断,调用函数组中不同改写入口,生成定制化query。
-- 改写向量召回query
function rewrite_embedding_recall(query, switch, param)
-- 创建query
local que = {}
que._biz = query._biz
que._cluster_name = query._cluster_name

que.q = ""

if really_need_search_embedding_recall(query) then
local qp_idlefish_table_qp_reserve_str_4rs_query_vector = query._qp_idlefish_table_qp_reserve_str_4rs_query_vector
local q_str = qp_idlefish_table_qp_reserve_str_4rs_query_vector .. "&n=" .. param.embedding_recall_search_hit

que.q = "sim_vec:" .. url_encode(q_str)
end

-- 改写attribues
if not switch.full_phase then
que.attribute = "item_id,bizType"
end

-- 改写rank
que.rank = { -- rank 子句
rank_profile = 'RecallScorer'
}

return que
end
3、如何并发执行多引擎召回、合并流程,预防搜索RT恶化
借助于SPL异步协程能力,通过一条lambda函数,实现并行调用,以解决搜索RT恶化问题。如:value = search_http("/qp?xxx"):value(),即表示一次异步并发调用操作。
-- 解析入口
function multi_parse(res_vec)
local items_search_lua_tables = {}

for _, p in ipairs(res_vec) do
-- p.res:value()执行异步并发请求
local res = p and p.res and p.res:value()
local biz = p and p.biz

... ...

local ret_table = res:getTable()

table.insert(items_search_lua_tables, {biz=biz, tbl = ret_table})
end
end
通过多引擎隔离、query改写手段,各业务间能有效地解耦,满足各业务定制化诉求,并且对闲鱼主搜服务能力干扰最小,将问题集中于单业务内;
通过集成dianmond配置中心的流控模块,达到实时干预query搜索能力,并有效孵化创新业务,如当前闲鱼无忧购创新业务;
通过多引擎并发召回及合并能力,一是解决搜索RT恶化问题,二是结合URF Rank,有效控制不同业务间混排效果,并最终呈现给用户,以达到更好的用户体验。
以一个精简版用户query为例,传递给sp的query如下(查询关键字为“Zimmermann 裙”,从三个引擎(0、1、2)中召回结果):
/bin/sp?outfmt=json2&src=idlefishwireless&app=spl_secondHand_new&q=Zimmermann%20%E8%A3%99&isForbiden=0&wlsort=35&s=0&n=10&enable_rank=true&enable_advsort=true&new_rs=true&ha3_version=v2&sellStatus=0&auctionType=a,b&se=tis2&bizType=0,1,2
对应可视化调用拓扑如下:
multi_searcher是多路召回入口,包括并发多引擎召回、多引擎结果解析、合并等逻辑。
红框中每一个ha3_searcher表示一条独立引擎召回链路,图中三条链路可得出当前召回是多路并发召回(56ms < 54ms + 10ms +20ms)。

效果

目前多引擎多路召回能力已经在闲鱼无忧购引擎、向量引擎场景下落地,整体取得了不错的效果:
1、构建快
主引擎中闲鱼无忧购商品引擎dump大全量单次构建平均时长约为14h,迁移独立引擎后平均构建时长约为5h
2、接入快
主搜场景接入向量召回能力,采用当前多路召回能力,召回链路打通原先1周缩短到2天
3、体验好
主搜场景开启主搜引擎、闲鱼无忧购引擎、向量引擎三路并发召回能力,整体RT上涨约15ms
4、资源省
主引擎占用内存(21.6T),无忧购引擎(210M),向量引擎(20G)
5、维护成本低
无忧购引擎整体12个schema字段,向量引擎目前只需要2个字段
闲鱼无忧购迁移独立引擎,整体曝光PV提升近50%,支付订单整体提升近33%
闲鱼无忧购商品与主引擎C2C商品混排效果如下:

展望

前期主要集中于搜索架构升级快速落地,快速支撑业务发展诉求,当前实现上存在不优雅、用户使用门槛高等问题,后续我们将围绕多路召回能力及用户体验继续优化:
1、隔离query改写及多引擎合并能力,将职责从平台侧迁移到业务侧,提高主链路稳定性,以及业务迭代效率
当前各个引擎query改写能力及合并能力,和主链路流程揉合在一起,未做到垂直业务间、垂直业务与主链路间隔离,对主链路的稳定性存在一定的影响
2、精细化流控及干预能力,并提供可视化配置能力
当前流控及干预手段,统一使用集团diamond配置,缺少一个便于操作使用的可视化能力
3、SP功能核心代码逻辑从lua迁移java,降低用户学习、开发成本
新的一年,闲鱼侧将有更多的垂直业务接入搜索,多路召回能力将极大的帮助更多垂直业务快速接入,并提供更优雅、灵活、高效的业务混排能力,为各业务的持续发展提供强有力的支撑。

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: