前言
业务千变万化,技术层出不穷,设计理念也是百花齐放,看起来似乎很难有一套通用的规范来适 用所有的架构设计场景。但是总是有一些原则是可以通用的。
#在设计系统时,应该多思考墨菲定律
-
任何事情都没有表面看起来那么简单
-
所有的事情都会比你预计的时间长
-
可能会出错的事一定会出错
-
如果你担心某种情况发生,那么它就更有可能发生
在系统划分时,也要思考康威定律
-
系统架构是公司组织架构的反映
-
应该按照业务闭环进行系统拆分/组织架构划分,实现闭环/高内聚/低耦合,减少沟通成本
-
如果沟通出现问题,那么就应该考虑进行系统和组织架构的调整
-
在合适时机进行系统拆分,不要一开始就把系统/服务拆得非常细,虽然闭环,但是每个人维护的系统多,维护成本高该处使用的url网络请求的数据。
高并发原则
-
无状态
如果设计的应该是无状态的,那么应用比较容易进行水平扩展。实际生产环境可能是这样的:应用无状态,配置文件有状态。比如,不同的机房需要读取不同的数据源,此时,就需要通过配置文件或配置中心指定。
-
拆分
在系统设计初期,是做一个大而全的系统还是按功能模块拆分系统,这个需要根据环境进行权衡。
- 服务化
总结为:进程内服务—>单价远程服务—>集群手动注册服务—>自动注册和发现服务—>服务的分组/隔离/路由—>服务治理 如限流/黑白明白,服务降级
- 消息队列
消息队列是用来解耦一些不需要同步调用的服务或者订阅一些自己系统的变化。使用消息队列可以实现服务解耦(一对多消费)、异步处理、流量削峰/缓冲等。但是订阅者太多,那么订阅单个消息队列就会成为瓶颈,此时需要考虑对消息队列进行多个镜像复制。
使用消息队列时,需要注册生产消息失败,以及消息重复接收时的场景。有些消息队列产品会提供生产重试功能,在达到指定重试次数还未生产成功时,会对外通知生产失败。这对于不能容忍生产失败的业务场景来说,一定要做好后续的数据处理工作,比如持久化数据同时要增加日志、报警等,或者在生产失败后发送http请求来保证成功。还有消息重复问题,特别是一些分布式消息队列,出于对性能和开销的考虑,在一些场景下会发送消息重复接收,需要在代码层面进行防重处理。
- 数据异构
订单分库分表一般按照订单ID进行分,如果要查询某个用户的订单列表,则需要聚合多个表的数据才能返回,这样会导致订单表的读性能很低。此时需要对订单表进行异构,异构一套用户订单表,按照用户ID进行分库分表。另外,还需要考虑对历史订单数据进行归档处理,以提升服务的性能和稳定性。而有些数据异构的意义不大,如库存架构,可以考虑异步加载,或者合并并发请求。
-
数据闭环
数据闭环如用户的聊天记录,因为数据来源太多,影响服务稳定性的因素就非常多了。因此,最好的办法是把使用到的数据进行异构存储,形成数据闭环,基本步骤如下:
· 数据异构:通过MQ机制接收数据的变更,然后原子化存储到合适的存储引擎,如redis,Elasticsearch等
· 数据聚合:这步是可选的,数据异构的目的是把数据从多个数据源拿过来,数据聚合的目的是把这些数据做个聚合,这样前端可以一次请求拿到所有数据,此步骤一般存储到KV存储中
· 前端展示:前端通过一次或少量几次请求拿到所需要的数据
这种方式的好处就是数据的闭环,任何依赖的系统出问题了,还是能正常工作,只是更新会有积压,单是不影响前端展示。
数据闭环和数据异构其实是一个概念,目的都是实现数据的自我控制,当其他系统出现问题时不影响自己的系统,或者自己出问题时不影响其他系统。一般通过MQ来实现数据分发。
-
缓存银弹
缓存对读服务来说,是扛流量的银弹,可总结为下表:
高可用原则
- 降级
对于一个高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,主要依据如下思路:
1. 开关集中化管理:通过推送机制把开关推送到各个应用。
2. 可降级的多级读服务:比如服务调用降级为只读本地缓存、只读NoSql缓存 、只读默认降级数据
3. 开关前置化: 如架构是Nginx—>Apache,可以将开关前置到Nginx接入层,在Nginx层做开关,请求流量汇源后端应用或者只是一小部分流量回源
4. 业务降级:当高并发流量来袭,保证核心业务是正常的,并保障数据最终一致性即可。这样就把一些同步调用改成异步调用,优先处理高优先级数据或特殊特征的数据,合理分配进入系统的流量,以保障系统可用。
- 限流
限流的目的是防止恶意请求流量,恶意攻击,或者防止流量超出系统峰值。思路如下:
1.恶意请求只访问到cache
2.对于穿透到后端应用的流量可用考虑使用Nginx的limit模块处理
3.对于恶意IP可以使用nginx deny进行屏蔽
原则是限制流量穿透到后端薄弱的应用层
#业务设计原则
- 防重设计
例如,结算需要考虑重复提交,还有扣减库存时需要防止重复扣减库存。解决方案可以考虑防重key、防重表。
- 幂等设计
在交易系统,经常会用到消息,而现有消息中间件基本不保证不发生重复消息的消息。因此,需要业务系统在重复消息消费时进行幂等处理。还有在使用第三方支付时,第三方支付会进行异步回调,也要考虑回调的幂等处理。
- 流程可定义
- 状态与状态机
- 后台系统操作可反馈
- 后台系统审批化
- 文档和注释
- 备份
总结
一个系统的设计,不仅需要考虑实现业务功能,还要保证系统高并发、高可用等。在系统容量规划(流量、容量等)、SLA制定(吞吐量、响应时间、可用性、降级方案等)、压测方案(线上、test等)、监控报警(机器负载、响应时间、可用率等)、应急预案(容灾、降级、限流、隔离、切流量、可回滚)等方面,也要有一些原则来进行设计。