火山引擎ByteHouse:一套方案,让OLAP引擎在精准投放场景更高效

news2024/11/13 10:11:07

由于流量红利逐渐消退,越来越多的广告企业和从业者开始探索精细化营销的新路径,取代以往的全流量、粗放式的广告轰炸。精细化营销意味着要在数以亿计的人群中优选出那些最具潜力的目标受众,这无疑对提供基础引擎支持的数据仓库能力,提出了极大的技术挑战。

本篇内容将聚焦字节跳动OLAP引擎技术和落地经验,以字节跳动内部场景为例,具体拆解广告业务的实现逻辑和业务效果。

广告精准投放场景

广告投放过程一般包含数据收集->数据整合->人群圈选->广告投放->反馈分析等关键流程,人群圈选是广告精准投放的关键步骤,它帮助确定广告目标受众,辅助投放平台根据不同受众和广告目标优化投放策略,提升广告收益;

人群预估

人群预估主要是根据一定的圈选条件,确认命中的用户数目。在广告精准投放过程中,广告主需要知道当前选定的人群组合中大概会有多少人,用于辅助判断投放情况进而确定投放预算,通常要求计算时间不能超过 5 秒。

d5a948bdf43c7422a40a25fae9be3773.png

广告投放

53012791fc8ca678a81171a832a20444.png

广告精准投放过程中遇到的问题与痛点:

1. 数据预估: 广告主需要对选定的人群组合进行预估,以便判断投放情况并确定投放预算。但人群包数据量多,基数大。平台的用户数上亿,仅抖音的 DAU 就几亿,抖音、头条对应的人群包在亿级别,早期的预估版本采用ElasticSearch,但由于数据过于庞大,只能采用1/10抽样存储,导致10%的误差,业务难以接受。

2. 查询性能: 广告主可以设定一个非常复杂的圈选条件,导致计算复杂(单次计算可能包含几百上千个人群包),Hive和ES等方案在处理大数据量时,查询速度会变得非常慢,如果需要查询某个广告主的所有用户,需要扫描整个用户库,而这个过程可能需要几分钟甚至几个小时,无法满足实时性要求。

3. 存储空间大: Hive和ES等方案需要额外的索引结构,导致存储空间变大,从而增加了存储成本。例如,如果需要对用户属性进行索引,就需要额外的存储空间来存储索引数据。

4. 不支持高并发: Hive和ES等方案在处理高并发请求时,容易出现性能问题,无法支持高效的广告投放。例如,如果同时有多个广告主需要查询用户信息,就可能会出现查询阻塞或响应延迟等问题。

5. 数据查询效率: 采用ClickHouse支持预估,但随着数据量的增长,ClickHouse在当前存储引擎的支持下也难以保证查询时间。这导致了数据查询效率的问题,影响了用户体验。

ByteHouse BitEngine方案

方案简介

新查询引擎

  • 基于高性能、分布式特点,ClickHouse可以满足大规模数据的分析和查询需求,因此研发团队以开源ClickHouse为基础,研发出火山引擎云原生数据仓库ByteHouse,并在其中定制一套处理模型——BitEngine,用于解决集合的交并补计算在实时分析场景中的性能提升问题。

  • 针对广告人群预估业务开发的新查询引擎,基于ByteHouse提供的MergeTree Family系列引擎,添加了新的bitmap64类型和一系列的相关聚合函数。BitEngine提供的bitmap64类型适合存储和计算大量的用户ID之间的关系;在广告人群预估业务中,bitmap64类型用于存储人群包数据,然后将人群包之间的交并补计算转化为bitmap之间的交并补,从而达到远超普通查询的性能指标。

实现步骤

创建一个bitmap64类型,可以将用户ID直接存储在bitmap中,提供一系列交并补的聚合计算,并且还希望可以充分利用多核CPU的并行计算能力,由此我们设计了BitEngine。示例如下

CREATE TABLE cdp.tag_uids_map (
tags String,
uids BitMap64 BitEngineEncode
)ENGINE = HaMergeTree('/clickhouse/xxxx/{shard}', '{replica}')
ORDER BY tag

tag_uids_map存储格式如下

taguids
A{10001,20001,30001,40001,50001,60001,70001,80001,90001}
B{10001,20001,20002,20003,20004,20005,20006,20007,20008}

要查询 A&B 的结果 SQL 为

SELECT bitmapCount('A&B') FROM tag_uids_map

BitEngine实现逻辑

核心思想
  1. 对数据做分区划分和编码,保证每个区间的数据之间不存在交集,然后使用roaring bitmap保存数据;

  2. 计算时每个分区的数据可以独立的做聚合计算,充分利用机器的并行能力,每个分区内部的聚合计算就是多个bitmap之间的交并补,利用roaring bitmap高效的交并补计算降低CPU和内存的使用;

  3. 通过字典将编码的结果反解回来,数据编码是为了让数据的分布尽可能稠密,roaring bitmap在存储和计算的时候就可以获得更好的性能。

业务应用
业务关键要素
  1. 人群包:广告主自定义规则计算出来的人群数据,标签是dmp团队根据市场需求定义的人群数据。

  2. 标签ID:每天定时根据产出规则更新一次,人群ID是自增的,每天根据广告主需求进行新建计算。

统一编码
  1. 为了对标签数据和人群数据的uid统一编码,编码服务先将标签数据中的uid和人群数据中的uid提取出来进行统一编码,将全量uid均匀hash到一万个桶中,桶编号为i[0<=i<=9999],uid在每个桶内由1开始顺序编码,每个桶的范围为i*2^40 - (i+1)*2^40。

  2. uid数据每天都在增加,因此需要支持增量编码, 编码服务每天会先获取增量uid,hash后顺序放置到每个桶中。

数据存储
  1. 完成编码后,会先把字典数据统一写入hive表中,便于字典的各种使用场景。

  2. 在数据经过分区和编码之后,ClickHouse可以以多种数据导入格式将数据以bitmap64类型存入磁盘。

数据计算

BitEngine如何充分利用计算机的并行能力完成每个分区多个bitmap之间的交并补计算?

存在问题:

假设存在四个bitmap,分别为a,b,c,d;则(a | c) & (b | d)不一定等于(a & b) | (c & d)。

人群包

人群包A = [10001, 20001,30001,40001,50001],人群包B = [10001, 20001,20002,20003,20004]

期望结果

通过BitEngine计算A&B = [10001, 20001]

设计方案

  • 人群包按照一定的规则划分为多个区间,任意两个区间之间的人群包没有交集

  • 一个计算线程只读取同一个区间的人群包进行计算,得到一个中间结果

  • 最终的中间结果只需要简单的进行bitmap or计算即可

对于这个设计,BitEngine需要保证数据的读取和计算是严格按照区间进行。BitEngine在数据读取时会为每一个文件构建一个读任务,由一个线程调度模块完成整个任务的调度和读取,这个线程调度模块的调度原则是:

  • 不同分区的文件不会交叉读取(ClickHouse的文件读取粒度小于文件粒度,会存在多个线程先后读一个文件的情况,一个分区也可能由多个文件组成),即一个线程只会读A_1,B_1,不会在这之间读取A_2或者B_2。

  • 一个分区读取完成后,可以立即触发聚合计算,执行bitmap之间的计算逻辑,获得中间结果。即A_1,B_1 读取完成后,可以立即计算A_1 & B_1。

  • 线程计算完中间结果后,可以继续读其他文件

BitEngine完成所有中间结果的计算后,会按照结果的输出要求做一次数据合并:

  • 如果需要计算的结果是bitmap的基数的时候,BitEngine直接将各个中间结果的基数相加

  • 如果计算结果需要的是bitmap,BitEngine直接将所有的bitmap合并起来,这里合并指的是bitmap or计算

业务效果

广告业务效果
  1. 数据存储空间缩小了 3 倍+

  2. 导入时间缩小了 3 倍+

  3. 查询 avg/pct99/max 都下降明显,pct99 从 5 s 降低到 2 s

  4. CPU 使用下降明显,PageCache 节省 100 G+

  5. 查询误差从10% 下降到 0%

BitEngine上线前后查询耗时监控
33617116a2b2dbcdd656190d9c6840b1.png
BitEngine上线后CPU负载对比
75fdaf9542fd4a73624f7b2325b1475a.png
PageCache 使用情况(lower is better)
537289b26e05e112485fe63f9a4a12f6.png

案例总结

BitEngine上线使用后,经过大量调优,在广告人群预估业务上取得了良好收益。目前,BitEngine已经集成在火山引擎云原生数据仓库ByteHouse中对外输出。火山引擎ByteHouse主要为用户提供极速分析体验,能够支撑实时数据分析和海量数据离线分析,具备便捷的弹性扩缩容能力,极致分析性能和丰富的企业级特性,目前已经与中国地震台网中心、海王集团、莉莉丝游戏、极客邦科技等诸多行业企业达成合作,深度助力各个行业数字化转型。未来,BitEngine将继续增强功能以支撑广告业务场景,包括:引擎集成数据编码,使编码对用户透明;提供细粒度的缓存以缓存部分重复表达式的计算结果;优化表达式解析等。

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

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

相关文章

开源ChatGPT系统源码 采用NUXT3+Laravel9后端开发 前后端分离版本

开源ChatGPT系统源码 采用NUXT3Laravel9后端开发 前后端分离版本 ChatGPT是一种基于AI的聊天机器人技术&#xff0c;它可以帮助用户与聊天机器人进行自然语言交流&#xff0c;以解决用户的问题或满足用户的需求。ChatGPT的核心技术是使用自然语言处理&#xff08;NLP&#xff…

设计模式之组合模式(Composite)的C++实现

1、组合模式的提出 在软件开发过程中&#xff0c;使用者Client过多依赖所操作对象内部的实现结构&#xff0c;如果对象内部的实现结构频繁发生变化&#xff0c;则使用者的代码结构将要频繁地修改&#xff0c;不利于代码地维护和扩展性&#xff1b;组合模式可以解决此类问题。组…

JQuery快速入门教程

1、JQuery快速入门 1.1、JQuery介绍 jQuery 是一个 JavaScript 库。所谓的库&#xff0c;就是一个 JS 文件&#xff0c;里面封装了很多预定义的函数&#xff0c;比如获取元素&#xff0c;执行隐藏、移动等&#xff0c;目的就 是在使用时直接调用&#xff0c;不需要再重复定义…

蓝牙 - BLE SPP的设计策略(Serial over BLE strategy)

在开发 BLE 连接产品的过程中&#xff0c;你可能会有这样的疑问&#xff1a;"Serial profile在哪里&#xff1f;也许你以为你在蓝牙技术联盟网站上滚动浏览长长的profile列表时错过了它。又或者&#xff0c;你根本就没去看&#xff0c;而是准备选择更快的方法&#xff0c;…

第 359 场 LeetCode 周赛题解

A 判别首字母缩略词 签到题… class Solution { public:bool isAcronym(vector<string> &words, string s) {string pf;for (auto &s: words)pf.push_back(s[0]);return pf s;} };B k-avoiding 数组的最小总和 贪心&#xff1a;从 1 1 1开始升序枚举&#xff0c…

mybatis-plus--配置-(sql)日志输出-自动填充-分页-多数据源-逻辑删除

写在前面&#xff1a; 本文主要介绍mybatis-plus的配置&#xff0c;以后在有的时候在补充。欢迎交流。 文章目录 日志输出自动填充分页全局字段配置多数据源 日志输出 调试的时候需要看执行的sql&#xff0c;这时候就很需要日志来记录查看了。 mybatis-plus的日志配置在yml…

葡萄目标检测(yolov8模型,无需修改路径,python代码,解压缩后直接运行)

运行效果视频&#xff1a;葡萄目标检测&#xff08;yolov8模型&#xff0c;无需修改路径&#xff0c;python代码&#xff0c;解压缩后直接运行&#xff09;_哔哩哔哩_bilibili 1.采用yolov8模型 models文件夹保存的是yolov8的训练好的模型参数 PinotNoir文件夹存放的是训练集 …

局部变量可能会引发的错误---误判---用阶乘函数求强数的 Python 程序中遇到的问题

背景介绍 今天遇到这样一个额需求&#xff1a;用阶乘函数求强数的 Python 程序。所谓强数&#xff0c;就是一个特殊数字&#xff0c;满足其所有数字阶乘的和应等于数字本身的条件。 问题描述 def facorial_of_number(number):result 1for i in range(1, number 1):result *…

如何使用Python实现遥感彩色合成?

综述 遥感影像真彩色合成是一种将多光谱遥感影像转换为真实感彩色影像的技术。它通过将不同波段的遥感数据进行组合&#xff0c;以模拟人眼对地物颜色的感知&#xff0c;从而提供更直观、更易于理解的影像信息。 库索引名&#xff1a;arcpy.CompositeBands_management 通过不同…

如何在window下cmd窗口执行linux指令?

1.Git&#xff1a;https://git-scm.com/downloads(官网地址) 2.根据自己的实际路径,添加两个环境变量 3.重启电脑

[oneAPI] 使用Bert进行中文文本分类

[oneAPI] 使用Bert进行中文文本分类 Intel Optimization for PyTorch基于BERT的文本分类模型数据预处理数据集定义tokenize建立词表转换为Token序列padding处理与mask 模型 结果OneAPI参考资料 比赛&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517…

标速高就是好?不看4K随机就别买SSD!

游戏玩家心心念念的SSD终于降到了白菜价&#xff0c;1TB的固态硬盘甚至比机械硬盘都便宜了&#xff0c;不过如果只看到动辄3000MB/s的读速&#xff0c;那你下单的时候还真的会被骗。 之所以这么说&#xff0c;是因为商品页面标注的速度都是连续读写速度&#xff0c;也就是直接向…

面试官:JVM是如何判定对象已死的?学JVM必会的知识!

本文已收录至GitHub&#xff0c;推荐阅读 &#x1f449; Java随想录 文章目录 引用计数算法可达性分析算法引用类型Dead Or Alive永久代真的"永久"吗&#xff1f;垃圾收集算法标记-清除算法标记-复制算法标记-整理算法标记-清除 VS 标记-整理 作为一名Java程序员&…

Autosar存储入门系列02_NVM之CRC校验及显隐式同步机制

本文框架 0.前言1. NVM中CRC校验2. NVM的显隐式同步机制2.1 隐式同步2.2 显式同步 0.前言 本系列是Autosar存储入门系列&#xff0c;希望能从学习者的角度把存储相关的知识点梳理一遍&#xff0c;这个过程中如果大家觉得有讲得不对或者不够清晰的地方&#xff0c;还请一定指出…

Linus对AMD的fTPM 漏洞表示”沮丧” 呼吁禁用该功能

导读AMD 的 fTPM 问题在业内众所周知&#xff0c;经常导致系统崩溃和卡死。Linux 的创建者 Linus Torvalds 对该功能表示失望&#xff0c;称其为内核的”瘟疫”。 简单回顾一下&#xff0c;可信平台模块&#xff08;Trusted Platform Module 或 TPM&#xff09;是一种安全检查…

抖音火山引擎推出免费域名DNS和公共DNS服务

抖音旗下的云计算服务火山引擎最近推出了"TrafficRoute DNS 套件"服务&#xff0c;其中包括两款产品&#xff0c;对软希网来说非常有用。 1.域名DNS&#xff1a; 这是一个用于网站域名的DNS服务&#xff0c;可以加速域名解析速度&#xff0c;从而提升网站的速度。如…

【100天精通python】Day42:python网络爬虫开发_HTTP请求库requests 常用语法与实战

目录 1 HTTP协议 2 HTTP与HTTPS 3 HTTP请求过程 3.1 HTTP请求过程 3.2 GET请求与POST请求 3.3 常用请求报头 3.4 HTTP响应 4 HTTP请求库requests 常用语法 4.1 发送GET请求 4.2 发送POST请求 4.3 请求参数和头部 4.4 编码格式 4.5 requests高级操作-文件上传 4.6 …

线性代数的学习和整理4: 求逆矩阵的多种方法汇总

目录 原始问题&#xff1a;如何求逆矩阵&#xff1f; 1 EXCEL里&#xff0c;直接可以用黑盒表内公式 minverse() 数组公式求A- 2 非线性代数方法&#xff1a;解方程组的方法 3 增广矩阵的方法 4 用行列式的方法计算&#xff08;未验证&#xff09; 5 A-1/|A|*A* &…

构建 NodeJS 影院微服务并使用 docker 部署【01/4】

图片来自谷歌 — 封面由我制作 一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 在本系列中&#xff0c;我们将构建一个 NodeJS 微服务&#xff0c;并使用…