广告场景下的检索平台技术

检索方向概述

在这里插入图片描述

数据检索领域技术选型大体分为SQL事务数据库、NoSQL数据库、分析型数据库三个类型。
SQL数据库的设计思路是采用关系模型组织数据,注重读写操作的一致性,注重数据的绝对安全。为了实现这一思路,SQL数据库往往会牺牲部分性能(尤其是写性能),来换取更好的事务性与稳定性。
分析型数据库的典型应用就是文本搜索,后来随着机器学习的发展,逐步扩展到向量检索领域。绝大部分分析型数据库的技术选型,保留SQL数据库对数据安全性的追求,采用适配块存储的数据结构存储数据。虽然ES通过一系列技术手段优化写性能,但在我看来并没有做出实质性突破。
NoSQL数据库基本就是我们常说的KV数据库。NoSQL之所以出现,是因为随着大数据时代到来,数据量的爆炸,SQL数据库分布式能力弱、存在性能瓶颈等问题逐渐暴露。NoSQL放弃了关系模型、事务性等能力,以此来换取高可扩展性和极致的性能。
扩展阅读:存储检索技术发展历史(1966 - 2021)
在介绍广告检索技术建设前,我们要先思考几个问题:

  1. 为什么我们不能直接用上述技术领域中的开源技术选型直接搭建我们的广告检索体系?
  2. 如果我们自建检索技术体系,放眼整个技术版图,我们的站位在哪里?

广告检索技术特点

大家可能会发现一个看似寻常的现象,就是国内那个比较大的互联网计算广告团队,几乎都会建设自己的检索内核,但是反观推荐、搜索团队,往往会基于一些开源的技术选型做个性化迭代(如ElasticSearch)。究其原因,要从广告业务的特点说起。

  1. 更新频繁,时效性要求高。
    广告业务存在广告主实时行为,这一点是显著区别于推荐、搜索等业务的。推演到检索技术领域,其表象就是检索内核需要支持高频更新,且时效性一般要求在亚秒级。
  2. 无需保证外部一致性。
    虽然上面对更新提出了很高的要求,但是广告场景也有要求比较宽松的地方,那就是并不要求满足外部一致性,而是仅需满足最终一致性。此外,一条记录内部(如一个计划内部)需要保证更新的原子性,不能出现同一条记录中的不同字段版本不一致的情况。
  3. 对系统工程指标要求极高。
    广告业务对收入极其敏感,任何一点时延抖动、不稳定都可能带来很大的资损。因此广告系统往往极致的追求高吞吐、高性能、高可用。对应到检索的技术选型上,往往斥巨资选用纯内存存储。此外,在读写并发的基础上,需要完全消除性能毛刺,避免更新操作对读请求带来影响。
  4. 采用关系模型。
    由于广告业务的复杂性,商家端往往将数据库划分为账户、计划、单元、创意、推广内容几个实体,以此来映射广告主的诉求模型。这些实体之间存在关联关系,因此本质上广告数据内部采用的是关系模型。这一点是显著区别于推荐、文档搜索等业务场景的。
  5. 需要应用倒排索引、向量索引。
    广告的检索过程其实是一次倒排检索的过程。在这里,我将“向量检索”这个行为也抽象为一种模糊的倒排检索。这个严格来说并不是广告场景的特点。之所以在这里提及,是想说明广告场景不能简单的选用NoSQL数据库(如Redis)来满足上面的要求。

有了上面的分析,再回到这张图。我们来看看我们的发挥空间究竟是什么?
暂时无法在飞书文档外展示此内容

广告检索本质是一个在线数据缓存服务。说他是服务是相对于数据库而言的,他对持久化、事务性、一致性的要求都不高,反倒是对读写两端的性能要求极高。这个服务需要具备的一些核心feature主要有倒排检索、向量检索,同时还要求具备关系模型表达能力(类SQL)。


一点个人理念

  1. 系统是长出来的,不是设计出来的;长出来的系统,有概率掉进万丈深渊。
  2. 提效不是最终目标,目标的尽头是敏捷度;敏捷度指的是快速适应与高效纠偏。
  3. 不要小看上述两点,这都是要命的事!
    暂时无法在飞书文档外展示此内容

平台的本质是标准化,标准化的目的是:至少不要让路线偏离的太远。


检索平台

基于在线数据缓存服务这个定位,我们规划了函谷检索平台,目标是为广告库提供标准化、通用的检索能力支撑,快速定制业务检索服务,通过能力复用放大技术建设的杠杆作用。

召回平台 与 检索平台 的区别
在规划 检索平台 的时候,其实我们同时也做出了建设 召回平台 的设想。
检索平台专注于提升基础检索能力(如kv、倒排检索、向量检索等),同时对外屏蔽服务部署等细节,提供云原生的“数据表”缓存服务。召回平台更专注于对业务的召回环节进行抽象,提供多种通用的业务实体、召回插件、过滤插件供策略与产品同学选择,方便快速实现产品需求。
简单来说,检索平台更关注基础能力,召回平台更关注业务抽象。

理念

在建设检索平台的时候,我们明确了几个设计理念。

  1. 数据与查询的标准化
    这个其实是老生常谈,建设任何平台都需要先标准化。这个地方不展开了。

  2. 数据即业务
    在这个地方,我们将整个检索流程抽象为“从一个数据转化为另一份数据的过程”。检索过程从一个表开始,查询到一些结果,然后对这些结果进行一定计算处理,利用计算结果再去查另一张表,如此往复,直到得到需要返回的数据表。如下图所示。
    暂时无法在飞书文档外展示此内容

  3. 云原生
    屏蔽服务部署等细节,提供云原生的“数据表”的声明式部署部署能力。例如,当一个业务方想部署一个计划表时,他只需要如下图操作。
    暂时无法在飞书文档外展示此内容

  4. 支持扩展业务插件/业务图
    原则上我们希望用类SQL的语言表达所有业务逻辑。但是考虑到业务的复杂性以及SQL可读性较差,我们还是提供了扩展插件的能力。如上图Step 3所示,插件会和数据表打包在一起部署到运行环境。
    用户可以通过两种方式调用插件,一是在函谷SDK的标准化接口中通过插件名调用插件。二是直接将插件的执行顺序编写为一个“插件流”文件,并把文件部署到运行环境中,然后在函谷SDK的标准化接口中通过插件流的名字调用插件。

  5. 智能分级存储
    在实际的应用场景中,一张表内的不同字段或不同行之间的的读取频率、性能要求、存储开销是不一样的。利用这个特性,我们很容易联想到操作系统中的三级缓存机制。那么这种缓存机制能否应用于我们的数据服务呢?我认为是可以的。我们可以采样真实请求与返回结果,根据一定策略智能的调整不同数据的存储介质(如磁盘、SSD、AEP、内存等),以此来满足业务对“资源-性能”兑换比的要求。

架构

[图片]

Controller
Controller是整个函谷系统的对外网关,用户通过HTTP协议向Controller发送信令,来实现具体的业务诉求。常见的信令有新建数据表、删除数据表、查看数据列表、构建数据表、调整shard数量等。Controller接收到信令后,会在后端系统中触发一连串操作,并维护任务状态,确保信令正确执行。
HBuilder
在Controller接收到“构建数据表”信令后,会调用k8s接口拉起多个HBuilder实例(取决于信令中数据表的数量、shard数量等)。HBuilder负责从指定位置读取源数据,并构建全量数据。构建完成后,HBuilder会将数据上传到对象存储中,并销毁自己。
HKeeper
HKeeper是运行在在线服务机器上的Sidecar,负责与Controller配合,完成数据分发、数据版本控制、增量消息读入等功能。HKeeper还通过心跳定期上传在线服务状态,如内存负载、CPU负载等,为Controller进行扩所容、迁移等决策提供数据支持。
HWorker
HWorker是在线提供检索服务的进程,解析请求中的检索语法,拆解为对应的基础检索操作。HKernel是HWorker的底层检索内核。
HShark
HShark是插件开发脚手架自动生成工具,是为了提高业务开发插件的效率。
举例:
假设这个是业务方定义的schema文件。

// 使用hangu 2.4.0及以后的镜像,不需要包含addr、segment、snapshot、extension 这几个字段,之前的都需要。
syntax = "proto3"; // 必须
import "hangu/kernel_option.proto";  // 必须
package engine.doc; // package name, // package name + message name 就是 clazz。
message Poi {option (table_name) = "poi";  // tablename,和在函谷平台配置的一致。int64 poiId = 2;string poiInfo = 3;int64 addr     = 10001;int64 segment  = 10002;int64 snapshot = 10003;map<string, string> extension = 10004;
}message SecondNested {int64 addr     = 10001;int64 segment  = 10002;int64 snapshot = 10003;map<string, string> extension = 10004;repeated string varLenStringValues = 2;
}message FirstNested {int64 addr     = 10001;int64 segment  = 10002;int64 snapshot = 10003;map<string, string> extension = 10004;repeated SecondNested secondNested = 1;int32 singleInt8Value = 2[(extend_type) = "int8"];
}

下面是HShark自动生成的Wrapper类的示例。
[图片]


索引内核

HKernel是检索技术的核心,它是面向广告业务场景定制设计的基础检索组件。

理念

  1. 内核职能分层
    检索内核承担了很多功能,比如管理存储IO、优化空间碎片、提供数据结构支持、管理数据对象等。这些功能之间是有明确的层级关系的。因此,在实现时,我们对内核进行了非常严格的分层,并且满足几个原则:(1)上层组件通过调用下层组件通用接口实现自身功能;(2)下层组件不允许调用上层组件;(3)同一层组件之间不允许相互调用。
    [图片]

  2. 技术参数配置化
    可以通过配置的方式,指定某一张表的某一个索引的底层技术选型。如poi表的正排索引选型,可以指定为hash table,也可以指定为sort table。配置方式如下:

poi.forward.index=hashtable
poi.forward.pool.type=fixpool
  1. 向量检索与倒排检索统一
    为了最大化地降低业务同学的认知成本,我们将向量索引与倒排索引进行了统一。具体来说,我们把对一张表的embedding建立向量索引的过程,看作是对这张表的embedding建立倒排索引。只不过这种索引是面向模糊检索,而非精准命中检索。
// 使用hangu 2.4.0及以后的镜像,不需要包含addr、segment、snapshot、extension 这几个字段,之前的都需要。
syntax = "proto3"; // 必须
import "hangu/kernel_option.proto";  // 必须
package engine.doc; // package name, // package name + message name 就是 clazz。
message Poi {option (table_name) = "poi";  // tablename,和在函谷平台配置的一致。int64 poiId = 2;string poiInfo = 3[(inverted) = "b+tree"];repeated float embedding = 4[(inverted) = "ivf-flat", (dim)="32", kernel="faiss"];int64 addr     = 10001;int64 segment  = 10002;int64 snapshot = 10003;map<string, string> extension = 10004;
}

设计

详见广告检索内核设计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/81927.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高频PCB设计如何选择PCB层数?

以四层板为例&#xff0c;可以第一层和第二层画信号&#xff0c;作为信号层。 第三层可以走电源&#xff0c;然后第四层走GND 但是更可以第一层和第三层画信号。第二层可以走电源&#xff0c;然后第四层走GND 用中间的电源层以及地层可以起到屏蔽的作用&#xff0c;有效降低寄…

[Linux_69] 数据链路层 | Mac帧格式 | 局域网转发 | MTU MSS

目录 0.引入 1.以太网帧格式 2.重谈局域网转发的原理(基于协议) 小结 3.认识MTU 3.1MTU对IP协议的影响 3.2MTU对UDP协议的影响 3.3MTU对于TCP协议的影响 0.引入 在去年的这篇文章中&#xff0c;我们有对网络进行过一个概述[Linux#47][网络] 网络协议 | TCP/IP模型 | 以…

vue2 provide 后 inject 数据不是响应式的,不实时更新

今天用 provide 后&#xff0c;inject 获取数据时不是实时更新的&#xff0c;获取的不是更新后的值 祖父组件 <div style"text-align: left !important;"><button click"change">更改</button> </div>data() {return {name: ini…

洛谷---P1629 邮递员送信

题目描述 有一个邮递员要送东西&#xff0c;邮局在节点 1。他总共要送 n−1 样东西&#xff0c;其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙&#xff0c;因此所有的道路都是单行的&#xff0c;共有 m 条道路。这个邮递员每次只能带一样东西&#xff0c;并且运…

2025年LangChain(V0.3)开发与综合案例

LangChain是什么&#xff1f; 在实际企业开发中&#xff0c;大模型应用往往比简单的问答要复杂得多。如果只是简单地向大模型提问并获取回答&#xff0c;那么大模型的许多强大功能都没有被充分利用。 要开始使用LangChain&#xff0c;首先需要安装相关的库&#xff1a; pip …

十分钟了解 @MapperScan

MapperScan 是 MyBatis 和 MyBatis-Plus 提供的一个 Spring Boot 注解&#xff0c;用于自动扫描并注册 Mapper 接口&#xff0c;使其能够被 Spring 容器管理&#xff0c;并与对应的 XML 或注解 SQL 绑定。它的核心作用是简化 MyBatis Mapper 接口的配置&#xff0c;避免手动逐个…

深度解析 MindTorch:无缝迁移 PyTorch 到 MindSpore 的高效工具

在深度学习领域&#xff0c;框架的选择往往取决于开发者的习惯、硬件支持以及项目需求。PyTorch 作为当前最受欢迎的深度学习框架之一&#xff0c;以其动态图机制和简洁的 API 设计深受开发者喜爱。然而&#xff0c;随着昇腾硬件的崛起&#xff0c;如何高效地利用昇腾的强大计算…

[250506] Auto-cpufreq 2.6 版本发布:带来增强的 TUI 监控及多项改进

目录 Auto-cpufreq 2.6 版本发布&#xff1a;带来增强的 TUI 监控及多项改进 Auto-cpufreq 2.6 版本发布&#xff1a;带来增强的 TUI 监控及多项改进 Auto-cpufreq&#xff0c;一款适用于 Linux 的免费开源自动 CPU 速度与功耗优化器&#xff0c;已发布其最新版本 2.6。该工具…

Linux 更改内存交换 swap 为 zram 压缩,减小磁盘写入

1、查看当前 swap 的方式 swapon --show 我这里是默认的 swap 文件&#xff0c;大小为 2G。 2、安装 zram Ubuntu 下&#xff1a; sudo apt install zram-tools安装后默认会启动&#xff1a; 3、关闭默认的 swap 文件 sudo swapoff /swapfile 其次是关闭 /etc/fstab 中的 …

ORCAD打印pdf

1 笔记本电脑绑定了打印机&#xff0c;要改成这个

C++中指针使用详解(4)指针的高级应用汇总

C 中指针的高级应用非常丰富&#xff0c;掌握这些内容能让你写出更高性能、更底层控制力强的代码。下面是应用模块梳理和例子讲解。 目录预览 函数指针与回调机制指针数组 vs 数组指针指针与类成员函数&#xff08;成员函数指针&#xff09;智能指针&#xff08;unique_ptr, s…

图像处理软件imgPro—调参救星!

推荐一款图像处理软件imgPro&#xff0c;该软件是逛B站时偶然间发现&#xff0c;虽然up主是新号&#xff0c;但是视频中看起来非常实用&#xff01; 核心是多种算法高效调参&#xff0c;亮点是自动生成源码&#xff01;这您受得了吗&#xff1f;调试之后&#xff0c;直接复制代…

DOM基础学习

一、DOM文档对象模型 通常将DOM看作一颗“树”&#xff0c;DOM将整个文档看作一颗“家谱树 ” 二、对象 用户定义的对象内建对象&#xff08;Array、Date、Math&#xff09;宿主对象 三、节点 node 元素节点&#xff08;element node&#xff09;文本节点&#xff08;text…

初识人工智能、机器学习、深度学习和大模型

文章目录 1. 前言2. 相关概念3. 层级关系4. 应用场景对比4. 实际案例 初识人工智能、机器学习、深度学习和大模型 1. 前言 之前经常听人说AI、机器学习&#xff0c;深度学习之类的词汇&#xff0c;总是傻傻的不了解他们的区别&#xff0c;近来有空&#xff0c;来通俗说说个人看…

n8n系列(1)初识n8n:工作流自动化平台概述

1. 引言 随着各类自动化工具的涌现,n8n作为一款开源的工作流自动化平台,凭借其灵活性、可扩展性和强大的集成能力,正在获得越来越多技术团队的青睐。 本文作为n8n系列的开篇,将带您全面了解这个强大的自动化平台,探索其起源、特性以及与其他工具的差异,帮助您判断n8n是否…

Linux:web服务

一、nginx的安装及启用 1、为主机配置IP和搭建软件仓库 &#xff08;1&#xff09;IP的配置 &#xff08;2&#xff09;搭建软件仓库 2、 web服务的安装与启用 &#xff08;1&#xff09;nginx的端口 更改nginx端口号 效果 &#xff08;2&#xff09; 默认发布目录 修改默认发…

用卷积神经网络 (CNN) 实现 MNIST 手写数字识别

在深度学习领域&#xff0c;MNIST 手写数字识别是经典的入门级项目&#xff0c;就像编程世界里的 “Hello, World”。卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;作为处理图像数据的强大工具&#xff0c;在该任务中展现出卓越的性能。本…

从 MDM 到 Data Fabric:下一代数据架构如何释放 AI 潜能

从 MDM 到 Data Fabric&#xff1a;下一代数据架构如何释放 AI 潜能 —— 传统治理与新兴架构的范式变革与协同进化 引言&#xff1a;AI 规模化落地的数据困境 在人工智能技术快速发展的今天&#xff0c;企业对 AI 的期望已从 “单点实验” 转向 “规模化落地”。然而&#…

苍穹外卖部署到云服务器使用Docker

部署前端 1.创建nginx镜像 docker pull nginx 2.宿主机&#xff08;云服务器&#xff09;创建挂载目录和文件 最好手动创建 而不是通过docker run创建&#xff0c;否则nginx.conf 默认会被创建为文件夹 nginx.conf 和html可以直接从黑马给的资料里导入 3.运行nginx容器&am…

C++ 渗透 数据结构中的二叉搜索树

欢迎来到干货小仓库 "沙漠尽头必是绿洲。" --面对技术难题时&#xff0c;坚持终会看到希望。 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; a、若它的左子树不为空&#xff0c;则…