1 什么是归因分析
归因分析说明
(Attribution Analysis)归因分析就是从客户的行为轨迹(Customer Journey)中去分析营销策略成功的原因(Attribution of Success)。举例来讲就是小明购买天猫精灵的消费行为是由哪些渠道广告促成的?这些渠道的贡献占比多少?
归因模型介绍
“归因模型指一个规则集,用于解释和衡量转化路径中每个接触点所贡献的转化量或转化价值”。目前最通用的一种是“last click attribute model”,即把100%的功劳给与离转化最近的一次广告点击。其它还包括线性模型、时间衰退模型、数据驱动模型等等。详情请参考文章[2]
归因窗口介绍
归因窗口(Attribution Window)有时也叫做转化窗口(conversion window)是一个连续的时间段,在这段时间内可以推导出对已经发生的“转化”的“贡献”,这里转化通常指购买,贡献通常指广告曝光或广告点击。Facebook提供的归因服务默认采用1天的曝光窗口和28天的点击窗口。[3]
2 实时归因的价值
归因的作用就是找到“成功的原因”,这可以使你持续保持成功,并且通过对“成功过程”的深入洞察,可以调整营销策略来获得更大的成功,最终提高投资回报,提高产品的客户群体。
实时归因是未来发展趋势[4][5]
2.1 天下武功唯快不破,今天的客户已经进入快消时代越来越缺少耐心,今天的营销渠道也是多样生态且有新场景涌现,今天RTB(实时广告竞价)已经大面积应用,所以实时归因也必须跟上步伐。
2.2 real time = right time,更加快速、细粒度的客户洞察使我们可以及时响应市场,及时优化营销策略。我们也可以及时发现潜在客户并给与定向干预,从而加速转化率以及转化周期。
3 实时归因的挑战
3.1 归因需要的用户行为数据体量大、写入频率高,需要系统有很好的扩展性
3.2 归因模型虽然以last click最常见,但其它更优秀的模型也在快速发展,需要系统支持多模型
3.3 归因窗口差异性较大,有些只需要20分钟,有些几天,有些要1个月或者更长。需要系统有灵活的存储和读取能力
4 如何设计归因系统
站在巨人的肩膀上,先看一下业内大佬们的解决方案
4.1 Netflix方案
如下图所示,Netflix使用Stream Processing层来实现Customer Journey的收集和存储。具体数据模型上是两张表,“impression table”存储所有的曝光、点击等事件,事件中至少包含用户ID与广告供应商ID。“conversion table”(Netflix 叫做 play,因为对于他们来讲转化=播放)存储所有的转化事件,事件中也包含用户ID。“impression table”和“conversion table”存储在S3上。然后通过Spark跑批对这两个表进行Join来实现归因计算[6]。
这个一个比较成熟的方案,可以解决上面提到的很多问题。首先数据持久化在S3上,S3支持PB级别存储且具备优秀的扩展性。其次Spark 可以支持丰富的计算,可以对一份数据应用多种归因模型。最后计算本身不受窗口大小限制。
但是这个方案的缺点也很明显,就是不那么实时。
4.2 Databrics方案
Databrics方案其实在架构上并没有跳脱出Netflix方案,只是将S3换成了Delta Lake,但是把整个方案的实时性提高了[7]。
在Netflix方案中,Spark Streaing直接写入S3,如果速度过快比如1秒一个文件,势必会产生非常多的小文件,对计算不友好。为了解决这个问题就需要做Compaction合并,合并完要删除小文件,但如果这个小文件还在被读取就会造成一致性问题。Delta Lake很好的解决了数据湖更新问题,提供ACID保障,自动合并小文件,还具备分布式元数据能力,综上Delta Lake可以让事件入湖达到秒级延迟。
但是解决了前半部分的实时性,后半部分还是有点问题,其架构图中显示归因计算还是用Spark批处理。但在演讲中提到Delta Lake提供CDC(Change Data Capture) 即数据订阅能力,可以对接Spark Streaming。
总的来看,继承了Netflix方案的优点,在实时性上有较大优化。但整体链路还是有点长,距离实时差了点味道。感觉是一个near real time范本。
4.3 Flink方案
下面我们介绍小红书基于Flink的实时归因方案,原文见[9]。这是一个非常酷的方案,其链路非常短Kafka + Flink就足够了,核心利用的是Flink的Session Window。Session Window是这样一种Window,它包含一个起始时间和一个超时时间,如果一个事件落在了起始时间和超时时间之内,那么该事件属于这个Session,并且超时时间会随之更新。
Flink使用Session Window来实现归因窗口(Attribution Window),Customer Journey存储在Session Window里,在Session Window结束时调用处理函数做归因计算。虽然在小红书的例子中其实没有做计算,只是将归因数据输出到了下游,但是这个架构是完全可以在Flink中就进行归因分析的。
使用流计算(Flink or SparkStreaming)来实现归因的最大好处就是链路短时效性强。但是也存在如下问题:
1 session window中状态太多,消耗系统资源,成本高
2 很难处理周、月级别的归因窗口,不管是Kafka还是Flink都不适合存储大量的数据
3 准确性不足,Session Window的超时时间设计是门艺术,比如超时设置20分钟,但在20分1秒发生了转化怎么破?
4.4 我们期待的是一个什么样的系统?
- 快,实时归因是我们的追求
- 准,归因分析能更真实的反应实际情况。这要求:归因数据要一致且全面,能支持多种归因模型
- 通,通用性,可以支持不同的归因场景,特别是不同的Attribution Window
- 稳,架构简单易维护
- 省,尽量少花钱:)
5 一种基于Lindorm的Event Sourcing解决方案
为了达到实时归因,采用流处理架构。把状态外置解决流处理存储大量状态的问题,Session State中仅保留开始事件和结束事件,整个Customer Journey从外置存储中摄取,这个外置存储就特别符合一个Event Sourcing。
考虑用Kafka来做这个Event Sourcing,虽然kafka支持reprocessing,但其只能做到分区级别的顺序消费,无法支持Key级别的顺序消费,很难支持基于单个用户的归因,另外Kafka也不适合存储月级别的数据。
考虑使用HBase来做Event Sourcing,HBase支持水平扩展存储PB级别数据(good),HBase支持高并发范围查询可以用来实现Customer Journey的摄取,扫描10000条也就百毫秒,而且支持反向扫描(good)。但是HBase没有CDC功能,无法驱动流计算系统。所以你要再加一套Kafka,双写Kafka和HBase,这一看就很复杂难维护。
综上,Kafka和HBase都有优点和缺点,我们推荐使用Lindorm来做Event Sourcing,Lindorm宽表完美继承HBase优秀基因,Lindorm Streams提供数据订阅能力。
这套架构的优势:
- 快,Fink/Spark Streaming 提供实时处理
- 准,Lindorm 作为Event Sourcing可以支持批流一体,批计算保障最终一致(本人倾向流计算终将一统天下,但目前看批流一体还是比较成熟)
- 通,支持不同的归因场景,不同的Attribution Window。Fink/Spark支持丰富计算,Lindorm支持高效存储和摄取
- 稳,只需要Lindorm 和 流计算引擎
- 省,流计算引擎只需要存储少量的状态。Lindorm具备高效压缩、透明冷热分离等降本手段。
参考
[1] The 3 Biggest Problems with Advertising Attribution
[2] 电商中,常用归因模型的介绍与分析
[3] The Facebook Attribution Window
[4] The power of real-time attribution in a multi-channel world
[5] PREPARING FOR THE FUTURE: WHY REAL-TIME ATTRIBUTION IS ESSENTIAL
[6] Near Real-Time Netflix Recommendations using Apache Spark
[7] Real-Time Attribution with Structured Streaming & Databricks
[8] Building a Real-Time Attribution Pipeline with Databricks Delta
[9] 小红书如何实现高效推荐?
## 咨询交流 欢迎加入Lindorm技术交流群 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/d8b2d91125404eec9e0003009273f769.png)