画像平台人群创建方式-规则人群创建

2023-10-18 22:05:17 浏览数 (2)

规则圈选是按照指定条件从画像数据中找到满足要求的用户并沉淀为人群的一种常见的人群创建方式。所谓的规则就是条件的组合,比如北京市男性用户,最近一周平均在线时长介于2到10分钟之间的中老年用户。规则圈选的实现依赖画像宽表数据或者BitMap数据,其实现逻辑如图5-12所示。

图5-12 规则圈选人群实现逻辑图5-12 规则圈选人群实现逻辑

筛选北京市男性用户的需求可以通过画像平台可视化页面表达出来,其圈选配置最终通过接口传递到平台服务端并存储在数据库MySQL中。人群创建引擎读取到规则人群配置信息后,首先判断是否适合通过BitMap实现人群圈选,如果适合,可以获取标签的BitMap在内存中进行交、并、差操作;不适合BitMap实现的可以兜底通过ClickHouse画像宽表进行人群筛选,其实现逻辑是将人群圈选条件转变为SQL语句,借助ClickHouse引擎查询出所有满足条件的UserId并构建人群;当ClickHouse执行异常时会再次兜底从Hive表中筛选用户,同理,人群圈选条件最终转换为Hive SQL语句并最终将执行结果构建为人群。前两种执行方式生产的人群会优先产出BitMap并存储到OSS中,第三种方式生成的人群数据直接存储在Hive表中。为了实现人群数据的持久化存储和便捷的接口调用,人群数据最终会存储在Hive表和OSS中。

基于BitMap进行人群圈选主要分为两步,第一步是从ClickHouse中读取标签BitMap,第二步是在内存中进行BitMap的交并差运算,其实现语句如下所示。其中代码重点是将字符串格式的数据转换为RoaringBitMap,并通过其自带的and函数进行交集计算。目前最新的ClickHouse版本中也支持自定义UDF函数,可以将上述步骤封装为UDF函数后直接使用。

代码语言:javascript复制
-- 第一步:从ClickHouse表中读取性别-男BitMap,同理可获取省份-北京市BitMap--
SELECT
bitmap
FROM
userprofile_demo.gender_label_bitmap_ch
WHERE
p_date = '2022-08-05'
AND label_value = '1'
// 调用stringToBytes()和bytesToBitMap函数将string转换为RoaringBitMap
public static byte[] stringToBytes(String str) throws IOException {
// 参见上文函数实现
}
// 字节数组转换为BitMap
public static Roaring64Bitmap bytesToBitMap(byte[] bytes) throws IOException {
// 参见上文函数实现
}
// 第二步:BitMap之间计算交集
maleBitMap.and(provinceBitMap);

基于ClickHouse宽表进行人群圈选的方式比较简单,其SQL语句如下所示,工程代码遍历其查询结果中的所有UserId并写入BitMap。目前ClickHouse支持将数组封装为BitMap格式的数据,这样可以在ClickHouse内部实现UserId的聚合,从而降低传输UserId的带宽消耗。基于BitMap和ClickHouse宽表生成的人群BitMap可以直接上传并保存到OSS中。

代码语言:javascript复制
-- 从ClickHouse表中查询出所有北京市男性用户UserId --
SELECT
user_id
FROM
userprofile_demo.userprofile_wide_table_ch
WHERE
p_date = '2022-08-05'
AND gender = 1
AND province = '北京市'
// 通过ClickHouse JDBC 执行SQL语句,获取ResultSet并遍历结果中的UserId
Roaring64Bitmap crowd = new Roaring64Bitmap();
while (rs.next()) {
long userId = rs.getLong(1);
crowd.add(userId);
}
-- 通过BitMap返回所筛选的UserId,返回格式为byte[],需要反序列化为RoaringBitMap --
SELECT
groupBitmapState(user_id) AS bitmap
FROM
(
SELECT
user_id
FROM
userprofile_demo.userprofile_wide_table_ch
WHERE
p_date = '2022-08-05'
AND gender = 1
AND province = '北京市'
)

通过JDBC连接HiveServer可以运行Hive SQL语句,基于Hive表进行人群圈选的SQL语句示例如下所示,SQL执行后人群结果数据将直接存储到人群结果Hive表中。

代码语言:javascript复制
INSERT OVERWRITE TABLE userprofile_demo.crowd_result_table PARTITION(crowd_id = 100)
SELECT
user_id
FROM
userprofile_demo.userprofile_wide_table
WHERE
p_date = '2022-08-05'
AND gender = 1
AND province = '北京市'

人群结果最终要存储在Hive表和OSS中。Hive表中的人群数据主要用于离线数据分析场景,很多业务使用人群之后需要通过人群结果表进行效果分析。图5-13展示了人群结果表的表结构设计,人群crowd_id作为分区键,分区下包含该人群所有用户。OSS中的人群数据主要应用在通过接口获取人群数据的场景下。人群数据压缩为BitMap并存储到OSS中,一亿人群大小在100M左右,通过接口可以在几秒内获取到人群结果。

图5-13 Hive人群结果表图5-13 Hive人群结果表

每一个人群最终都会存储在Hive表和OSS中,但是不同人群创建方式优先产出的人群存储类型不同,所以画像平台需要支持Hive和OSS之间数据的相互转换。图5-14展示了Hive和OSS人群BitMap之间相互转换的主要方式。HiveToBitMap主要通过Spark/Flink批量读取Hive表中数据,在内存中构建BitMap后存储到OSS中;BitMapToHive需要将内存中的数据快速写入Hive表,主要分为写入本地文件、上传到HDFS以及加载成Hive表三个步骤,该过程与第3章中通过文件导入创建标签类似。相关代码和步骤本章不再赘述,可以参考第3章中对应内容。

图5-14 人群数据Hive与BitMap之间转换图5-14 人群数据Hive与BitMap之间转换

本文节选自《用户画像:平台构建与业务实践》,转载请注明出处。

0 人点赞