前面的三年多一直在流量仓库,可是却偷懒,没有将学习到的东西好好归纳反思成体系。虽然现在已经没在做流量了,还是觉得需要回过头来复习规整一下。
什么是流量数据
流量数据,就是指用户在客户端(APP/PC/WAP/APP内嵌H5 等)的行为。举个例子:用户打开APP、退出APP、活动曝光到用户的屏幕上、用户点击某个活动等等。
客户端根据业务的需求在固定操作时去记录用户的行为,就是所谓的「埋点」或者「打点」
如何收集
目前业内日志服务器架构都大同小异: client->Nginx->Flume->Kafka->HDFS->Hive建模。
图我就懒得画了,可以参考一下美团的一些文章:
https://tech.meituan.com/2013/12/09/meituan-flume-log-system-architecture-and-design.html
https://tech.meituan.com/2013/12/09/meituan-flume-log-system-optimization.html
另外一些优化点:
- 日志批量上传,避免逐条发送导致qps过高(根据时间间隔及日志条数)
- 批量上传避免一次日志条数过多,控制每次批量的最高条数,可以有效避免由于requestbody太大导致的请求失败
- 通常日志使用json格式,而多条日志之间建议直接使用特殊字符分隔(如果使用json数组合并多条日志,某一个字符缺失就导致多条日志都无法解析)
- 固定不变的信息可以每次APP唤醒时发送(比如:设备信息、机型、mac地址、imei等),记录一个唯一的启动ID,后续行为带上启动ID,就可以将设备日志和行为日志合并起来
- app端可以对日志gz压缩以后发送到Nginx机器,节省用户流量(Nginx端直接用lua组件解压即可)
- 客户端记录一个累加的序列ID,可以通过序列是否连续来判断客户端日志丢失情况
收集内容
除了客户端的一些基本信息(时间、设备信息、版本信息、网络信息等),最重要的就是如何区分用户行为,不可能每个不同类型的行为都构建一个模型对不对?比如用户点击banner表、用户点击活动表、如果有上百种行为,这样可是会累死的!所以最简单的方式就是使用同一个模型,使用字段区分用户行为。
所以区分行为,最简单的做法就是使用一个固定的「行为ID」代表一个用户的行为。比如:点击商品 行为ID为1, 点击banner 行为ID为2。当用户点击商品时,客户端发送行为ID=1 即可。这种方式的缺点就是ID和行为对应关系匹配后,客户端开发需要根据ID手动埋点,所以这些埋点都是跟随版本的,最好做到每个版本添加的新功能都给埋上点。
区分行为是搞定了,但是如何区分用户具体操作的对象呢?比如点击商品,需要同时记录商品名、商品ID, 点击banner需要知道banner类型。莫非我们还是只能不同行为使用不同的表了?不不不,这里就加一个字段记录「行为参数」,值为json格式,这样就能兼容不同的行为拥有不同参数。比如行为ID为1 行为参数为:{"name":xxxx,"id":xxxx}, 行为ID为2 行为参数为{"type":xxxx}。
特点
做流量仓库,得有一些工程化的思维,与其他的数据模型还是有区别的。下面是我列出的一些差异:
内容 | 流量模型 | 交易模型 |
---|---|---|
数据来源 | 客户端 | 业务数据库 |
数据可靠性 | 不可靠 | 可靠 |
业务相关 | 弱 | 强 |
字段增减 | 尽量避免 | 根据业务需求增减 |
历史数据可变 | 否 | 是 |
数据量级 | 日活*N (活跃用户就有流量数据) | <日活 (不是所有用户都会下单) |
主要模型 | 当日用户行为模型(天) | 全量订单模型(天) |
- 数据来自客户端,没有业务数据库可靠,建模前需要先进行数据清洗
- 由于不可变性,几乎不会对历史数据进行刷新
- 天模型需要对小时模型汇总。(小时模型仅包含当前小时流量数据,模型执行完成后,天模型再汇总当天所有小时的数据。而对于有状态的订单模型,每个小时模型中的数据都是当天全量,当天最后一个小时数据直接可以当做天模型使用)