客户画像系统在不同公司有不同的业务场景需求,但总的目标基本都是由于客户越来越多,我们需要对海量的客户信息进行降维,进而更好的理解客户和精准推荐或者营销。基础的客户画像系统有如下几种需求:
- 输入用户 id, 输出用户相应的画像标签
- 输入用户 id,相应标签和指定时间区间,输出对应标签值在这段时间内的变化情况
- 输入多个标签值,输出满足指定标签值的一组用户(精准推荐或营销用)
- 输出的标签最好能和业务数据进行关联
这四个需求虽然都可以通过 HBase 实现,但是对于需求3这种搜索的场景,用 HBase 来实现则往往需要 scan 全表,而且范围查询也不易实现。我们可以选用 ES(ElasticSearch) 来作为搜索过滤。对于需求4,常用的数据仓库有 Hive, 我们可以通过外表的形式关联 HBase, 也可以定期从 HBase 导入至 Hive.
系统架构及数据流
- 源数据层:数据源可以是关系型数据库,实时行为日志,Hive 仓库或者从 HBase 加工过的标签数据。
- 计算引擎层:使用 Spark 作为中间的计算引擎和不同的数据源接口可以省掉繁琐的数据驱动整合工作,同时借助 dataframe API 可以高效的进行异构数据源关联分析和处理。
- 数据分发层:使用 HBase 作为主存储,ES 通过 HBase 的 coprocessor 机制同步更新,往 ES 写可以通过批量写减少网络 IO。Hive 通过外表则不必做专门的数据同步操作,但是这种方法效率往往不高。
- 数据对外使用层:通过 REST API 查询 HBase 和 ES 获取所需标签/用户 id
+------------+
| |
+-----------------> | REST API |
| | |
| +------+-----+
| ^
| |
| |
+--------+ +----+----+ +----+----+
| | external | | coprocessor | |
| Hive | <-------------+ HBase +--------------> | ES |
| | | | | |
+--------+ +----+----+ +---------+
^
|
+-------------+-------------+
| |
| Spark / Spark Streaming |
| |
+-------------+-------------+
^
|
+--------------------+------------------+
| |
| Hive, SQLServer, MySQL, HBase, HDFS |
| |
+---------------------------------------+
Spark 写 HBase 可以用 hortonworks-spark/shc
其中 HBase 写 ES 和 Hive 建外表的细节另外写两篇博文做深度一点的解析,这里不再赘述。
数据模型映射
Spark dataframe <==> HBase
我们知道 HBase 主要是通过 rowkey 来实现快速查询,对于典型的用户画像场景,用户 id 往往必不可少。但 rowkey 在 HBase 中的存储为字节数组,且为了更好发挥 HBase 分布式存储的效率,我们需要防止用户 id 过于集中造成热点,这里我们可以尝试将 int 型数据映射到 00000000~FFFFFFFF 内,然后反转字符串即可完美适配 HBase 对 rowkey 设计的要求。
对于 HBase 往 ES 的数据同步,我们主要利用了 HBase coprocessor 绑定更新/删除事件进而对 ES 同步。这里一个比较棘手的问题是 HBase 的内容都是以字节数组存储的,比较理想的方案是同步到 ES 时保留类型信息以便范围查询。这里我采取的方案是通过 Spark dataframe 取出类型信息,在写入 HBase 时列的最后一个字节用于类型标记,如 i -> integer
, d -> double
, s -> string
. 这样就完美的解决了类型的转化问题了,还能自适应匹配。
HBase 中的 rowkey 可以映射为 ES 中的 docid, 列名 cf:tag_namespace.tag_name
可以映射为 ES 中的 JSON 嵌套结构。
HBase <==> ElasticSearch
TODO
HBase <==> Hive
TODO