本文作者:友盟+技术专家 刘章军
前言:App推送在日常经营场景中常常用到,如:资讯类的新闻及时下发、生存服务类优惠券精准推送、 电商类的货品状态或是促销优惠等,通常开发者会依据经营的需要通过自建音讯推送通道或应用第三方音讯推送平台实现,但自建音讯推送的开发成本和人力老本十分高, 很多App开发者抉择第三方音讯推送。明天就以友盟+音讯推送U-Push,具体解读在海量业务背景下如何保障服务的稳定性以及功能丰富的触达服务。
1. 业务背景
========
友盟+音讯推送U-Push日均音讯下发量百亿级,其中筛选工作日均数十万,筛选设施每分钟峰值可达7亿+,本文将分享友盟+技术架构团队在长期生产实践中积淀的筛选架构解决方案。
如何保障百亿级的下发量?
友盟+U-Push筛选是Push产品的外围性能,其中实时筛选是面向推送要求较高的付费Pro用户提供的外围能力之一,实现了用户实时打标、筛选、散发、触达的性能。友盟+U-Push的设施辨认以device_token为基准,为保障尽可能的触达咱们留存了近期所有可能触达客户的device_token,以10亿实在设施为例,每个设施装置10个集成友盟+SDK的利用能够产生10个device_token,牵扯到硬件环境变动导致的device_token漂移问题,可能产生更多device_token。
( 图1.1.1 友盟+U-Push业务数据流简图)
图1.1.2 友盟+U-Push性能清单
2. U-Push筛选架构概览
================
2.1 上下行两个外围链路
U-Push服务由两个要害链路组成,上行链路保障客户音讯的触达,上行链路承载终端采数和与客户服务端的数据同步。其中上行链路次要分为任务调度、筛选核心,上行链路次要服务是多种收数通道(为兼容历史问题)和设施核心,上行通过设施核心实现跟上行桥接。
图2.1.1 友盟+U-Push筛选业务场景
在U-Push服务中,按照业务场景不同定义了多种工作类型,其中除单播、列播间接下发外组播、播送、自定义播、自定义文件播均须要通过筛选服务解决后才可执行下发,上行链路中(如图2.1.2)优先级最高是的工作受理和工作发送流程(红色链路),即无论产生什么状况都要保障客户音讯的正确下发,是U-Push服务稳定性的底线。出于融灾思考,筛选服务在架构上与主链路解耦。
图2.1.2 筛选和外围链路隔离
2.2 数据架构指标和设计
提到筛选,其本质是通过建设正当的标签索引零碎实现数据的疾速定位。筛选的指标是U-Push外围设施库,然而为防止筛选申请影响到外围库稳固须要将待筛选汇合分库冗余存储,与个别OLAP,OLTP场景不同,U-Push筛选的利用场景更加刻薄。
1. 不俗的在线工作并发能力
筛选实质还是在线场景,具备肯定的并发能力,并发压力次要在于压迫零碎IO上,通过正当的中间件应用、谨严的服务调度、针对性场景的差异化设计升高单次筛选的执行工夫,进步并发。
2. 实时海量数据分析和传输能力
筛选提供了多种剖析维度(图2.2.2),反对灵便的语法组合。筛选服务不仅要满足对海量数据的实时查问剖析,还要反对对单次可能破亿的后果集做低成本传输。
图2.2.2 筛选反对的字段类型
3. 老本可控
========
所有问题都是老本问题,从行业看全民上云后服务架构的老本问题更是备受关注,尤其在友盟+宏大的业务量下老本问题更加重要。
4. 为上游工作并行发送创造条件
=================
友盟+U-Push的发送层集群用于大量的发送节点,最现实的设计就是在工作筛选阶段即实现数据切片、散发、调度,上游间接并行发送以达到最高效率。
U-Push筛选在继续的技术迭代中,和多畛域业余团队深度单干,充分利用不同组件的个性,通过整合Tair、AnalyticDB for MySQL(ADS)、OSS、MaxCompute(ODPS)、Lindorm、HBase、SchedulerX等产出了一套兼顾稳固、性能、和老本的平衡解决方案。
筛选分为离线和实时两局部,离线通过ODPS生成设施主库快照,导入ADS。实时通过生产数据上行服务的设施信息更新事件,实时更新ADS或者RDB库。在执行筛选时候,对于较大后果集通过upload或者dump到OSS的形式输入多个小文件,传输给发送链路上游执行并行发送。
图2.2.4 筛选服务数据流向
上述业务链路和数据结构介绍了筛选目前的整体设计,然而要应酬简单的客情和多变的业务场景还须要做更多细节设计。
3. 设计细节
3.1 筛选库的场景设计
从下面的概览能够看出,筛选架构中的主要矛盾就是音讯上行链路中海量数据的读和上行链路中设施属性更新的高频写的矛盾,解决这个矛盾须要大量的资源来保证数据一致性和性能,在惯例的设计思路中在目前的老本资源下简直是不可行。大数据三大宝,冷热拆散分库分表,通过业务剖析调研,U-Push将业务分成若干场景,基于客户的不同生命周期的业务诉求和服务能力将客户指向不同场景,尽量优化客户体验。
图3.1.1 筛选库的场景设计
组播和播送筛选咱们次要围绕ADS来建设,ADS提供了实时和离线两种更新形式,在产品状态上只对Pro客户凋谢实时筛选能力,在架构设计上通过分库的形式隔离不同层客户的数据,提供差异化服务,进步稳定性。
离线局部:通过离线主库保障了所有客户的T+1筛选能力。在理论业务中离线主库只有读申请作为所有极其场景下的兜底,离线主库以device_token分区,能够实现齐全打散然而聚合查问的时候性能稍差。为了进步局部客户尤其是新客户的体验咱们设计了新客户离线库,批改为客户分区,进步了单客户聚合查问的效率。然而新客户离线库因客户间的规模差别容易引发分区歪斜,生产中这个表须要继续关注,及时清理和转移,否则在跑ads_loader的时候可能破线。
图3.1.2 离线主库的分区状态
图3.1.3 以客户为分区的分区歪斜状况
实时局部:保障实时筛选服务体验是整个零碎的重点,将实时筛选再细分为VIP实时库、测试设施库(不便客户接入阶段实时获取测试成果)、新客户实时库(新增客户个别设施量很小,U-Push会收费提供一段时间的实时筛选服务)。与离线分区相似,在分区设计上同样对大规模场景数据和较少规模场景的数据分表,特地的测试设施库可能产生大量脏数据,整体隔离进去。
图3.1.2 客户场景迁徙
新客户接入伊始基于客户规模辨别,在不同的生命周期节点会被引入特定的场景,在保障大盘能力的前提下尽量输入更优质的客户体验。
3.2 利用OSS传输和切分文件
在上述设计中通过离线和实时的辨别,升高了高频写可能对设施库造成的影响。然而始终绕不过海量数据的传输问题,为躲避这个问题U-Push采纳差异化的设计思路,以后果集规模做辨别,对大后果集间接通过ADS dump到OSS,基于不同客户的并行度做近程切分,在OSS实现upload和split操作后返回文件门路汇合,后续链路只保留文件门路集,直至进入发送层执行并行发送。对小后果集通过select拉取到内存整合消息报文传输,后续链路间接发送设施ID。通过OSS做两头存储,极大的升高冗余的IO损耗。
ADS3.0因为整体架构改变改为通过内部表的形式dump到OSS,与2.0能够dump出单个文件不同3.0在dump后会产生一系列小文件间接导致原有的计划不可行,在通过和ADS团队沟通后ADS顺便在3.0版本欠缺了dump单个文件的性能,致谢ADS的同学。
图3.2.1 筛选查问中的性能瓶颈危险
3.3 查问缓存和预筛选
谈到查问场景,必然会有缓存的一席之地,与个别设计思路不同,U-Push间接放弃了针对实时筛选能力的查问缓存,因为在这样的设施量级下随时的设施更新是必然。U-Push的实时筛选库是一个高频写低频读的场景,然而对单次读的要求比拟刻薄,首先对未开启实时性能的离线客户,因为设施库是快照模式,一天内的屡次读拿到的后果必然雷同这时候设置缓存就很有意义,比方新闻、气象、工具类客户的习惯,一天内发送屡次播送,就不用每次再去从新生成筛选集文件。
图3.3.1 查问缓存逻辑流程图
预筛选性能的开发是个小插曲,后面讲到U-Push放弃了对实时的查问缓存,导致客户的每次音讯发送都要从新去生成文件,在保证数据实时性的角度思考无可非议,然而遇到“较真”的客户就很有压力。比方新闻类客户极度关注音讯下发的时效性,通过开发者控制台能够查看每个工作的筛选工夫,有时候同类音讯2s的差别也会引发客户在DING群的”客诉”。客户的诉求能够了解然而这也消耗了团队大量的精力。通过和个别客户沟通U-Push开发了预筛选性能,在客户习惯性发送音讯的前一段时间事后调度执行筛选逻辑生成设施ID汇合,通过损失大量的数据时效性来压缩音讯下发工夫,争取音讯发送速度。
图3.3.1 友盟+U-Push音讯轨迹
3.4 Alias筛选的优化
筛选申请能够归类为两种场景:
- Alias性能依赖的ID Mapping场景,NvN的设施ID和Alias映射。
- tag组播和iOS播送性能的select场景,条件查问,基于ADS实现。
Alias性能简介:Alias容许开发者为设施绑定别名,别名由alias_type,alias两个属性组成,譬如开发者能够标识设施A,为他减少alias_type=telephone_number, alias=13900000000以此来给设施A减少手机号的属性。在发送音讯时候能够绕开device_token,间接通过服务端指定alias实现触达,alias是一个典型的NVN ID Mapping场景,一个设施在同一个alias_type上面同时只能领有一个alias。这也是合乎个别业务场景的,比方上例个别一个设施只有一个手机号,设置新手机号后会笼罩原alias。如果须要满足双卡双待的性能,须要设置两个alias_type,即alias_type=telephone_number_main,alias_type=telephone_number_secondary。alias的个别应用场景是开发者通过自定义文件播上传一批文件,文件内容为某个alias_type下若干设施alias的汇合(百万千万级)。筛选服务扫描文件后顺次找出alias值mapping的device_token。
3.4.1 Alias的晚期设计
说到Mapping,轮询,高吞吐查问,首当其冲选Redis,晚期的U-Push也是如此。
图3.5.1 alias晚期数据结构设计
alias利用Redis的Set和Hash构造实现正查和反差的性能,为什么反差用hash,后面讲到1个设施在1个alias_type下只保留最新的alias。这也是出于爱护用户的目标,如果1个设施同时存在多个alias下,在开发者执行圈选的时候可能会屡次选出这个设施造成屡次有效触达。
这个设计平铺直叙,确实也能够满足绝大部分客户的筛选场景,然而随着业务量的减少有几个问题逐步裸露
- 轮询成为海量设施查问的瓶颈,且不可冲破。
- Redis数据长久化难的问题凸显,数据分析难上加难。
- Alias无奈很好的满足数据返还链路的需要。
3.4.2 钻研Alias的解法
分库确实是很好的思路然而依然无奈满足性能问题和长久化问题,而且随着行业对大数据的关注,数据返还也成为更多开发者的诉求。买通数据返还链路做好客户数据的存、取、管、用曾经是一个重要的行业方向。为了解决这个问题U-Push通过离线和实时相结合制订措施
- 分库,减少KA级别客户独享库,压缩横向扩容空间。
- 分层,基于Lindorm做长久化分层存储。
- 离线留存,通过日志零碎留存上行筛选后果,一方面欠缺统计需要,一方面通过回执返还客户。
3.4.3 基于Lindorm宽表的分层设计
用宽表代替Redis的Set设计做正查,用一般表基于设施ID的联结主键做反查,在查问时候通过将单次轮询改为屡次mget尽量压缩IO损耗寻找响应性能和服务稳固的两头值,Lindorm的磁盘存储能够满足业务需要的同时通过exporter的配置实现lindorm数据T+1同步至ODPS。
图3.5.2 基于Lindorm款表的分层设计
3.4.4 数据迁徙的尝试和思考
数据迁徙是在很多业务架构中都是痛中之痛,如何保障稳固、平滑、平安的迁徙须要付出大量的老本。U-Push在Alias的数据迁徙中做了多种计划的钻研和思考。
- Tair整体dump迁徙,dump计划实践上可行然而有较大的业务危险,出于稳定性的思考放弃。
- 写申请增量更新,通过客户的写申请逐key迁徙,会有漫长的灰度工夫,且无奈执行彻底清理,胜在稳定性强。
- 扫描设施主库,分客户批次灰度迁徙。在U-Push的性能中,提供了appkey下alias_type的性能,客户能够在开发者控制台查问appkey下的alias_type列表,为实现这个性能对appkey和alias_type做了汇合索引,这个索引成为数据迁徙的要害。通过扫描设施库获取appkey和device_token,联合alias_type去反查库查找alias,再拿appkey+alias_type+alias去正查库查问device_token列表实现迁徙。
第三种办法能够实现存量数据的完满迁徙,对线上服务简直没影响,然而在百亿级设施下,以1wTPS计算依然须要10天的工夫,好在该计划能够实现单个客户的灰度与回滚。
5. 结语
======
U-Push筛选服务只是U-Push泛滥服务中的一环,在友盟+微小的业务量下,为满足不拘一格的各行业需要输入了大量粗劣的设计,本文列出的只是冰山一角,日均音讯下发量百亿级做到熟能生巧离不开其余技术架构团队在筛选服务迭代中的独特合作。
目前U-Push曾经以Push通道为根底,整合了微信、短信、隐衷短信降级为多通道触达服务,为泛滥出名的App如:今日头条、磅礴新闻、作业帮、易车等提供了触达能力,后续继续接入支付宝小程序、头条号等更多经营场景通道,继续为客户提供稳固、高性能、低成本的触达能力保障。
友盟+,国内当先的第三方全域数据智能服务商,截至2020年6月已累计为200万挪动利用和890万家网站提供十年的业余数据服务。