营销系统黑名单优化:位图的应用解析 | 京东云技术团队

news2025/1/17 9:05:34

背景

营销系统中,客户投诉是业务发展的一大阻碍,一般会过滤掉黑名单高风险账号,并配合频控策略,来减少客诉,进而增加营销效率,减少营销成本,提升营销质量。

营销系统一般是通过大数据分析建模,在CDP(客户数据平台,以客户为核心,围绕数据融合、人群圈选、用户洞察等提供产品能力)创建营销目标客户群体,黑名单同样也是通过CDP维护。下面的图片简单描述了过滤黑名单的处理流程,流程是相对简单的。但是,测试过程中却发现一个问题,对于一个近30万的营销群体,整个触达流程需要处理一个多小时,而其中过滤黑名单就占用了近半个小时的时间,业务有点难以接受这个性能。

黑名单处理流程

性能优化

引入多线程优化

其实很容易就能想到,对于调用RPC接口这种含有I/O操作的场景,可以引入多线程优化,将一个几十万的账号集合拆分为多个子任务提交给线程池处理,从而加快处理速度。从下图可以看出引入多线程后性能有很明显的改善,单线程处理25万、50万个账号的群体分别需要近半小时、近一小时,改为25个线程处理后可以分别控制在1分钟、2分钟左右。

多线程处理

引入位图优化

进一步了解CDP的底层原理后,会发现这个问题应该还有其他的解决方案,即通过位图优化。CDP的群体都会有对应的位图文件,也就是说营销客户群体和黑名单群体都是以位图的数据结构存储的,通过CDP下载群体的SDK就可以获取到位图文件,营销群体的位图与黑名单群体位图进行与非操作(andNot,就是从一个位图中移除另一个位图中存在的元素,而保留不在另一个位图中的元素),得到的新的位图就是过滤掉黑名单账号后的目标客户的位图。代码实现很简单,使用CDP SDK的示例代码如下(也可以参考GitHub示例代码,但不适用于CDP群体位图处理):

DataLoader dataLoader = new DataLoader(token, bitMapBaseUrl);
ABitmap customerBitmap = dataLoader.loadGroup(customerGroupCode);
ABitmap blacklistBitmap = dataLoader.loadGroup(blacklistGroupCode);
customerBitmap.andNot(blacklistBitmap);

位图存储相当节省空间,50万群体的位图文件也就约2MB大小。同时位图的与非操作是相当快的,上边例子中的25万、50万的群体都可以在80毫秒左右过滤掉黑名单账号。从近半小时、近一小时到几十毫秒这个对比非常惊人了,那么为什么位图的处理速度可以这么快呢?

位图简介

位图原理

位图的基本思想是使用bit来标记一个数值,1表示该数值存在,0表示不存在。由于以位为单位存储数据,因此可以大大节省存储空间。通过这种方式,可以非常高效地表示和操作数值集合。

举个直观的例子,有40亿个不重复的随机自然数,如果使用long型数值存储,一个long型数值8个字节,40亿个数值占用约29.8GB,但如果是存储为40亿个bit,则只需要约0.47GB。

在Java中一个long型数值占64位,可以用一个long型数组long[] words = new long[(nBits - 1) / 64 + 1]存储位图,其中nBits表示位图的初始大小。对于给定任意自然数xx / 64就能得到x在数组中的下标,x % 64就能得到x在此下标的哪个位。数组的第一个下标words[0]可以表示数值0~63,第二个下标words[1]可以表示数值64~127,之后依此类推。

如果将 3, 4, 6 几个数值存入位图,则如下图所示,对应数组的第一个下标的 3, 4, 6 位被标记为1,其他位均为0。

位图

对于添加操作,假设要添加数值2,可以计算出其在数组中的下标为2 / 640,在words[0]的位置为2 % 642,只需将1按位左移2位,然后和words[0]进行按位或操作,将相应位置置为1

位图添加成员

对于移除操作,假设要移除刚添加的数值2,和添加操作一样,可以通过计算得到其在数组的下标为0, 在words[0]的位置为2,只需将1按位左移2位再按位取反,然后和words[0]进行按位与操作,将相应位置置为0

位图移除成员

而对于查找操作,假设要查找数值3,可以计算得到其在数组的下标为0, 在words[0]的位置为3,只需将1按位左移3位,然后和words[0]按位与操作不等于0即可判断数值是否存在。

位图查询成员

以上内容简单介绍了 Java 中的BitSet的实现原理,实际代码还会稍微复杂一些,比如会涉及到数组扩容,范围边界的检测等等。有意思的是BitSet中计算数组下标和位置并没有使用除法和取模,都是通过位移操作实现的,x / 64是通过右移操作x >> 61按位左移x % 64位是直接将1左移x位即1 << x

位图对象还支持一些常用的位运算,如求交集(and, 按位与操作),求并集(or, 按位或操作),求差集(andNot, 按位与非操作)。

位图非常节省存储空间,位操作也非常高效,这也是为什么引入位图过滤黑名单能在毫秒级别处理完成的原因。

RoaringBitmap

遗憾的是,BitSet会占用过多内存。如果BitSet中只存储一个数值200000000,通过GraphLayout发现BitSet会占用约23MB内存,这种情况对空间的浪费极其严重。为了弥补这一缺陷,通常使用压缩位图。

RoaringBitmap是一种压缩位图,其性能往往优于WAHEWAHConcise等传统压缩位图。在某些情况下,RoaringBitmap的速度可以快上数百倍,而且压缩效果往往要好得多。它们甚至比未压缩的位图更快。如果使用RoaringBitmap只存储一个数值200000000,只需要144B的内存。

RoaringBitmap将一个int数值x划分为高16位和低16位,高16位下标可以通过x >>> 16得到,高位container中维护了一个数组,数组的元素中存储了低位container,低位container中的元素数量未达到4096时,使用ArrayContainer存储,其内部实现是一个char数组,数组中存放低位数值,达到4096后低位container会转换为BitmapContainer,其内部实现就是一个位图。此外还有一个RunContainer的实现,不过较少使用。

RoaringBitmap

为什么要使用4096这个阈值呢?是因为超过4096后,BitmapContainer会比ArrayContainer更节省空间。

container

存储long型数值时可以使用Roaring64NavigableMap,区别是它会将数值分为高32位和低32位。CDP存储人群的位图就是基于Roaring64NavigableMap实现的。

位图的应用场景

位图可以用较少的内存来表示大规模的布尔值集合,节省内存空间,并且支持高效的位操作,如ANDORXOR等,使得对集合进行复杂操作变得简单高效,对于存在性查询,位图可以在常数时间内完成,具有高效的查询性能。一些面试题中出现的几十亿数据的去重、排序、计数或者成员查询等问题,都可以通过位图解决,此外还有很多场景应用到了位图。

Java 中的位图应用

ArrayList为了提升性能并节省空间,重写了Collection接口默认的removeIf方法,重写后的方法使用了位图,首先遍历一遍元素用位图标记待删除的元素位置,然后遍历第二遍才真正删除元素,通过这种方式实现,可以高效移除元素,减少不必要的数组复制和元素移动次数,并且使用位图标记待删除位置也没有过多浪费空间。

位图索引

位图索引是一种特别适合于处理具有较少唯一值的列(例如性别、婚姻状况等)查询的数据结构,它在数据仓库等场合中非常有用,因为这些环境通常包含大量的数据读取操作和复杂的布尔逻辑查询,同时数据更新的频率相对较低。位图索引通过将列值映射到位上,并利用位运算来快速完成查询,能够有效提高查询效率,但它不适合那些具有高基数值和频繁更新的场景,因为这些场景下位图索引会占用大量空间并且更新成本很高。

Redis 的位图

Redis的位图非常适合于处理大量的布尔值数据,例如追踪用户的在线状态、记录用户每日签到或统计活跃用户数量等场景,因为位图通过每个位代表一个布尔值,可以极大地节省存储空间,并且Redis提供了丰富的位操作命令来高效地执行各种计算,如统计特定位上值为1的数量或者对多个位图进行位运算以实现快速的集合操作,这些特性使得位图在特征标记、实验分组以及AB测试等方面也非常有用;但是,需要注意的是,由于Redis将位图存储为字符串,因此其大小会受到字符串最大长度的限制,并且当数据量巨大时,对内存的使用效率也是一个需要考虑的因素。

布隆过滤器

数值可以很方便地使用位图处理,但是有些场景需要处理的可能是字符串,比如用户账号、URL等,一般需要将字符串跟数值做一个映射,CDP是将用户账号和偏移量offset做了一个映射表,再将偏移量offset存储到位图。布隆过滤器则是通过多个哈希函数将元素映射到了位图上,它是一种空间效率极高的概率型数据结构,它用于判断一个元素是否在一个集合中,并且能够非常快速地进行查询,常见的应用场景包括网络爬虫中避免重复爬取相同的URL、数据库中快速判断某个元素是否存在以减少不必要的磁盘IO操作、防止缓存击穿,以及各种需要快速集合检测且可以容忍一定误报率的场合,误报是指布隆过滤器可能会错误地判断某个不存在集合中的元素为存在,但它绝不会错误地判断存在的元素为不存在,因此在不需要百分之百准确性的情况下,布隆过滤器是一种非常有用的工具。

总结

通过探讨营销系统中优化黑名单过滤的策略,本文引入了位图这一数据结构,并详细阐述了其背后的实现机制及适用场合。位图特别适用于那些对空间效率和查询速度有极高要求的场景。在处理大数据时,位图通过压缩和优化可以极大地减少内存占用,提升数据处理的性能,希望本文能为大家提供有益的参考和帮助。

作者:京东科技 冯浩

来源:京东云开发者社区 转载请注明来源

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

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

相关文章

h5网页和 Android APP联调,webview嵌入网页,网页中window.open打开新页面,网页只在webview中打开,没有重开一个app窗口

我是h5网页开发&#xff0c;客户app通过webview嵌入我的页面 点击标题window.open跳转到长图页面&#xff0c;客户的需求是在app里新开一个窗口展示长图页面&#xff0c;window.open打开&#xff0c;ios端是符合客户需求的&#xff0c;但是在安卓端他会在当前webview打开 这…

Sora:新一代实时音视频通信框架

一、Sora简介 Sora是一个开源的实时音视频通信框架&#xff0c;旨在提供高效、稳定、可扩展的音视频通信解决方案。它基于WebRTC技术&#xff0c;支持跨平台、跨浏览器的实时音视频通信&#xff0c;并且具备低延迟、高并发、易集成等特点。 --点击进入Sora(一定要科学哦&#x…

MSS与cwnd的关系,rwnd又是什么?

慢启动算法是指数递增的 这种指数增长的方式是慢启动算法的一个核心特点&#xff0c;它确保了TCP连接在开始传输数据时能够快速地探测网络的带宽容量&#xff0c;而又不至于过于激进导致网络拥塞。具体来说&#xff1a; 初始阶段&#xff1a;当TCP连接刚建立时&#xff0c;拥…

Day50 739每日温度 496下一个更大元素I 503下一个更大元素II

739 每日温度 请根据每日 气温 列表&#xff0c;重新生成一个列表。对应位置的输出为&#xff1a;要想观测到更高的气温&#xff0c;至少需要等待的天数。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 例如&#xff0c;给定一个列表 temperatures [73, 7…

【Unity】管道流动模拟Shader

【Unity】管道流动模拟Shader 抽象模拟管道介质流动的效果&#xff0c;使用顶点片元着色器。可以调整管线光泽&#xff0c;颜色&#xff0c;流动方向&#xff0c;透明度&#xff0c;流动体粗细&#xff0c;流动速度和横断面。 实现效果 Demo效果 Demo下载地址 管线光泽调整 …

OpenAI最新Sora视频学习与生成的技术分析与最新体验渠道

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言OpenAI体验通道Spacetime Latent Patches 潜变量时空碎片, 建构视觉语言系统…

从 AGP 4.1.2 到 7.5.1——XmlParser、GPathResult、QName 过时

新年首发&#xff0c; 去年的问题&#xff0c;今年解决~ 问题 & 排查 1: Task failed with an exception. ----------- * What went wrong: Execution failed for task :app:processCommonReleaseManifest. > org.xml.sax.SAXParseException; lineNumber: 1; columnNu…

内存计算研究进展-通用的近数据计算架构

通用的近数据计算架构方面代表性工作有&#xff1a; AMD Research的 TOP-PIM&#xff0c;Carnegie Mellon Univeristy 的 TOM&#xff0c; University of Wisconsin-Madison 的 DRAMA 和 NDA&#xff0c;Seoul National University 的 PEI &#xff0c;IBM Research 的 AMC (ac…

【金蝶BI方案】做生产订单分析,要分析哪些指标?

一般来说&#xff0c;做生产订单分析要做量大部分的内容。一个是分析总的计划生产数据和实际完成情况、良品情况&#xff1b;另一个则是详细分析每种产品的订单量、计划生产数量、实际完工数量等。从而让运营管理者更加直接地了解到生产订单情况&#xff0c;更好地安排生产任务…

单片机学习笔记---红外遥控红外遥控电机调速(完结篇)

目录 低电平触发中断和下降沿触发中断的区别 红外遥控 Int0.c Int.h Timer0.c Timer0.h IR.c IR.h main.c 红外遥控电机调速 Timer1.c Timer.h Motor.c Motor.h main.c 上一节讲了红外发送和接收的工作原理&#xff0c;这一节开始代码演示&#xff01; 提前说…

九州金榜|家庭教育中孩子焦虑怎么办?

随着现代社会的快速发展&#xff0c;孩子们面临的压力和焦虑感也在逐渐增强。家庭教育作为孩子成长过程中的重要环节&#xff0c;对于如何有效缓解孩子焦虑情绪产生是家长不得不面对的问题&#xff0c;九州金榜家庭教育以为&#xff0c;我们需要了解孩子焦虑的根源&#xff0c;…

mysql同类型的多行变成一行value1和value2不同的列

关键字 row_number() over (partition by) 例如&#xff0c;下面的数据&#xff0c; 这是按照name分组后&#xff0c;展示property值。 我们想得到这样的值; 第一步&#xff1a;将每一组的property标上序号 select name,property,row_number() over (partition by name order…

Java中的Arrays和Lambda表达式

Arrays和Lambda Arrays常用方法数组中是对象&#xff08;如何排序&#xff09; Lambda什么是LambdaLambda表达式的省略规则 Arrays 是一个用来操作数组的工具类 常用方法 数组中是对象&#xff08;如何排序&#xff09; 方式一 方式二 Lambda 什么是Lambda 是JDK 8 开始新…

fastApi笔记03-请求体

请求体是客户端发送给API的数据&#xff0c;fastApi使用 Pydantic 模型来声明请求体 不能使用 GET操作&#xff08;HTTP 方法&#xff09;发送请求体。 要发送数据&#xff0c;必须使用下列方法之一&#xff1a;POST&#xff08;较常见&#xff09;、PUT、DELETE 或 PATCH 创…

自养号测评低成本高效率推广,安全可控

测评的作用在于让用户更真实、清晰、快捷地了解产品以及产品的使用方法和体验。通过买家对产品的测评&#xff0c;也可以帮助厂商和卖家优化产品缺陷&#xff0c;提高用户的使用体验。这进而帮助他们获得更好的销量&#xff0c;并更深入地了解市场需求。因此&#xff0c;测评在…

2024 互联网大厂职级和薪资一览表!

在向往互联网的朋友们的眼中&#xff0c;互联网大厂的工作可是一个“香饽饽”&#xff0c;无论是薪资福利、还是晋升制度&#xff0c;都是整个行业的标杆。 “大厂经验”更是互联网就业环境中的一块金字招牌&#xff0c;让简历光鲜度up up&#xff0c;对找工作有很大的帮助。 所…

GitHub | 在 GitHub 上在线展示 Vue 项目

简洁版&#xff1a;上传所有代码 << 构建项目并上传 dist 目录 << 设置仓库 << 访问 Step1&#xff1a;在 GitHub 上新建仓库&#xff0c;并将 Vue 项目的代码 push 到该仓库中。坑点在于&#xff0c;如果你是从 GitHub 上 clone 的别人的项目&#xff0c;那…

多层深度土壤墒情监测站

TH-GTS05随着科技的不断进步&#xff0c;农业生产的智能化和精准化已成为大势所趋。多层深度土壤墒情监测站作为现代农业的重要组成部分&#xff0c;为农业生产提供了强大的技术支持。 一、什么是多层深度土壤墒情监测站&#xff1f; 多层深度土壤墒情监测站是一种高科技农业设…

OpenCV 4基础篇| 色彩空间类型转换

目录 1. 色彩空间基础2. 色彩空间类型2.1 GRAY 色彩空间2.2 BGR 色彩空间2.3 CMY(K) 色彩空间2.4 XYZ 色彩空间2.5 HSV 色彩空间2.6 HLS 色彩空间2.7 CIEL*a*b* 色彩空间2.8 CIEL*u*v* 色彩空间2.9 YCrCb 色彩空间 3. 类型转换函数3.1 cv2.cvtColor3.2 cv2.inRange 1. 色彩空间…

Git基本操作(2)

Git基本操作&#xff08;2&#xff09; 上交文件之后&#xff0c;git文件的变化git cat-file HEAD指针里面有啥文件被修改git statusgit diff 文件名 版本回退&#xff08;git reset&#xff09;撤销回退git reflog 撤销的三种情况还没有addgit checkout -- [file] 已经add还没…