re:Invent全球大会引领风向重塑未来 了解详情
写点什么

苏宁精准营销之生成人群包的演进

  • 2018 年 11 月 10 日
  • 本文字数:3309 字

    阅读完需:约 11 分钟

苏宁精准营销之生成人群包的演进

一、前言

”精准营销”现在已经被大家熟知,并且成为各公司非常看重和依赖的营销模式,那么怎么才能在海量的数据里面精准找出人群去进行投放,相信每个公司都有一套不同的实现。苏宁易购作为一家大型智慧零售企业,“精准营销”在集团业务中承担着重要的角色,每天会生产数以万计的人群包,尤其是在大促中,更是承担着重要的责任,那么怎么保证快速、准确的生成人群包,满足业务的需要,下面是我们对生成人群包的技术的一些思考及演进过程,希望能让大家收获一些东西。本文推荐技术总监、架构师、技术经理、开发工程师等群体阅读。


二、业务介绍及面临挑战

业务场景分析

精准营销模式可以概括为 5W 营销分析框架,在合适的时机(When),将合适的业务(Which),通过合适的渠道(Where),采取合适的行动(What),营销合适的用户(Who),在整个过程中贯彻“以客户为中心”的理念,实现营销管理的持续改善,其中营销合适的用户即生成人群包,选出的人群是否精准直接决定着此次营销活动的成败。


生成人群包作为营销活动的生产引擎,其生产功率的大小和精准性,决定着生产人群包的效率与价值,效率和精准性对每天营销活动很多的公司来说尤为重要,我司生成的人群包主要分为线上人群包及线下人群包,当然线上会员和线下会员已融会贯通,线上会员可以通过精准定位及活动引流到线下,线下会员也可通过活动引流到线上,实现线上线下会员真正融合。每个营销活动的目的都是不一样的,那么它所关注的人群就不一样的,那么当然圈出人群的条件就是千变万化的,我们通过标签化用户特征行为,然后固化下来并及时更新的标签,来作为筛选人群的条件,通过标签来筛选出所要的人群,并进行投放。当然,这只是我们其中的一种筛选人群的方法,不同的业务不同的场景来锁定目标人群的方法都是不一样的。


挑战

  • 海量用户

  • 在生产人群包的的时候需要从几亿甚至数十亿的用户中筛选出你所需要的会员,怎么能做到快速准确。

  • 千变万化的条件组合

  • 每个营销活动的目的不一样,就导致筛选人群的条件不一样,怎样才能支持各种条件的互相组合。

  • 数以万计的人群包

  • 每天要处理数以万计的人群包,怎么保证在业务可接受的时间处理出来。

  • 系统的扩展性

  • 如何保证系统的扩展性,在存储资源、计算资源、以及存储形式上才能满足业务的持续扩展。


三、技术演进

生产人群包的技术演进主要经过了 3 个阶段:


1. 大数据 hive 任务创建


此技术方案是通过运用大数据平台(后面简称 ide)的存储计算能力来实现人群包的生产和投放,其中主要分为三块:业务系统负责人群条件的筛选;大数据系统负责进行存储计算,投放系统负责发进行投放;


业务系统主要承担后台的功能,为营销人员提供创建人群包的后台界面,使业务能通过一些界面化的一些操作就能生成人群,其将筛选的人群条件通过调用大数据平台的接口生成计算任务,得到计算结果即人群包。其主要的技术架构如下:



该技术方案分析:


通过创建任务的方式,在 cbt(大数据计算平台)上一个人群包创建一个计算任务,当人群包的数量越来越多的时候,将造成任务数量越来越多,计算资源需求也越来越多,机器资源总是有限的,就会造成计算瓶颈,延长人群包的生成时间。


动态的创建任务对大数据平台的调度及稳定性造成了一定的影响,不能因一个系统的业务而增加公共系统不稳定的风险


针对以上问题,我们在技术实现方案上提出了一些优化的设想:


hive 是把所有的数据拿过来进行计算,而且没有索引的机制,我们为什么不能用索引的方式来增加计算速度,原来用几分钟算好一个人群包,通过索引的方式是否能达到秒级,这样处理人群包速度就会有大的提升,在业务要求的时间内用更少的资源来完成更多的计算。


通过增加消息中间件来实现业务系统与 ide 的解耦。


2. Spark + ES


此技术方案是采用 kafka 将业务系统跟 ide 解耦,然后通过 sparkStreaming 来消费 kafka 中的数据存储到 hive 表中,然后创建一个 spark 的任务来分批获取 hive 表中的数据,然后在 driver 端多线程的根据条件来查询 es(ElasticSearch)并将最终结果存储到 hive 表中,相当于一个 driver 多组并行的 excutor,提高生产人群包的并发度,加快人群包的生产速度。其生产人群包的速度是原先的几十倍,乃至上百倍,相比于第一个方案,性能有了质的飞越,并且使用的机器资源有了大幅度的降低。


Spark 天生支撑 ES(ElasticSearch)的查询,有现成的封装代码,使用起来非常简单,基本上是一个查询中一个分片一个 excutor,有助于项目的快速启动及实现,而且 es(ElasticSearch)是分布式搜索引擎,可动态扩展,采用多副本容灾,保证了系统的健壮性,及其可扩展性。


其主要的技术架构如下:



该技术方案分析如下:


由于采用 es(ElasticSearch)作为数据的存储及查询引擎,当新增一个或几个字段的时候,要重新往进灌数据,而且 es(ElasticSearch)中存储的是全量的索引数据故重新灌一遍数据需要很长的时间。


es(ElasticSearch)中的 mapping 字段越来越多的情况下会对创建索引及检索的速度产生影响,使性能下降很快


通过 es(ElasticSearch)聚合人群预估人数的时候查询很慢要达到秒级。


3. Spark + pg + roaringbitmap


Roaringbitmap 是一种十分优秀的压缩位图索引,被广泛用于数据库和搜索引擎中,通过利用位级并行,它们可以显著加快查询速度。


因此,我们将 elasticsearch 换成了 PostgreSQL + roaringbitmap 插件,来提高我们的查询速度,我们采用将用户和标签形成倒排方式进行存储,也就是一个标签里边包含所有拥有这个标签的用户,用户形成一个 roaringbitmap,通过 roaringbitmap 的交并差,形成最终的人群。


其主要的技术架构如下:



该技术方案解决了第二种方案里增加字段的难题,基本上实现了业务的无限扩展,并提升了查询的响应速度,这套方案也是我们苏宁目前正在运行生成人群包的技术方案,为各大促及日常营销活动提供了强有力的支撑。


四、踩过的那些坑

1. 向同一个 hive 表中 insert into 数据


第二种方案中当全量人群包计算的时候会向同一个 hive 表中插入不同的人群包数据,而且是并行插入,在最开始的时候很快到后面越来越慢,基本情况如图:



后来我们针对这种情况进行了优化,采用分区的方法来进行解决,也就是按照人群包的 id 进行分区,每个人群包的人群数据存储到一个独立的分区上,修改完成后存储性能得到了极大的提升。


2. Es 中_source设置,在查询人群明细时减少 io


_source是一个自动生成的字段, 用来存储实际提交的 JSON 数据, 他是不索引的(不可搜索), 只是用来存储。 在执行"fetch"类的请求时, 比如 get 或者 search, _source字段默认也会返回。这个存储十分的占用磁盘空间,而且在进行大批量检索时会非常的占用磁盘 io。


因为我们只需要返回用户 id 故对_source字段进行了设置,让其只保存用户 id,这样既节省了存储空间又减少了查询时磁盘 io 过大的问题。设置如下图:



3. Spark 任务读取 es 人群详细数据时 driver oom


Spark 生成人群包的任务,在运行一段时间后出现 oom(out of memory),刚开始的时候也没有注意以为是内存不够,直接增加内存,但是增加内存之后,后面还是不间断的出现 oom(out of memory)现象,后面进行分析发现,spark 在读取 es(ElasticSearch)数据的时候会将一些配置信息、dsl(Domain Specific Language)等存储到 driver 端,当并行获取很多个人群包详细信息的时候就会把内存打满,后面我们在 driver 端将开启的线程数降低,解决了次问题。


五、总结

以上内容就是我们生成人群包的一些技术实践,通过不同技术方案的持续优化和改进来满足业务提出的目标,为企业创造更大的价值,减少无谓的资源浪费,这就是我们技术人存在的价值。我们会持续的优化改进下去,技术方案的改进和优化就像一场没有终点的马拉松,永远在路上。在这里只是给大家抛砖引玉,当前方案中如果有什么不对或者不足的地方,欢迎提出来我们一起探讨改进。


作者


王志伟,苏宁易购 IT 总部大数据中心标签研发部部门负责人,对推荐系统、精准化营销及高并发、高流量应用等方面的架构及研发有着深刻的理解及实战经验,拥有 6 年以上相关领域经验。目前负责苏宁易购标签平台、精准化营销的工作,多次主导大型促销活动推荐系统、精准化营销性能优化,对标签、推荐、精准化营销有着深刻的认知。


2018 年 11 月 10 日 08:281726

评论

发布
暂无评论
发现更多内容

模块四作业

Mr.He

架构实战营

安全世界观 | 常见WEB安全问题及防御策略汇总

架构精进之路

安全 8月日更

阿里开发人员献礼“Java架构成长笔记”,深入内核,拒绝蒙圈

Java~~~

Java spring 面试 微服务 架构师

毕业感想

薛定谔的指南针

架构实战营

【Docker 系列】我们来看看容器数据卷到底是个啥

普普通通程序员

华为大佬的“百万级”MySQL笔记,基础+优化+架构一键搞定

Java~~~

Java MySQL 数据库 面试 架构师

新手小白花几个月勇敢裸辞转行网络安全

网络安全学海

网络安全 信息安全 转行 渗透测试 安全漏洞

Java架构速成笔记:七大专题,1425页考点,挑战P8岗

Java~~~

Java spring 面试 微服务 架构师

200道Java灵魂考题:全部掌握拿下阿里P7腾讯T3.2

程序员改bug

Java 架构 编程语言

模块四作业

秀聪

架构训练营

Github访问量破百万!原来是美团大牛的分布式架构实战笔记上线了

Java~~~

Java 面试 分布式 微服务 架构师

04-可扩展架构

Lane

【架构实战营】毕业设计

swordman

架构实战营

设计千万级学生管理系统的考试试卷存储方案-模块四

小牧ah

架构实战营

架构实战营-毕业设计项目

阿体

单向数据流-从共享状态管理:flux/redux/vuex漫谈异步数据处理

zhoulujun

React Redux vuex vue2 状态机

从java注解漫谈到typescript装饰器——注解与装饰器

zhoulujun

Java 注解 装饰器 ts 元数据

初学字典-python

加哥

硬核!啃完666页Java面试高频宝典,4月成功定级腾讯T3-2

程序员改bug

Java 编程 程序员 架构 面试

毕业设计作业

薛定谔的指南针

架构实战营

微信朋友圈的高性能复杂度分析

Saber

架构实战营

腾讯技术官手撸笔记,全新演绎“Kafka部署实战”,已开源

Java~~~

Java MySQL 面试 MQ 架构师

06-高可用复杂度

Lane

架构实战营模块四作业

王晓宇

架构实战营

三维旋转笔记:欧拉角/四元数/旋转矩阵/轴角-记忆点整理

zhoulujun

矩阵旋转 欧拉角 三维旋转 四元数

13W字!腾讯高工手写“Netty速成手册”,3天能走向实战

Java~~~

Java 面试 微服务 Netty 架构师

我们是如何优雅修改正式环境的表结构,而不影响线上运行的?

普普通通程序员

Android Jetpack Compose

Changing Lin

8月日更

记录一次基于Qt的内存数据修改工具开发

星河寒水

qt 内存数据修改 Cheat Engine

其实,这就是「幸存者偏差」

非著名程序员

提升认知 认知提升 个人提升 8月日更

05-高性能复杂度

Lane

撑起瞬时千亿交易额的云数据库是怎么炼成的?

撑起瞬时千亿交易额的云数据库是怎么炼成的?

苏宁精准营销之生成人群包的演进-InfoQ