猫眼作为国内互联网在线票务的领头羊,自成立至今发展经历了品牌独立、合并等重大发展。伴随品牌的独立、合并,账号作为业务的底层基石必然需要考虑账号独立建设、以及多账号体系整合。猫眼C端账号系统发展至今产生了一套类似SaaS化的账号体系架构以支撑不同渠道、体系的业务产品需求。
SaaS化的体系结构决定了上层租户之间数据相互隔离,与之对应的账号体系的SaaS化反应在业务上形成了同一自然人在不同渠道使用账号相互隔离这一现象。账号隔离在早期满足了不同业务间差异化的需求,避免了历史包袱对新业务影响,快速支撑了产品矩阵打造。但伴随着业务成熟,不同产品间用户账号的数据隔离导致上层业务、资产、数据的割裂。对于用户产生了数据割裂、品牌认同的困扰,对于业务因为割裂无法快速支撑多渠道的业务联动,渠道间无法有效使用彼此的流量红利。当前猫眼的两大账号体系分别是猫眼APP账号体系与小程序账号体系。
以上问题在猫眼发展过程中逐步显现并放大,不仅不能够为新业务很好的导流,甚至成为新业务发展过程中的绊脚石。基于上述背景猫眼进行了多账号体系整合的专项行动,苦练内功,期望彻底解决这一遗留顽疾。
账号的整合打通不简单的是账号信息数据的搬迁,诸多问题需要考虑,其中包括:
柔性打通、整合差异化的账号,让用户无感知或弱感知、自然地接受原本割裂的体验一体化
兼容、支持用户换绑、注销等主观流程以及移动运营商二次放号等客观场景的影响
支撑不同业务场景对账号的需求,例如电影社区关注基础用户信息展示,裂变场景关注三方信息展示,电商场景关注自然人唯一标识
有效引导、处理打通整合过程中异常的账号,避免大规模问题爆发
保障全局亿级账号、业务数据一致性、完整性,保障服务的整体可靠性
降低业务改造成本,以低侵入的方式完成整合
当多个独立的产品发展到一定阶段后,产品所有权变更、产品互相导流等各种原因对产品进行整合时都跳不过账号的打通整合,我们在账号改造中首先调研了业界的实现方案。业界基于自身的历史原因、业务考量选择了不尽相同的账号打通方案,我们分别对几家大厂当前版本的产品账号打通能力进行了调研。按照我们的理解账号打通方案可以大体归为三类:
我们尝试分析各家的产品逻辑背后的异同:
相同点:都没有对账号体系本身做整合等较大规模的改造
差异:因为产品间的定位、业务复杂度等原因,通过强化绑定、弱化绑定、弱化历史数据、静默绑定等方式实现账号打通
回到猫眼的场景,猫眼经历自身发展有APP、小程序两个主要的账号体系,并有以下两个特点:
小程序与APP在业务、功能上没有较大差异。这点不同于微信&QQ、美团&点评、淘宝&支付宝
小程序与APP都有亿级存量用户,且活跃度较高。这点不同于京东
这两点与上述业界背景情况都存在差异,一味地借鉴大厂的经验并不能解决猫眼现有业务的痛点,因此我们明确了设计猫眼多账号体系整合方案的思路。
同时在调研过程中,我们也进一步明确了账号打通整合的三个核心目标:
强调自身品牌
整合业务资产
弱化用户影响
要打通账号,首先需要找准一个公共锚点(即自然人在不同渠道、平台的唯一公共标识),以公共锚点作为不同账号体系的中间桥梁。不同账号体系之间常见的唯一标识主要有手机号、第三方(如微信)开放平台标识这两类。这两类在对于猫眼都不能无缝使用,猫眼账号实际情况如下图所示:
APP侧:使用手机号注册,注册登录要求绑定手机号,以手机号作为不同渠道唯一标识
小程序侧:使用微信开放平台信息注册,注册登录不要求绑定手机号,以unionId作为不同渠道唯一标识
无法唯一标识一个自然人已然成为猫眼各业务的痛点之一,除了账号打通需求无法满足外,衍生出的发券、新老客活动等促销场景都可能带来额外的成本问题。
猫眼在分析了用户群体习惯、用户数规模、行业习惯等因素后,最终确定了以手机号作为公共锚点。
业界在多账号打通时,主要采取的是读打通的方式。即账号、用户、业务数据不做合并,而进行显示、静默的账号绑定后,根据业务可以有选择性地进行数据合并,流程类比大致如下:
上文已经说明猫眼与业务典型案例的差异,如果以读打通的方式实现,我们将面临三个主要问题:
基础服务保障SLA困难。所有用户操作都需要查询账号打通关系,导致账号等服务请求压力上涨,极端场景下可能翻倍。猫眼在演出秒杀等热门活动下SLA保障将面临巨大挑战
端到端的响应时间上涨。所有资产展示都需要先查询账号打通关系,再合并多账号下的资产,除读流量放大外,业务请求响应时间也会上涨,直接影响C端用户体验
业务迭代发展需要兼容读打通。所有业务在迭代过程都需要兼容读打通流程以保证用户体验一致,否则会额外给用户带来困扰,而且读打通长期也会给业务带来持续的运维成本
基于上述三个主要原因,我们没有选择读打通的方式,而是选择了如下图所示的写打通方式:将割裂的账号彻底统一,搬迁账号下用户、资产信息。写打通最大的优势即一劳永逸,业务写打通后不需要再考虑兼容打通问题,可以轻装上阵。但同时写打通在实现方案上将面临更大挑战,包括:性能、可用性、数据一致性等等,这些问题需要在技术方案上做更完善的设计与平衡。
公共锚点描述了账号打通的媒介问题,写打通明确了多账号打通方式,剩下一个打通后账号载体问题。
举个例子:用户有APP账号U1、小程序账号U2,这两个账号打通后承载账号、用户、资产信息的账号即目标账号。可选的目标账号有三种可选方案:
我们选择了以APP账号作为目标账号,除了上述账号、业务的改造项较少之外,还包括:
猫眼APP上线时间久,品牌认知更强,且存量用户量大于小程序存量用户
APP端注册登录的改造复杂,需要考虑存量版本的处理,并且客户端灰度方案实现更加困难
至此,多账号体系整合的整体方案确定:以手机号作为两侧账号体系的公共锚点,通过写整合的方式将小程序账号整合至APP账号。
整体开始前,先介绍下猫眼小程序账号体系背景信息:小程序存量账号已经有2亿,因为历史原因这部分账号数据分散在多个系统:
HIVE库:保存小程序账号的基础信息,以userId、注册信息为主
小程序账号服务:保存了小程序用户在微信体系的三方授权记录,例如小程序、公众号的openId、unionId等信息
小程序用户服务:保存了小程序用户手机号授权、绑定记录
微信服务:保存了关注公共号用户的信息,以及微信用户头像、昵称信息
基于以上的背景信息,第一阶段的目标是完成数据、系统的统一,将割裂的账号服务整合。在具体时间中我们拆分为三步执行:
收口增量账号创建,以及账号信息修改、读取。完成接口、服务层面的收敛
搬迁历史积累的存量数据,确保数据的完整性、一致性
注册登录改造,彻底与历史服务、数据介质解耦
这一阶段我们重点建设小程序注册登录流程入口改造,完成了统一账号注册登录对接门面,尽可能屏蔽后期改造对前端的影响。并且在收敛的同时完成了增量账号数据同步,在注册登录阶段完成用户数据在两个系统间同步,避免增量数据遗漏。具体方案中,我们抽象了账号服务统一网关,以屏蔽不同账号体系账号生命周期内操作的差异。改造后两个账号体系之间的关系如下图:
第一步注册登录改造完成后,增量数据得以同步统一账号体系,但存量数据无法有效迁移,需要做存量账号数据同步。
如上文背景所述,这一阶段主要的技术挑战包括:
分散的数据源增加了清洗的复杂度,并导致数据一致性难以保证;
大规模的数据、分散的数据源又进一步导致同步过程需要较长的时间周期;
较长的同步时间周期会放大数据不一致问题
针对大规模数据、多数据源、数据一致性错综复杂的问题,猫眼采取多种方式解决:
在性能方面,设计了支持水平扩展处理的能力,除了常规的多进程、多线程扩展外,针对性的进行了调优,例如对网络IO进行了TCP参数调优、对JVM参数适当调整;
一致性方面,采取多轮数据同步 + 数据巡检 + 数据补偿的方式确保数据的最终一致性;
异常处理方案,数据同步中异常任务可以failover,同步后异常数据可以兜底获取进行补偿,极端场景支持彻底降级、回滚
数据搬迁整体架构如下图所示:
第二步改造完成后,小程序账号服务已经不直接对外提供服务,接下来我们将彻底完成小程序账号体系的解耦。原小程序账号体系解耦下线需要格外考虑账号ID生成逻辑的变动,公司整体业务架构中因账号ID生成逻辑变动可能存在各种潜在风险,例如:不同账号体系ID号段冲突可能导致线上重大事故,跨产品体系功能推送中号段变化可能导致支付、数据统计分析等等账号上层业务异常。对于猫眼除了APP、小程序多账号体系问题外,还面临美团、点评业务场景的交互,以及猫眼、美团不同服务对账号ID识别等问题。
基于上述原因,我们在充分进行业务调研、梳理后,仍然决定采取较保守的两侧注册策略尽可能小的对业务产生影响。具体来说:不直接替换小程序账号体系账号生成逻辑,在小程序账号注册时会分别在原小程序账号服务、新的统一账号服务生成两个不同的账号ID,全业务只使用统一账号服务生成的账号ID。在统一账号服务内部维护两个账号ID的映射关系,在上线过程中如果因为账号ID变化产生未知的冲突、故障时,账号服务依然有能力完成账号ID清洗,最大程度的避免潜在故障的影响。
在两侧注册阶段稳定后,我们开始了账号服务整合的最后一个阶段——完全切换,即完全不再依赖小程序账号服务。至此,我们完成了两套账号在系统层面的整合,为接下来全局资产的整合解决了账号侧面的入口、数据收敛问题。
上述的三步改造中注册登录流程大致经历了以下过程:
数据双写:完成两侧数据的增量同步
两侧注册:基本解耦小程序账号服务,仅保留账号ID生成逻辑
完全切换:彻底下线小程序账号服务
回退双写:兼容两侧注册、完全切换阶段降级
整合过程中,遵循了先增量、再存量的原则。在接口层面统一收敛后,逐步减少对小程序账号体系的依赖,逐步解耦,并在账号服务内部进行数据搬迁、清洗,尽可能对业务无感知。具体落地实践中,鉴于注册登录是典型的写场景在发布、回滚等方面天然就复杂于一般的读操作流程,并且注册登录流程作为所有核心业务的起始节点,故障将导致核心业务直接受影响,业界也频繁多次出现过因账号服务不可用导致重大业务损失的事故,我们在注册登录流程的改造上采取了小步快跑的策略,将C端注册登录流程的改造拆分为多个阶段,重点保障了各阶段的改造上线可灰度、可观测、可降级、可回滚。
完成账号服务整合方案后,猫眼开始着手对全局资产进行整合。资产整合我们拆分为两个阶段:
整合衔接。在C端注册登录中嵌入资产整合,在注册登录基础上,额外扩展整合需要的身份验证、二次放号验证等操作完成前后端交互流程衔接
整合执行。收到整合请求后调度全局业务数据进行整合,是实际的全局数据合并阶段
全局整合中账号整合作为必要条件,可以嵌入位置大致可以分为:账号生命周期内核心操作、业务流程内操作。考虑到对业务的低侵入,猫眼在账号的注册登录阶段完成打通逻辑的嵌入,比较注册登录改造前后的差异:
在此基础上注册登录的改造依然考虑了接口版本回退,以及回退后的数据兼容,并能够根据整合实际执行情况控制注册登录实际使用版本完成负反馈调节。
用户资产数据全局整合过程类似于Java虚拟机Full GC过程。FGC需要STW避免GC同时产生新垃圾导GC不彻底,类似的,用户数据合并需要一个时间段用来阻塞用户、业务操作,避免融合中产生新的数据导致融合不彻底或数据不完整。如何设计全局业务停顿成为资产数据合并中面临的第一个问题。面向亿级用户、几十项资产进行大规模、大面积的数据整合对程序性能、鲁棒性也有不小的挑战,如何有效的完成融合调度,保证全局数据一致性、完整性,对异常任务、数据感知、观察、定位成为了数据整合中面临的第二个问题。
业务停顿问题
对于全局业务停顿问题,猫眼在内部梳理了各种业务场景,典型的C端业务场景包括选座、演出、订单、支付、UGC、裂变活动等等,在这些场景下业务数据的整合需要面临不同的处理流程,例如典型的同步调度流程、多服务之间的异步调度流程,在订单、UGC等场景下还需要考虑严重的写放大情况,整体评估后可靠的全局数据整合需要分钟乃至小时级的停顿才能完成。但这与猫眼用户日常的使用习惯严重不符,用户的使用典型场景包括购票、取票,设想在购票、取票阶段让用户暂停使用对用户造成的伤害是严重的。
因此猫眼没有采取同步阻塞的方式实现整合,而是采取了”异步非阻塞的“方式实现:在登录时与用户确认账号整合信息,记录该信息后,在次日凌晨业务低峰期开始任务调度,从账号层面进行锁定,开始全局业务数据整合,在全局业务数据整合完成后解锁该账号。
整合调度问题
对于整合调度问题,针对整合任务整体的治理我们建设了整合调度中心,其职能包括记录上报整合信息,调度全局整合任务,记录全局整合轨迹,支撑测试、运维、客服等不同使用场景。
整体架构如下图:
在稳定性方面,整合调度中心嵌入注册登录、核心业务流程需要保证高可用,并能够支撑日均百万次调用。在具体设计中,我们重点关注了四方面的能力:
可灰度:保证梯度灰度、规模可控。上线初期面向内部、可控范围的灰度,暴露隐藏故障的同时避免外部用户受到影响;后期避免上报数据过载导致系统、服务故障
可降级:在降级方案上因为数据已经持久化、用户主观操作的不确定性,降级具体实现上兼容了包括已灰度、已整合用户、已上报用户、解换绑、注销等多种场景
可观察:上线后支持各维度数据可视化,支持了总量以及各业务视角、各阶段整体的数据指标,保证整合记录可视化、可追踪
面向失败:整合处理过程中采取异步调度重试机制,保证不阻塞用户、不阻塞业务
在性能方面,采取异构的存储架构,扬长避短,以支撑百亿级数据规模,具体的:
借助MQ异步、削峰填谷的能力尽可能的提升处理速率的同时避免过载流量导致下游服务故障
借助DB事务、区间查询的特性存储整合映射关系,并使用多级缓存提高查询性能,满足核心流程的查询需求
借助ES、Hive支持检索、大规模数据归档
此外对PaaS层我们进行了主题隔离,并支持了限速、水平扩展,避免过载的洪峰流量导致PaaS不可用,保证整体服务的高可靠与高性能。
上述是猫眼账号体系在发展过程中多账号体系整合做出的一些实践,在调研业界解决方案基础上,我们结合猫眼自身的产品、业务背景设计了猫眼的多账号体系整合的流程,并依托此流程猫眼已完成了亿级账号的整合。