微服务后业务系统围绕CAP的业务方案设计思考
成规模后的业务系统,一般都会走到微服务拆分的阶段。虽然这种方式有各种弊端,但也有显而易见的好处。
先说好处:
- 业务按从属范围可以做到内聚较高,仅在边界处通过接口耦合
- 资源的管控更细腻,提升资源利用率
- 团队职责更明晰,成员技能更深入专注,进而更好的反馈业务价值
- 多业务线协作更顺畅,敏捷模式有一个良好的畅通基础
- 面对团队人员流动,能最大程度上规避业务迭代可能遇到的技术风险
那凡事有好有坏,接下来说说坏处:
- 业务范畴伸缩是一道鬼门关,服务上容易,下很难
- 业务领域模型会散列成多个原子服务,需要多个子系统共同承载一个业务域能力,故而团队所需的人员配比也会提升
- 基础设施维护,基础架构开发的要求变高,虽然可以依靠云服务解决一定的问题,但还不足以解决所有问题
- 团队协作太细碎,一个项目涉及人员过多,功能散列到各个子系统中,串流程成为一个复杂且持续的事情
- 不同业务场景,对于CP,AP模型的设计定义会产生不同的结果,取舍成为一个考验经验&能力的技术活
一般而言,我们会要求服务粗粒度化,尽量避免过于碎片化后的服务导致的复杂度攀升问题。
在这里,仅说说针对CP,AP的业务模型设计方案思考。
对于CP场景的定义一般如下:
多个系统必须准确的保证一致性,否则当前请求不可用(比如:抛异常,返回错误之类)。
CP业务场景有:
- 下单扣库存场景
- 商品后台信息更新场景
下单扣库存场景
用户提交订单后,请求会在订单系统中进行一系列校验后,进行后续处理,比如扣库存。
为了保证不超卖,不少买,业务系统一般如下流程。
- 用户提交订单后,先在订单系统本地生成中间态订单
- 同步RPC调用扣库存接口,扣减库存。扣减成功,更新本地订单状态为成功;扣减失败,更新订单状态为失败
- RPC异常,则更新本地失败,同时异步通知商品子系统回补库存
在这个过程中,对于客户而言就是要求扣减库存成功了再生成正确的订单,两者缺一不可。但是,业务方更关注正向流程的强一致性,逆向可以接受微小延迟。
针对这种场景的要求,会采用CP+AP模式,通过正向强一致性,逆向弱一致性来保证一致性&可用性的均衡。
商品后台信息更新场景
运营在商品后台更新商品信息后,一般会刷新若干个子系统的数据。比如:商品子系统,商品缓存,dns缓存等。
对于数据的同步刷新,运营会要求大部分数据能及时更新,如果不能,可以分拆成多个阶段分步骤成功也行。不能接受响应一个成功,过段时间可能成功,可能失败这种情况。
从需求角度来看,这是一个CP的场景。但是对这个流程分解下来后,会拆分成如下几个部分:
- 基础信息更新
- sku信息更新
- 多媒体信息更新
- 附加业务字段更新
这些内容中,涉及dns缓存的,仅有多媒体信息部分。一般的做法,是生成新的url,历史的不再使用即可。并不需要刷新历史url对应的内容。
其它内容要解决的问题就是商品子系统&商品缓存之间数据同步保持一致的问题。
要做到运营期望的CP系统,要解决如下问题,即:如何保证更新DB后的数据能正确,及时刷新到缓存中?
一般的数据更新流程如下:
- 用户提交更新请求
- 更新数据库记录,更新成功,刷新、失效商品缓存
主要的问题在于更新DB成功后,针对缓存的操作如何保证一致性。
这类异构系统,要保证2个系统的保持一致性,有几种方式。
- 第一种:将缓存的操作并入本地事务中,出现网络问题,依赖事务失败来驱动用户侧重新提交来保证一致性。过程中存在短暂的数据不一致,在使用时,强校验环节依赖DB数据,弱校验环节依赖缓存。
- 第二种:有其它同步机制,比如缓存的刷新依赖消息队列进行,本地事务中不考虑缓存刷新的问题仅同步发布一个普通消息即可,依赖mq的异步消费来完成缓存的同步刷新。
- 第三种:依赖定期刷新机制,比如定时任务周期性刷新缓存的方式。那这种情况下,可以忽略缓存更新异常,仅关注本地事务即可。
无论哪种方式,会要求在提交时,涉及多系统交互部分全部成功才算成功(依赖定时器的不算)。那这种设计出发点就是CP,但是每一个交互可能并不直接完成同步,或者存在异常情况下短暂的不一致,需要其它环节或者步骤来补充一致性。这里考虑的就是AP,因为短暂的不一致不会导致业务出现严重错误,出于功能可用性角度,可以接受这种有损解决方案。
但是,如果真有客户较真,比如涉及价格部分的调整,正好被顾客碰上了的情况,还需要在执行环节做数据的校验,最终以DB中存储为标准,同时给到用户相应友好提示,降低客诉的概率。
AP业务场景有:
- 依赖配置中心的配置推送场景
比如网关协议配置管理场景下,配置的下发是否实时且一致推送到所有实例并不是最关键的,因为即便存在网络问题,最终也会推送到位。关键是在这个过程中网关服务必须正常可用,即便部分实例得到更新拒绝前端访问,部分实例未得到更新前端可以正常访问出现也无妨。可以这么说,依赖这种变更推送机制的场景,都需要支持AP的设定,系统集群需要兼容多种配置共存的情况。
业务方案设计的时候,围绕不同的场景会经常AP,CP或者AP+CP等定义不停的变换方案。相比中间件而言,这种变换会非常频繁。比如kafka,可以在不同的配置下是一个AP系统或者一个CP系统。不同实现机制抽象到理论层面一直在CAP范畴中打转,区别大部分仅仅在于一个AP设计方案下,接近CP的过程区别。