Hologres RoaringBitmap 在 Lazada 选品平台的最佳实践
Lazada 选品平台包含全网商家、商品的圈选,通过 Hologres RoaringBitmap 能力帮助业务突破选品池 20w 大小限制,6000+选品池调度完成由 12h 下降至 1h,单个选品池调度时间由 90s 下降至 2s。
选品平台介绍
Lazada 选品平台是面向内部运营小二选品的操作系统,其核心能力是:通过用户制定的规则条件组合以筛选出满足期望的业务实体,这里的业务实体包括但不仅限于:商品、商家。站在电商运营体系上来看,选品系统的核心职能在于 选 和 供,选出合适的 “品”(商品、商家... ),供给到对应的 “渠道” (会场、频道、JFY...)。通过供和选核心能力的组合,选品平台在营销活动链路中作为数据通路,打通从商家到消费者的核心链路,并且在导购链路赋能了会场、FlashSale、JFY 等等诸多业务,覆盖了 Lazada 的绝大数场景化供给。
从选的角度来讲,可以用于运营范围圈定、业务准入门槛、大促会场和日常频道投放等。在大促招商以及商家运营系统中,商家范围界定就成为整个运营流程的起点也是最值得关注的一点,限定满足预期的商家会让后续的流程更加顺滑也势必会取得更好的效果;在各种官方营销活动中,各行业运营会根据商家层级、货品类目、成交表现等为商家提供特定报名入口,为消费者提供更匹配的货品,选品成为不同层次门槛制定的有力抓手。从供的角度来讲,多货品集交并差供给、离线供给、打标供给、渠道供给等能力让选品成为数据通路的统一出口。这里供给的含义不单纯是将数据以在线或者离线的方式提供给下游,可能是一次打标任务、一次 excel 导出、也可能是持续的增量打去标任务。
Hologres(原交互式分析)是一站式实时数据仓库引擎,支持海量数据实时写入、实时更新、实时分析,支持标准 SQL(兼容 PostgreSQL 协议),支持 PB 级数据多维分析(OLAP)与自助分析(Ad Hoc),支持高并发低延迟的在线数据服务(Serving),与 MaxCompute、Flink、DataWorks 深度融合,提供离在线一体化全栈数仓解决方案。
在过去几个月,我们把选品平台的底层数据引擎从 Ha3 替换成 Hologres,并使用 DataWorks+Flink 构建了一套和 Saro 类似的离在线数据同步解决方案,打破了使用搜索引擎支撑选品的传统,开创了 OLAP 数据库在选品平台上应用的先河。
RoaringBitmap 科普
Bitmap
在介绍 RoaringBitmap 之前,先来了解下 Bitmap。
Bitmap 的基本思想就是用一个 bit 位来标记某个元素对应的 Value,而 Key 即是该元素。由于采用了 Bit 为单位来存储数据,因此在存储空间方面,可以大大节省。
假设有这样一个需求:在 20 亿个随机整数中找出某个数 m 是否存在其中,并假设 32 位操作系统,4G 内存
在 Java 中,int 占 4 字节,1 字节=8 位(1 byte = 8 bit)
如果每个数字用 int 存储,那就是 20 亿个 int,因而占用的空间约为 (2000000000*4/1024/1024/1024)≈7.45G
如果按位存储就不一样了,20 亿个数就是 20 亿位,占用空间约为 (2000000000/8/1024/1024/1024)≈0.233G
假设有四个整数:int[ ] a = { 0, 3, 5, 7 },使用下图的 Bitmap 表示,表格标记了 0 到 7 的数字,其中 0、3、5 和 7 被标记为 1:
因为 1Int = 4Byte = 32Bit,所以一个 Int 所占的二进制位可以映射 32 个数字,相当于压缩了 32 倍,那么之前 20 亿个整数所需要的 7.45GB 内存可缩减至 233.41MB。
Bitmap 的问题在于,不管业务中实际的元素基数有多少,它占用的内存空间都恒定不变。如果 Bitmap 中的位的取值范围是 1 到 100 亿之间,那么 Bitmap 就会开辟出 100 亿 Bit 的存储空间。但是如果实际上值只有 100 个的话,100 亿 Bit 的存储空间只有 100 个 Bit 为 1,其余全部为 0,数据存储空间浪费严重,数据越稀疏,空间浪费越严重。
RoaringBitmap
为了解决 Bitmap 稀疏存储浪费空间的问题,出现了很多稀疏位图的压缩算法,RoaringBitmap 就是其中的优秀代表。
RoaringBitmap 是高效压缩位图,简称 RBM。RBM 的历史并不长,它于 2016 年由 S. Chambi、D. Lemire、O. Kaser 等人在论文《Better bitmap performance with Roaring bitmaps》与《Consistently faster and smaller compressed bitmaps with Roaring》中提出。
RoaringBitMap 的基本思路:
将数据的前半部分,即高 16 位作为桶的编号,分为 65536 个桶,RBM 中将这些小桶称之为 Contriner(容器)
存储数据时,按照数据的高 16 位做为 Contriner 的编号去找对应的 Contriner(找不到就创建对应的 Contriner),再将低 16 位放入该 Contriner 中:
与 Bitmap 相比的优势
●空间节省:Bitmap 比较适用于数据分布比较稠密的存储场景中;RoarringBitMap 在稀疏存储上空间更省,稠密和 Bitmap 一致。
●更高效的做交、并操作:将大块的 Bitmap 分成各个小块,其中每个小块在需要存储数据的时候才会存在。所以当进行交集或并集运算的时候,只需要去计算存在的一些块,而不需要像 Bitmap 那样对整个大的块进行计算。这里既不是用空间换时间,也没有用时间换空间,而是用逻辑的复杂度同时换取了空间和时间。
集合运算性能下面这段代码测试 RoaringBitmap 与数组在交集运算上的性能差异:
测试结果:
下面这段代码测试 RoaringBitmap 与数组在差集运算上的性能差异:
测试结果:
从测试结果不难看出,在集合传统的交差集运算上,RoaringBitmap 具有无与伦比的速度优势。
RoaringBitmap 实践
指标存储
前文提到我们把选品平台的底层数据引擎升级成 Hologres,Hologres 数仓存储了 lazada 全平台的商品,按目前运营小二组合商品表现数据来选品的习惯,我们把商品的表现数据抽象成商品指标存储在大宽表(为什么叫大宽表,因为随着业务关注视角的不同,指标越来越多,目前已经接近 300 个字段)。
其中商品指标不乏多值字段,如:商品所属类目、商品已报名活动、商品所属行业...,存储这些多值字段,我们一开始采用数组类型字段进行存储。如果运营小二使用了多值指标进行选品,规则翻译模块会把运营的输入翻译成数组的交集运算提交到 Hologres 执行。直到我们从 Hologres 的监控发现,CPU 偶有冲高到 100%的情况:
通过抓取该段时间的慢 SQL,我们发现导致 CPU 冲高的大部分 SQL 都是数组取交集的运算。
问题定位到了,当时想到两种优化方案:
●多值字段从数组换成 RoaringBitmap,RoaringBitmap 是一种高效的 Bitmap 压缩算法,目前已被广泛应用在各种语言和各种大数据平台。适合计算超高基维的,常用于去重、标签筛选、时间序列等计算中。
●多值字段依旧使用数组,数据落表时先排好序再写入,在查询取交集时,传入比较的数组也排好序,即“先排序再比较”的策略。
两种优化方案优劣比较:
离线写入:即商品大宽表数据由 MaxCompute 写入到 Hologres,选品平台的数据层一般由离线数据和在线数据两部分组成
综上,字段类型修改为 RoaringBitmap,离线写入的耗时增加 1min 左右 CPU 消耗增加 10%,对离线链路构建时长的影响可以忽略;查询性能大幅优于有序的数组和现有无序的数组。
基于此,我们把商品大宽表的 23 个多值字段由数组类型升级成 RoaringBitmap,整体优化收益如下:
●商品大宽表存储空间下降 30% ~ 40%,存储文件个数下降 30% ~ 40%(不同国家有所差异,整体在 30% ~ 40%)。文件个数减少有以下几个好处:
○提高查询性能:更少的文件意味着查询需要扫描的数据量和文件数量都较少,从而提高查询速度和系统整体性能。
○减少存储开销:小文件会在硬盘上产生更多的碎片,导致磁盘空间利用率降低,文件个数减少有助于提高磁盘空间利用率。
○简化管理:当文件数量较多时,管理和监控任务会变得更加复杂。文件个数减少能够简化管理和维护工作,提高运维效率。
○优化备份和恢复:备份大量小文件通常比备份少量大文件所需的时间更长。文件个数减少可以缩短备份和恢复的时间,提高业务连续性。
○减轻元数据压力:文件系统需要跟踪每个文件的信息(如权限、大小等),大量的小文件会增加元数据的压力。文件个数减少有助于减轻元数据服务器的压力,保证系统的稳定运行。
●Hologres CPU 利用率下降 30%
HologresRoaringBitmap 类型字段建表语句参考:
选品池运算
选品池:符合运营小二选品规则的业务实体(商品、商家...)的集合,选品池数据一般为商品 ID 或商家 ID 的集合
“供给”是选品平台的核心能力,围绕着“供给”,我们构建了选品池持续的增量打标/去标的核心能力。打标供给核心流程如下:
当前打标供给流程核心问题定义:
●数据冗余:因为需要对选品池今天和昨天的数据进行比较,选品池今天的数据从选品引擎实时拉取,选品池昨天的数据冗余到 Mysql 以方便第二天进行比较
●选品池运算:今天和昨天的选品池数据对比,在应用内存中进行,如果选品池数据量过大,容易触发应用频繁的 FullGC。技术通过设置 20w 上限来规避这个问题,业务对突破 20w 的述求越来越强烈
●调度效率低:6000+选品池调度完成,要 12h,单个选品池调度完成花费 80~90s
在了解到 RoaringBitmap 在集合存储具有较大的空间优势,在集合运算具有较大的时间优势,我们决定使用 RoaringBitmap 来存储选品池数据。
在 RoaringBitmap 落地过程中,遇到了很多困难和挑战,罗列其中一二:
●为了解决数据冗余的问题,我们限定选品池数据不出 Hologres 数仓,也就是要借助 Hologres 的 RoaringBitmap 字段类型来存储选品池数据。但 Hologres 的 RoaringBitmap 字段类型只支持 32 位整数存储,商品 ID 和商家 ID 显然已经超过了 32 位整数的范围。于是,问题就演化成了 RoaringBitmap 怎么能存下 64 位整数。从实现复杂度,以及对未来 SKU 选品池支撑友好程度等多方面综合考虑,我们最终采用分桶法。
○偏移法:
○分桶法:将商品 ID 或商家 ID 拆为低位和桶号,这里我们直接将商品 ID 的高 34 位作为桶号,将低 30 位存入 RoaringBitmap
○自定义 id:因为商品 ID 或商家 ID 均存在较大的断层,实际上商品数量和商家数量远未达到 32 位整数的上限,内部维护一个自增长 ID 去映射商品 ID 或商家 ID
在攻克了诸多困难和挑战后,打标供给整体实现方案简化为如下流程:
选品池运算核心逻辑:
优化整体收益:
●数据流转效率:6000+选品池调度完成由 12h 下降至 1h,单个选品池调度时间由 90s 下降至 2s
●系统稳定性:应用层 FullGC 次数下降 88%
●存储成本:消除数据冗余,节省 75GB 存储空间
●业务突破:帮助业务突破选品池 20w 大小限制,目前暂定 50w
Hologres RoaringBitmap 分桶表建表语句参考:
导出选品池数据到 RoaringBitmap SQL 参考:
选品池差集运算 SQL 参考:
总 结
RoaringBitmap 的成功应用,不仅是对业务功能的强力助推,彰显了技术对业务突破的关键赋能作用,更是先进技术驱动生产效率提升的典范。RoaringBitmap 通过其高效的压缩机制大幅优化数据存储(空间效率),以及卓越的集合处理能力显著提高操作性能(时间效率),有效克服了业务在选品池规模上的原有约束,实现了对 20 万条数据容量限制的突破。这不仅证明了 RoaringBitmap 技术的先进性,也是技术创新提升核心竞争力的生动实例。
评论