干货 | 携程国际业务动态实时标签处理平台实践

一、背景与挑战:国际业务标签处理的复杂性

携程作为全球领先的在线旅行服务平台,其国际业务覆盖200+国家与地区,用户行为、文化偏好、支付习惯等维度存在显著差异。传统标签系统面临三大挑战:

  1. 动态性不足:国际市场规则(如GDPR、CCPA)频繁变更,标签规则需实时响应;
  2. 计算效率低:跨时区、多币种、多语言的复杂计算导致标签生成延迟;
  3. 扩展性受限:静态架构难以支撑业务从10万QPS到百万QPS的爆发式增长。

以欧洲市场为例,某酒店标签需同时满足”近地铁口”(地理标签)、”支持欧元支付”(支付标签)、”德语客服”(服务标签)三重条件,传统批处理模式无法在用户浏览时实时完成标签计算与推荐。

二、平台架构设计:分层解耦与实时闭环

2.1 核心架构图

  1. 用户行为数据 Kafka集群 Flink实时计算 标签存储(HBase+Redis 应用层(推荐/风控/营销)
  2. 规则管理后台 MySQL/MongoDB 规则引擎(Drools

架构采用”数据流+控制流”双通道设计:

  • 数据流:通过Kafka实现毫秒级数据采集,Flink任务按区域(如欧美/亚太)拆分,利用KeyBy(region)实现计算资源隔离;
  • 控制流:规则引擎支持热更新,管理员通过后台界面修改标签规则(如”将’高端用户’阈值从年消费5万调整为8万”),规则变更通过Kafka通知Flink任务动态加载。

2.2 关键技术选型

组件 选型理由
流处理引擎 Apache Flink(支持Exactly-Once语义,状态后端用RocksDB应对TB级状态)
消息队列 Kafka 2.8(支持Tiered Storage降低存储成本,ISR机制保证数据可靠性)
存储层 HBase(标签宽表存储)+ Redis(热点标签缓存,ZSET实现标签权重排序)
规则引擎 Drools(DMN模型支持复杂规则可视化编排,避免硬编码)

三、核心功能实现:从数据到标签的全链路优化

3.1 实时数据采集与清洗

  • 多源接入:通过Flume采集APP/Web日志,Kafka Connect同步MySQL交易数据,Debezium捕获数据库变更;
  • 数据清洗:Flink SQL实现字段映射与异常值过滤,示例代码:
    ```sql
    CREATE TABLE source_kafka (
    user_id STRING,
    event_type STRING,
    timestamp TIMESTAMP(3),
    raw_data STRING
    ) WITH (‘connector’ = ‘kafka’, …);

INSERT INTO cleaned_data
SELECT
user_id,
CASE WHEN event_type = ‘click’ THEN ‘CLICK’ ELSE event_type END AS event_type,
timestamp,
CAST(JSON_VALUE(raw_data, ‘$.price’) AS DECIMAL(10,2)) AS price
FROM source_kafka
WHERE JSON_VALUE(raw_data, ‘$.price’) REGEXP ‘^[0-9]+(\.[0-9]{1,2})?$’;

  1. ## 3.2 动态标签计算引擎
  2. - **规则热加载**:Flink通过`Broadcast State`接收规则变更,示例逻辑:
  3. ```java
  4. DataStream<Rule> ruleStream = env.addSource(new KafkaSource<>());
  5. BroadcastStream<Rule> broadcastRules = ruleStream.broadcast();
  6. DataStream<Event> eventStream = env.addSource(new KafkaSource<>());
  7. SingleOutputStreamOperator<LabeledEvent> result = eventStream
  8. .connect(broadcastRules)
  9. .process(new KeyedBroadcastProcessFunction<String, Event, Rule, LabeledEvent>() {
  10. private transient MapStateDescriptor<String, Rule> ruleStateDesc;
  11. @Override
  12. public void open(Configuration parameters) {
  13. ruleStateDesc = new MapStateDescriptor<>("rules", BasicTypeInfo.STRING_TYPE_INFO, TypeInformation.of(Rule.class));
  14. }
  15. @Override
  16. public void processElement(Event event, ReadOnlyContext ctx, Collector<LabeledEvent> out) {
  17. MapState<String, Rule> rules = getRuntimeContext().getMapState(ruleStateDesc);
  18. List<String> matchedTags = new ArrayList<>();
  19. for (Rule rule : rules.values()) {
  20. if (rule.match(event)) {
  21. matchedTags.add(rule.getTagId());
  22. }
  23. }
  24. out.collect(new LabeledEvent(event, matchedTags));
  25. }
  26. @Override
  27. public void processBroadcastElement(Rule rule, Context ctx, Collector<LabeledEvent> out) {
  28. MapState<String, Rule> rules = getRuntimeContext().getMapState(ruleStateDesc);
  29. rules.put(rule.getId(), rule);
  30. }
  31. });

3.3 标签存储与加速

  • HBase优化:设计RowKey为region_userId,预分区避免热点;
  • Redis缓存:对高频查询标签(如”最近30天消费金额”)建立ZSET,示例命令:
    1. ZADD user:123:spending 1500 "2023-10-01"
    2. ZRANGE user:123:spending 0 -1 WITHSCORES # 获取消费记录时间序列

四、实施路径与效果验证

4.1 分阶段上线策略

  1. 灰度发布:先在东南亚市场试点,验证规则引擎稳定性;
  2. 全链路压测:使用JMeter模拟500万QPS,发现Kafka消费者滞后问题;
  3. 弹性扩容:基于K8s的HPA自动调整Flink TaskManager数量。

4.2 量化效果

  • 延迟:P99从1200ms降至85ms;
  • 资源利用率:CPU使用率从70%优化至45%;
  • 业务指标:国际酒店订单转化率提升3.2%。

五、经验总结与行业启示

  1. 架构设计原则:坚持”数据流与控制流分离”,避免规则变更影响计算性能;
  2. 技术债务管理:对HBase大Region进行定期Split,防止Compaction风暴;
  3. 合规性保障:通过标签脱敏模块(如对欧盟用户隐藏宗教相关标签)满足数据主权要求。

该平台证明,通过流批一体架构与动态规则引擎的结合,可有效解决国际业务中标签处理的实时性、灵活性与扩展性难题,为跨境电商、金融科技等全球化企业提供可复用的技术范式。