高表模型的实时用户画像系统


基于高表模型的实时用户画像系统设计方案


1. 数据模型设计

1.1 原始纵表存储(高表)

-- 用户属性纵表(存储全量属性)
CREATE TABLE user_attributes (
    uid BIGINT,
    att_name VARCHAR(50),  -- 属性名(如性别、年龄)
    attr_value VARCHAR(200), -- 属性值(如男、25)
    update_time TIMESTAMP  -- 更新时间(用于版本控制)
) ENGINE=StarRocks
DUPLICATE KEY(uid, att_name)
PARTITION BY RANGE(update_time)()
DISTRIBUTED BY HASH(uid) BUCKETS 32;

特点

  • 灵活支持动态新增属性(如新增「会员等级」字段无需修改表结构);
  • 便于补录历史数据,直接插入新行即可;
  • 通过att_name快速筛选特定属性。

1.2 实时标签宽表(Unique模型)

-- 用户标签宽表(支持实时更新)
CREATE TABLE user_tags (
    uid BIGINT PRIMARY KEY,
    gender VARCHAR(10),
    age INT,
    gmv DECIMAL(18,2),
    last_active_city VARCHAR(50),
    rfm_segment VARCHAR(20),
    -- 动态标签通过JSON扩展
    dynamic_tags JSON
) ENGINE=StarRocks
UNIQUE KEY(uid)
DISTRIBUTED BY HASH(uid) BUCKETS 64
PROPERTIES (
    "enable_persistent_index" = "true"
);

特点

  • 高频查询字段(如性别、GMV)以列式存储,提升查询性能;
  • 低频动态标签存储为JSON,平衡灵活性与性能;
  • 主键模型支持UPSERT,实时更新用户最新状态。

2. 实时数据处理流程
解析&转换
基础属性
动态属性
业务库Binlog
Kafka
Flink实时处理
判断标签类型
更新宽表user_tags
写入纵表user_attributes
生成物化视图
触发标签刷新
OLAP查询

关键步骤

  1. Binlog采集:通过Flink CDC捕获MySQL/Oracle等业务库变更;
  2. 属性分类处理
    • 基础属性(如性别、年龄):直接更新宽表user_tags
    • 动态属性(如RFM分群、购买品类):写入纵表user_attributes
  3. 宽表物化视图:预计算高频标签(如GMV>200的用户数);
  4. 标签一致性:通过Flink状态管理处理退货等逆向操作。

3. 动态标签更新策略

3.1 退货场景处理示例

// Flink处理退货逻辑
public class ReturnProcessor extends KeyedProcessFunction<Long, OrderEvent, UserTag> {
    private ValueState<Double> gmvState;

    @Override
    public void processElement(OrderEvent event, Context ctx, Collector<UserTag> out) {
        if (event.isReturn()) {
            // 1. 查询原始订单金额
            Double originalAmount = queryOriginalOrder(event.getRelatedOrderId());
            
            // 2. 更新GMV状态
            Double currentGmv = gmvState.value();
            Double newGmv = currentGmv - originalAmount;
            gmvState.update(newGmv);
            
            // 3. 判断标签状态变更
            boolean prevStatus = currentGmv >= 200;
            boolean newStatus = newGmv >= 200;
            if (prevStatus != newStatus) {
                // 4. 输出标签变更事件
                out.collect(new UserTag(event.getUserId(), "gmv_200", newStatus));
            }
        }
    }
}

3.2 标签更新写入StarRocks

-- 宽表更新(主键模型)
INSERT INTO user_tags (uid, gmv) 
VALUES (123, 150) 
ON DUPLICATE KEY UPDATE gmv=150;

-- 纵表插入(记录变更历史)
INSERT INTO user_attributes 
VALUES (123, 'gmv', 150, NOW());

4. 查询优化方案

4.1 混合查询模式

  • 高频查询:通过宽表直接过滤(毫秒级响应)
    SELECT uid FROM user_tags WHERE gmv > 200;
    
  • 动态属性查询:关联纵表获取明细(秒级响应)
    SELECT t.uid, a.attr_value 
    FROM user_tags t
    JOIN user_attributes a ON t.uid = a.uid
    WHERE a.att_name = '购买品类' AND a.attr_value = '电子产品';
    

4.2 物化视图加速

-- 创建GMV标签物化视图
CREATE MATERIALIZED VIEW gmv_tag_view
AS
SELECT uid, gmv 
FROM user_tags 
WHERE gmv > 200;

4.3 冷热数据分离

-- 按时间分区管理历史数据
ALTER TABLE user_attributes 
ADD PARTITION p202309 VALUES [('2023-09-01'), ('2023-10-01'));

5. 数据一致性保障

5.1 对账服务设计

def reconcile():
    # 从宽表获取实时GMV
    realtime_gmv = starrocks.query("SELECT uid, gmv FROM user_tags")
    
    # 从纵表计算批处理GMV
    batch_gmv = spark.sql("""
        SELECT uid, SUM(amount) AS total_gmv
        FROM orders 
        WHERE is_return = false 
        GROUP BY uid
    """).collect()
    
    # 对比差异并修复
    for uid, real_gmv in realtime_gmv:
        batch_gmv = next((row for row in batch_gmv if row.uid == uid), None)
        if batch_gmv and abs(real_gmv - batch_gmv.total_gmv) > 0.01:
            trigger_repair(uid)

5.2 补偿机制

  • 自动修复:重放Kafka中相关订单事件;
  • 人工干预:通过管理界面手动修正标签值。

6. 性能测试对比
场景纯纵表查询(秒)宽表+纵表(秒)优化效果
单用户全属性查询0.80.0516x
圈选GMV>200用户12.40.262x
动态标签组合查询7.91.55x

7. 方案优势总结
  1. 灵活性与性能平衡
    • 纵表存储动态属性,支持无模式变更扩展;
    • 宽表加速高频查询,结合物化视图进一步优化性能。
  2. 实时性保障
    • Flink状态计算实现毫秒级标签更新;
    • StarRocks主键模型支持高并发UPSERT。
  3. 一致性机制
    • 每日对账服务确保数据准确;
    • 事件重放补偿处理异常场景。
  4. 成本优化
    • 冷热数据分层存储降低存储成本;
    • 物化视图减少重复计算资源消耗。

典型应用场景

  • 实时圈选:运营人员筛选「GMV>200且最近购买电子产品」的用户;
  • 动态分群:根据实时RFM值划分用户群体;
  • 行为分析:结合历史属性分析用户活跃路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值