最近遇到的几个项目分别用到了本地环境和分布式缓存。对于各种类型,我们希望做成设计标杆,以后不管是业务团队同学自己开发还是我们架构团队帮助优化,都有一套标准的设计模版。
本文是使用Redis分布式缓存优化的项目。
要不要打破服务化的限制
当时拿到需求的时候有个纠结点:原来数据查询服务通过RPC调用数据存储服务,因为涉及RPC调用以及查数据库,耗时长。所以希望我们加一层缓存,绝大多数情况下直接从Redis取数据。如下图所示:
通常的设计要做服务化,一个服务对外提供增删改查,而缓存这种优化应该放到服务内部。也就是说数据查询服务查询仍然需要通过API来调用数据存储服务,存储服务做不做缓存,数据查询服务应该是不感知的。如下图所示。
图片
而需求方的原始需求会破环服务的封装性。这个矛盾怎样来解决呢?可以这样来考虑。作为一个服务,内部的数据处理,包括存储、逻辑处理这些是要封装在内部的。但是可以使用策略模式提供灵活的访问API。RPC调用是一种访问方式,redis调用是另外一种访问方式。这样就不算破坏封装行。如下图所示:
图片
数据一致性校验算不算多余?
这个和需求方讨论没有达成一致。这也是为什么我连续三天都发文了。我不想破坏文章内容在实际实施时原本的先后顺序,但这一篇要赶在技术评审之前发出来,作为评审前跟需求方讨论的一个资料。
这个设计Redis和MySQL里数据各存储了一份,既然有异构的存储,架构团队这边认为数据一致性校验是要做的。而需求方认为既然都是消费MQ消息后处理,如果处理的没有问题就不会发生数据不一致的问题。所以只要有个手动运维补偿机制来处理生产故障即可,没有必要定时巡检来做数据一致性校验。
我一直遵从的理念是对于负责的服务或者功能,要做到:可观测、可衡量、可应对。自己开发的功能模块是正确的,怎样衡量呢?
数据一致性检查就是用来衡量正确性的。如果逻辑没有漏洞,数据一致性检查应该每次巡检对比数据都是一致的。一旦出现不一致,就是逻辑上出问题了,都是需要case by case分析并做逻辑的修改或者补充的。
如果逻辑本来就简单,跑了一年都没有检查出任何的数据不一致,这个检查是不是浪费呢?服务和功能都是要演进的,要做变更。变更要做到可灰度、可监控、可应急。数据一致性检查就是监控变更后逻辑正确性的手段。
总结来说:这个数据一致性校验属于业务巡检的一项,是用来发现问题的。发现问题可以通过在设计、开发阶段做严格的设计审查、代码Review来避免一部分。通过逻辑来保证是否属于过度设计?需求方对这个逻辑到底有哪些顾虑呢?
巡检逻辑会不会增加业务的复杂性、对数据库造成额外的压力?
这个巡检逻辑我们打算通过分布式调度任务来做。通过分布式调度平台,可以手动触发执行任务作为上线时初始化数据的手段,同时也是故障处理的应急预案,本来就是要做的,做成巡检只是每天定时执行一次,不会增加业务的复杂性。
对数据库的压力方面,这个巡检的确需要扫描数据库。但是我们会通过控制分页,采用>id,利用索引等手段来优化深度分页,并且会通过观察生产监控挑选低峰期执行,因为这是读数据,不会加互斥锁,表的数据量也不大,预计对数据库的压力可以忽略不计。
总结
我自己在沟通过程中犯了一个很严重的错误。在论证数据一致性巡检有必要做的时候,我说:「业界都是这么做的。」我之前确实是调研过各个做的比较好的大厂,他们对于业务巡检都非常重视。但是我的表达犯了在《批判性思维》这本书中介绍的「笃信权威」的错误。
更正确的处理方式是要从:优势、劣势、必要性、成本等角度来考虑。更要主动询问需求方的顾虑。