找回密码
 会员注册
查看: 28|回复: 0

转转一体化推送平台的实践

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64080
发表于 2024-9-20 06:00:17 | 显示全部楼层 |阅读模式
1背景2设计思路2.1将"可变"的配置化2.2将"不变"的系统化3实现细节3.1速度控制3.2资源分配策略3.3问题解决4上线效果5总结1背景转转不同业务会根据各自业务特点,经常性地向不同用户推送各种消息。例如:每天向部分图书新用户发放红包,并推送站内卡片消息,以刺激新客增长;每周向部分奢侈品用户发送站内系统消息,以召回老用户;在世界图书日推送站内消息,同时发布图书微信公众号消息;在指定日期,向游戏线索商家推送push,并发送短信提醒等等。随着各业务的不断成熟,“消息推送”类型的需求逐渐累积,我们从中总结出了如下特点:不同业务的推送主体不同,例如:图书、游戏、奢品等。每次推送面向的用户群不同,例如:浏览过某些页面的用户、提交过某种订单的用户、新注册的用户等。用户数据来源不同,有些是通过执行HiveSQL生成的,有些是通过用户画像平台圈定的,有些是产品同学人工指定的Excel表格。推送渠道多种多样,包含红包、push&IM消息、短信、公众号消息等。此外,还包含组合发送的情况,例如:先发红包再发push,站内消息和短信同时推送等。每个推送对应各自的推送内容,包含:文案、落地页、图片等。同时,可能会伴随文案的动态替换。例如:点击消息,跳转至订单页,需要根据不同用户替换不同落地页链接。不同推送有各自的推送频次,有些是定时周期性推送,有些是临时一次性推送。此外,周期维度各不相同,有些是每天发送,有些是指定一周中的某几天推送。推送需求的业务目的不同,有些是为了拉新,有些是为了召回,还有些是为了提醒用户。痛点在于,每次面对新的推送,我们都需要针对上述特点,编码一个新的推送任务,而每个任务的实现过程,都伴随着重复搬砖:都需要增加一套推送配置,进而生成一套消息上下文;为了保证可靠性,都需要做防重频率校验;为了提升效率,都需要通过异步方式提升速度;为了保证高数据量级下的系统能力,还需要同时进行速度控制。都需要统计对成功率、触达率、打开率做统计。上述的重复能力的实现会造成冗余代码和人力成本。此外,每个推送配置分散在各个角落,也不方便代码维护。因此,需要一个较为通用的推送平台,将这一类需求进行统一管理。2设计思路整体设计思路为:将“可变的”配置化,将“不变的”系统化。2.1将"可变"的配置化维护一张推送配置表,为每一个推送需求创建一条配置记录。上述背景中提到的“特点”即为“可变的”,将其抽象为配置表中的一个字段。例如:“业务方”字段:将推送主体抽象成一个枚举类,每个业务方对应枚举类中的一个值。“推送类型”字段:将不同推送渠道抽象成不同推送类型,该字段存储的是渠道列表,允许同一推送需求选择多个推送渠道。各推送内容字段:、文案、落地页、图片、红包计划id等。此外,针对上述类似“订单页”的推送,需要在配置项中加入占位符,例如:不同用户根据订单id区分落地页,则需要在链接的相应位置中加入${订单id}占位符。用户来源相关字段:若为HiveSQL生成的,则需要填写“文件id”和“APIkey”,以触发sql任务执行;若来自用户画像平台,则需要填写“人群id”,以从拉取圈定数据;若为人工指定,则需要上传excel文件,由系统解析。2.2将"不变"的系统化将上述“重复编程”的工作内容,抽取成一套代码,沉淀为通用的系统能力。例如:维护一张推送用户表,记录用户id、对应的配置id、推送结果、失败原因等。将配置表中的配置项和用户表中的用户信息,根据不同推送渠道,映射成推送上下文实体。执行推送前,进行用户维度的防重和频率校验,若系统判断重复推送,则直接将失败结果写回。执行推送时,开启线程池异步,并限制远程服务接口调用QPS。推送后,记录推送结果,并分批将结果回写至用户表。整体设计按照上述思路,将开发后的推送工具可视化之后,当新增一个推送需求时,产品同学只需在后台添加一个配置,将推送需求填充至各配置项即可。若用户来源为HiveSQL生成,研发同学只需编写SQL语句圈定用户群,添加至用户表。接下来的工作全部交给系统,即可满足新的推送需求。一方面,将研发同学从重复搬砖中解放出来,省时省力;另一方面,所有推送配置集中交给后台管理,方便维护。3实现细节3.1速度控制异步化:由一个主线程顺序执行推送,显然效率低下。为保证推送速度,我们使用线程池开启异步推送:主线程只负责从库表读取推送数据,分批将推送任务提交至线程池任务队列。异步推送过程分片:当面对百万甚至千万级数据量时,推送任务集中在单节点上,一方面容易造成单机过载,另一方面容易达到性能上限。为进一步提升系统效率,并实现负载均衡,我们使用分片广播调度:将推送任务分布至集群中各机器上,分片执行。分片策略:各机器分批从用户表中读取相同数据量的用户,表主键id%机器数,若命中当前机器号,则执行推送。分片调度断点重试:用lastId记录上一批次推送数据的结束位置,每台机器将各自的lastId缓存至redis,用来标识执行进度。若任务异常中断,将根据lastId进行断点重试,避免全表扫描。接口限速:消息推送依赖平台能力,因此在提升效率的同时,会在RPC接口调用处通过架构组件设置全局QPS限制。3.2资源分配策略无论线程池、机器数还是配置的QPS限速为多少,单时段的推送资源都有上限。因此,在面对同一时段多个配置执行推送时,必然要解决资源分配问题。主要考虑如下几种策略:按优先级顺序按优先级顺序这样分配的好处在于,策略比较简单,只需配置优先级即可解决资源分配问题。但同时会引入新的问题,例如:设置优先级时应该考虑哪些因素?当优先级相同时该如何处理等。此外,优先级低的配置可能始终没机会被执行。按数据量大小每个时段执行推送前,先计算当前时段各命中配置的数据量大小,按比例分配可执行的推送量。例如:共有3个配置,总数据量分别为:40、20、20,每个时段最大推送量为:30。时段1:命中配置为前2个,则按比例划分的数据量分别为:20、10。推送结束后,3个配置的余量分别为:20、10、20。时段2:待推配置为3个,将余量按比例划分后的数据量为:12、6、12。推送结束后剩余:8,4,8。时段3:将剩余数据推送完毕。按数据量大小按数据量分配的好处在于,可以根据推送进度,实时动态分配占比,保证每个配置都有机会推送数据,更加公平。但是策略相对复杂,每次推送前需要重新扫表计算数据量,一定程度上影响推送性能。均匀分配每个时段推送前,根据当前命中的配置数,均匀分配推送量。例如:共有3个配置,总数据量分别为:40、20、20,每个时段最大推送量为:30。时段1:待推配置为前2个,则均匀分配的数据量分别为:15、15。推送结束后,3个配置的余量分别为:25、5、20。时段2:待推配置为3个,将余量均分30后的推送量为:10、5、10。推送结束后,第2个配置的5条数据全部推送完毕,其他配置的余量分别为:20、10。时段3:剩余配置均分30后的推送量:15,10。剩余配置1的5条数据。时段4:将配置1的数据全部推送。均匀分配综上,对比优先级策略,均匀分配可以保证公平性,每个配置都有机会执行一定数据量的推送,此外,均匀分配有一个默认优先级:数据量越小越先推送完成,符合业务场景要求;相比按数据量策略推送,均匀分配不需要二次读表计算数据量,效率更高。因此,我们最终选择均匀分配策略。3.3问题解决现象系统上线后,面对千万级的推送量,持续FullGC。异常监控原因主线程不断读取库表,获取用户信息,分批提交至线程池执行推送。由于执行推送的耗时大于数据读取,导致线程池任务队列累积,进而造成内存积压。改进改用生产者-消费者模式维护一个固定长度的阻塞队列,队列不空时,由消费者从队列中取数并执行推送;队列不满时,由生产者扫表取数并放入队列。当生产者速度过快,即队满时,生产者线程阻塞,等待消费者推送数据完成后,队列不满时,再次唤醒。效果FullGC问题不复存在。老年代使用明显下降。4上线效果目前,已将上述功能可视化至业务后台,开放给多业务方。至此,每产生一个推送需求,产品同学只需在后台新建一条推送配置,并根据需要填写各配置项,即可完成推送。上线至今,已支持转转多业务方日常及活动推送,日均达百万级推送量,最高可达两千万推送量。5总结本文介绍了转转一体化推送平台的实现,现已成为多业务日常推送的通用工具。未来会在诸如推送目标转化率、推送结果定向通知等方面继续完善和丰富系统能力。关于作者陈曦,转转订单业务研发工程师。想了解更多转转公司的业务实践,欢迎点击关注下方公众号:
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 11:36 , Processed in 0.423916 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表