Flink 在字节跳动实时推荐系统中的使用实践 —— 每秒百万行为数据如何处理?

293 阅读3分钟

在字节跳动,每一次滑动、点击、点赞、评论,都会变成一个实时流式事件。为了将这些用户行为“秒级反馈”到推荐系统中,字节跳动采用了 Flink 构建大规模实时处理链路。本篇将带你从推荐系统的视角,理解 Flink 的角色,并用 PyFlink 编写一个“用户行为实时聚合”的核心原型。


🎯 一、推荐系统为什么离不开流处理?

推荐流程模块是否依赖实时数据?示例说明
用户画像更新用户30秒内点赞10条视频,兴趣需要立刻变化
内容热度计算某条视频突然评论暴涨,需实时排序靠前
CTR 模型训练滚动窗口内的点击率作为特征输入
AB 实验监控实验组与对照组数据需秒级归因

Flink = 用户行为在推荐系统中“闭环反馈”的加速引擎


🧠 二、字节跳动使用 Flink 的架构位置(简化示意)

lua
复制编辑
+------------+         +------------+         +-------------+
|  App用户行为  | --> | Kafka日志流 | --> | Flink 实时处理 |
+------------+         +------------+         +-------------+
                                                  ↓
                                            用户画像状态表 (HBase)
                                                  ↓
                                          推荐系统召回 & 精排
  • 每条点击、播放、点赞、评论等行为,都转为日志 → Kafka → Flink 处理
  • 结果存入状态系统或实时特征表,供推荐系统下一次请求使用

⚙️ 三、代码实战:用 PyFlink 实现实时点击聚合器

我们构建一个 Flink 流处理任务,用于统计每个内容的实时点击量(窗口滑动)


✅ 环境准备

bash
复制编辑
pip install apache-flink

如果部署困难,也可用 Flink SQL Gateway 本地测试


1. 创建 PyFlink 环境 & 数据源模拟

python
复制编辑
from pyflink.datastream import StreamExecutionEnvironment, TimeCharacteristic
from pyflink.common.typeinfo import Types
from pyflink.datastream.functions import KeyedProcessFunction, RuntimeContext
from pyflink.datastream.window import TumblingEventTimeWindows
from pyflink.common.time import Time

env = StreamExecutionEnvironment.get_execution_environment()
env.set_parallelism(1)
env.set_stream_time_characteristic(TimeCharacteristic.EventTime)

# 模拟用户点击数据:content_id, user_id, event_time
clicks = [
    ("v101", "u001", 1000),
    ("v101", "u002", 1500),
    ("v102", "u003", 2000),
]

2. 创建数据流 & 添加时间戳

python
复制编辑
ds = env.from_collection(
    collection=clicks,
    type_info=Types.TUPLE([Types.STRING(), Types.STRING(), Types.LONG()])
)

with_timestamps = ds.assign_timestamps_and_watermarks(
    lambda x: x[2]
)

3. 按内容ID聚合点击次数(窗口5秒)

python
复制编辑
from pyflink.datastream import WindowedStream

windowed: WindowedStream = with_timestamps \
    .key_by(lambda x: x[0]) \
    .window(TumblingEventTimeWindows.of(Time.seconds(5)))

windowed.reduce(
    lambda a, b: (a[0], "merge", a[2] + b[2])
).print()

可将结果写入 Redis、HBase 或 MySQL,用于推荐排序特征


📊 四、推荐系统中如何用 Flink 结果?

场景示例
热度打分hot_score = log(clicks + 1) + freshness
排序特征feature.hot_clicks_last_5min = 123
内容过滤点击为0的内容不召回
用户兴趣更新最近点赞的视频分类出现“科幻”→ 兴趣分提升

✍️ 五、总结与思考

  • Flink 让推荐系统从“天级反馈”变为“秒级响应”
  • 字节跳动的推荐闭环依赖流处理 + 状态管理 + 多路写入
  • 小团队也可以用 Kafka + Flink 实现用户行为 → 排序特征链路

🎁 拓展阅读

  • Flink 官方文档中文站
  • 《字节跳动实时推荐系统的演进实践》
  • 阿里:Flink 在淘宝首页推荐中的实时特征处理