广告精准投放人群的实现:千万用户过滤指定人群
背景
厂商希望自己的广告可以精准地投放给有指定行为的一些用户,或者排除一些自己不想投放的人群,比如已经下载过这个游戏的用户。
产品:希望能有个后台可以进行配置,选择广告,然后选择若干人群包,方式选择包含或排除。
我:ok
简单流程和问题分析
首先需要根据厂商的要求将特定的人群圈出来,通过用户特征进行过滤生成人群包。
后台需要根据配置拉取对应的人群包,并存储在特定的地方。
对应广告提供的接口,需要根据配置判断用户是否属于配置的人群包中的一员来决定是否展示广告。
流程看上去那是非常的简单,但是其中的坑不得不防
生成的人群包可大(千万)可小(几百),如果同时拉多个人群包可能会出现 OOM 的风险
将人群包存储在哪里也是个问题,后台配置一旦多了起来,内存完全不够用
如何判断用户是否属于配置的人群中,从千万数据中判断其中一条是否存在的问题
头脑风暴
我们需要一个个解决过去
首先是拉取人群包的问题,一开始采用递归的方式进行分页拉取,然后内存爆了而且拉取速度非常慢。
后来发现是递归过程中产生的对象并没有及时的清空,导致内存 OOM,用多线程+伪递归进行拉取解决问题,千万数据保证在 2 分钟左右拉取完成
然后人群包存储的问题,千万数据该存储到哪里!存到 tidb?no!每次获取广告都取数据库分分钟超时!redis?可以是可以,但是如果一个人群包对应一个 key-value,那肯定是个大 key!想要存储这么大的数据又要同时获取的数据非常快,一开始我们只想到了 redis,我们将大 key 进行分散,将横向扩展变成纵向扩展,使用用户 id 和广告 id 做 key,redis 中有则排除或包含,响应速度也一直很快
但是 随着配置的人群包越来越多,redis 的 key 就越来越多,这样下去是有一定风险的
有没有什么办法对人群包进行压缩,然后又可以快速查询的数据结构呢!
有的!RoaringBitmap!
RoaringBitmap
Roaring Bitmap 是一种压缩位图(BitSet)的数据结构,它以更高效的方式序列化和反序列化比传统 Java BitSet 更大范围的位集合。RoaringBitmap 比较适合那些明显不连续的相对稀疏的数据。
RoaringBitmap 的主要特性:
高效的 AND, OR, XOR, NOT 操作。
支持对单个元素的高效添加和删除。
支持高效的聚合操作(如统计位数、找到最小/最大的位等)。
更低的内存消耗。
高效的序列化和反序列化。
RoaringBitmap 的使用示例:
使用 RoaringBitmap 很简单,下面是快速的的使用示例。
添加或查询元素:
执行位操作:
总结
还是有很多坑点是没有写出来的,写项目前多想想,重构真的很难受!
这个项目中其实最有意思的是用户画像,可惜我不会,难受。
版权声明: 本文为 InfoQ 作者【xfgg】的原创文章。
原文链接:【http://xie.infoq.cn/article/9a8bc77d56d304da285d6f804】。未经作者许可,禁止转载。
评论