分布式系统架构的内功心法

架构是一种权衡

没有一种架构可以应用到所有环境,也没有一个技术或框架可以解决所有问题,即使是针对同一种场景也往往存在多种解决方案。在架构的时候,更多的是方案和手段的权衡,例如高可用性、高并发性、一致性本身就存在一定的矛盾;而异步还是同步、是否需要事务、如何应用事务、缓存、拆分、容灾、发布等等,每一项都需要从各种技术实现中进行权衡。细化到框架,ActiveMQ、RocketMQ、Kafka、Redis、ZooKeeper等等都可以实现消息队列模型,具体使用哪个就需要结合场景进行权衡了。

分与合

天下大事,合久必分、分久必合,在解决高并发分布式的问题时绝大部分都在使用分与合的思想。

当数据量很大、并发量很多的时候就需要考虑拆分(分而治之),例如分层设计、横向拆分、纵向拆分、分IDC、分库分表...等等。并且这些拆分本身就是分层的,例如在DNS层可以将流量按照地域或运营商分配到不同的IDC、业务层可以将业务处理逻辑分配到多个子系统、系统层可以根据用户进行横向拆分、而存储层可以根据规则将数据分配到不同的库不同的表;另外读写分离、热点分离、独立出缓存层也体现了分布式系统架构中分的思想。

为什么要做这么多的拆分,拆分就是为了化多为少,在单节点处理能力有限的情况下,通过横向拆分提供无线的扩展能力,当巨大的流量通过拆分后,每个节点要处理的QPS就会下降;拆分是为了化繁为简,简化单节点的复杂度,现在的微服务(当然微服务引发的服务治理需要另说)、二阶段事务提交,就是将复杂的业务通过多维度的拆分降解单节点复杂度的手段。

拆多了就要合,hadoop将复杂的任务分解到一个个的mapreduce job处理和聚合后,处理效率得到了极大的提升,而这种分解必然伴随着聚合。而在有些业务场景,两类节点相互调用非常频繁,通过合并将原本的RPC调用转换为本地JVM调用,则可以很大的提升系统性能。

隔离

隔离也是一种思想,其中也包含了分的意思,例如灰度、压测隔离、动静隔离、多版本发布等。

转换

路由与转换,可以看做是分思想的衍生物。分的太多,就需要能将请求转发到正确的位置,此外也需要将各种通信格式与协议进行转换。

重复与唯一(幂等)

幂等伴随着请求的靠套投递而产生,在发送请求时可能会存在如下几个场景:接收端不一定要接收、接收端只能接收一次、接收端可重复接收。对于配置推送平台,大多场景要求接收端可重复接收配置信息,但只保存最后一次消息即可;而对于一笔付款请求,如果重复发送,接收端要控制只能处理一次(即要进行幂等控制)。

最终一致

在分布式系统架构中,面对事务性业务有两种选择,一种是分布式事务、一种是最终一致性处理。分布式事务控制比较复杂,一般采用二阶段提交的方式,其思想是要么成功要么失败,注意要么失败是指其中有一步出错就全部回滚,看似是保证了数据一致性但实际业务却失败了。而最终一致性相对于分布式事务的核心思想是让业务尽可能成功,即当业务处理过程中可能会存在中间步骤失败的情况,但通过补偿逻辑可以保障失败的步骤后续继续执行,此时就应该尽可能的标记业务成功。

并行与串行

将大量的计算分散到多个节点、多个进程、多个线程进行并行处理,是应对大数据计算的常用技巧。而伴随并行的就是串行(或者说是并发锁)的处理,在分布式环境,并发锁的可以通过数据库、zookeeper等进行实现。

主动与被动

主动与被动主要是针对客户端如何获取服务端内容的场景,典型的就是消息队列中的推模式(push)和拉模式(pull)。具体底层实现上,无外乎轮询、长链接等等,其中使用轮询不一定就是拉模型,很多推模型其底层也是通过轮询实现的。

同步与异步

同步与异步也是经常要面临抉择的事情,异步可以减少系统的阻塞,例如Ajax、消息队列(还可以达到消峰填谷的作用)等等。此外流式计算与离线计算,也可以看做是同步与异步的衍生技术。再深一层次,会衍生批量计算、全量、增量等思想。

点到为止

限流:当巨大的流量打过来时,通过牺牲部分请求处理可保证整个系统可用;

降级:当面对流量高峰时(例如大促)往往将次要的服务停掉,以便节省资源给主要服务;另外当某个服务不可用时,直接返回默认结果也是降级的一种表现;

熔断:对于金融系统,当出现bug时可能会造成资损,此时需要旁路系统进行不断的核对,当发现异常时能够及时终止处理。

对于以上几个方面,系统要能做到自动限流、自动降级和自动熔断。

最后

以上一切问题都是由于量(数据量、请求量等等)产生的,当量很小时不需要架构,通过增加内存、CPU、机器等都能解决;当量增加到一定的程度时,才需要考虑架构,而架构的道与术却又是“道可道,非常道,名可名,非常名”。

你可能感兴趣的:(分布式系统架构的内功心法)