精准营销系统是基于数据和技术的营销解决方案,旨在帮助企业实现更精确、个性化的营销策略
数据驱动:系统依赖于大数据分析和挖掘技术,可以收集、整理和分析大量的用户数据。通过深入了解目标受众的需求、行为和偏好,企业可以更准确地定位和满足他们的需求。 个性化营销:系统可以根据用户的个人喜好、历史数据和行为模式,提供个性化的营销内容和推荐。这有助于增强消费者的参与度,并提高转化率。 多渠道触达:系统可以整合并管理多个营销渠道,包括站内信、智能语音、短信营销等。
通过大数据深入分析用户数据和行为信息,精准锁定目标群体,并可根据预设条件或实时事件触发,定向推送个性化信息或执行特定批处理任务。进行个性化的决策和营销策略
基于用户特定的行为,我们提供实时的决策和指令触达服务,例如弹出信息、发放优惠券等,以满足您对特定用户群体的营销需求
根据不同的营销场景,我们可以聚合数据源并提取所需的变量,然后根据预设的规则进行决策。您可以查看决策日志以了解每个决策的结果
指令集主要分为三大类别。首先是触达类指令,这些指令包括短信、站内信、AIM短信和智牛等,用于与用户进行沟通。其次是权益类指令,包括优惠券、发放奖品(如话费券、JD卡等)以及提额等,用于为用户提供特定权益或提升用户福利。最后是系统类指令,包括进件服务、决策服务以及延迟执行等,用于提供更高级别的业务功能和操作。
主要包含两个核心部分。首先是规则的编写、管理和发布,这些步骤是建立一个高效营销系统的基础。其次是规则的路由和规则的执行
案件进件到系统中进行营销的三种主要途径包括:1通过后台管理界面,您可以直接将需要营销的案件导入系统;2通过与实时数据平台的集成,您可以按照特定条件筛选目标人群,并在指定时间将他们推送到系统;3捕获用户特定行为可作为触发条件,将相关案件导入系统进行营销
案件在营销之前,完善案件的所需的信息,以及条件的验证,最后变更案件的状态,并触发决策流程
根据案件的营销场景,对案件所需的变量进行聚合,并组装为决策报文,路由到对应的规则进行决策
通过规则决策报文,解析出案件所需要进行营销的指令,并初始化案件所需的指令记录
根据指令的明细,进行相关指令的调用,例如短信、站内信、智能语音等
以上功能基本满足大多数营销场景的需求,但我们的系统还提供了更多特殊业务场景的支持。例如,您可以设置延迟指令以适应某些特定时间点的触达需求,或者使用再次决策功能来对用户进行更为精细化的分类和个性化营销。这些特殊功能使我们的解决方案更具灵活性和适应性,能够满足您更为复杂的业务需求
随着营销活动的不断拓展,名单数量也日益增长,我们面临着以下三个挑战:
我们根据案件场景对时效性的需求,同时考虑到不同场景下的名单数量,将队列进行精细化管理,拆分为高优先级快速处理队列、普通处理队列、慢处理队列、大批量案件专用队列以及特定业务队列等,以满足多样化的业务需求
相信大家对线程池并不陌生,例如我们经常会用到的FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledThreadPool,以及特殊如WorkStealingPool、ForkJoinPool等;根据使用场景选用了Guava库的ListeningExecutorService,可以更方便地处理异步任务的结果和异常,从而避免阻塞线程并提高任务的响应性, 同时对于不同的业务场景,对线程池进行了拆分,以保证资源的合理利用
系统流程中涉及到引擎对象的使用,为了减低对象创建和销毁带来的开销,我们使用了GenericObjectPool,这是一个通用的对象池,它提供了一些参数来配置池的大小、空闲对象的最大数量、空闲对象的最小数量、最大空闲时间、最大等待时间等。当需要使用该对象时,可以调用GenericObjectPool的borrowObject()方法来获取一个可用的对象。使用完对象后,可以调用returnObject()方法将对象归还到池中。基于对不同活动的优先级定义,将引擎对象池化,并了拆分为多个对象池。
以上通过不同活动设置相应的优先级,对于案件进行隔离,再通过任务分发,对案件进行不同比例的资源分配,以保证能够快速完成时效性要求高的案件
通过预编译 JavaScript 脚本,Nashorn 在执行过程中可以跳过解析和编译阶段,直接使用预编译的字节码,从而加快了 JavaScript 的执行速度
全局变量的访问比局部变量更耗时。每次访问全局变量都需要在作用域链上进行查找,这会导致性能下降。而且,全局变量的频繁读写可能会导致内存占用过高,进而影响整体执行速度。
--class-cache-size:合理设置缓存编译后类的最大数量,从而避免重复的解析和编译过程,提高执行性能
--global-per-engine:使得全局对象的访问更加高效。没有这个选项的情况下,每个脚本上下文都会有自己的全局对象实例,这会占用更多的内存和时间。当使用此选项时,所有的脚本上下文共享一个全局对象实例,这会大大提高效率,测试下来使用此项可以提升10倍以上。同样使用此选项,需要避免并发问题,这也为什么尽量避免使用全局变量和脚本原因之一。
参考:https://github.com/JetBrains/jdk8u_nashorn/blob/master/src/jdk/nashorn/internal/runtime/resources/Options.properties
ScriptEngineManager:标准接口调用,需要管理ScriptEngine实例,使用ScriptEngine.eval()执行脚本 GroovyShell:执行Groovy脚本片段,使用GroovyShell会造成Class太多,性能较差 Groovy官方提供GroovyClassLoader类,加载解析Groovy Class,实例化对象,比较适合复杂的场景
考虑的系统的业务场景,我们采用了第三种集成方式来支持脚本的执行
脚本编译:
脚本编译时,指定脚本的文件名,默认由 "script" + System.currentTimeMillis()+Math.abs(text.hashCode()组成,避免因为代码重复进行编译、加载导致Metaspace的膨胀,可以自定义文件名规则,也考虑Groovy脚本的md5值作为文件名
分类加载
首先,普通java类不涉及框架或其他中间件的类,直接加载脚本、编译、实例化即可。spring管理类,在加载脚本,编译获取到class元信息后,通过创建beanDefinition,再将实例注册到spirng容器中,完成类的实例化。
缓存对象实例
如上图,通过mq和schedule触发脚本重新加载和实例更新,并将将编译实例化后的对象放入缓存 ,在脚本没有变更的情况,避免重复编译加载,提升执行效率, 同时减少了内存的开销
使用静态编译
将Groovy代码转换为Java字节码,从而在运行时获得更好的性能,避免不必要的动态特性,以减少动态调度的开销
预设钩子
public interface GroovyDateSource {
Object getData(GroovyContext groovyContext);
}
通过预定义钩子方法,利用多态的特性来扩展父类功能,我们可以在不修改流程代码的情况下,通过脚本实现新的功能,从而更加灵活地扩展程序功能。这样一来,不仅可以避免因修改流程代码而带来的风险,而且还可以大大简化开发过程
通过接入实时数据服务和用户标签平台数据服务,标准标签可以通过标准服务获取,从而大大减少系统在决策过程中获取变量时的复杂性和性能开销,提高系统的运行效率。对于非标准标签,可以通过Groovy来实现。这种方式提供了更大的灵活性和可扩展性,以满足不同业务的需求
通过本文对系统架构和流程的详细介绍,您已经全面了解了营销平台的整体框架。此外,文中还探讨了在营销过程中可能遇到的问题以及相应的解决方案,希望这些信息能对大家有所帮助。
scott,现任运营平台后端研发专家。
Java、大数据、前端、测试等各种技术岗位热招中,欢迎扫码了解~