在应用层之下,其实是需要大量分布式中间件支撑的。
那设计开发一个分布式系统,需要关注哪些东西,有哪些挑战呢?
分布式系统,简单可以理解为一些独立的机器通过网络相互传递消息,进行通信。这些机器可能相距很远或者很近。
分布式系统中,需要设定一个非常重要的世界观,就是一切都会失败,磁盘会出现问题、网络会出现问题、数据中心会断电或者遇到地震。
所以,一个分布式系统,需要应对以上的异常情况,保障业务持续运行,这也是分布式系统非常重要的价值之一。
由于一个大型系统,是在地理上的分布,那不同地理位置上距离较远的数据中心的通信就会很慢。一些全球化的互联网应用,机器可能彼此在地球的两端。
不管是磁盘故障、网络抖动、数据中心被摧毁、地理位置过远导致的延迟,这些导致的可用性问题,都可以通过数据复制、冗余的方式解决。
一份数据在多个物理位置的备份,有助于解决可用性和性能,一种空间换时间与可用性的思路。
这些副本数据可以存储在一个数据中心之内,也可以存储在多个数据中心之间。
你拥有的副本越多,容错能力就越强,数据丢失的可能性就越小。
结合数据局部性原理,可以最大限度地减少延迟,就是让副本接近于可能访问它的人。
副本多的另一个好处是,可以尽可能为更多人提供访问,也就是提高了访问吞吐。
副本复制可以解决大部分分布式系统的问题,但也会导致一些新的问题。
好处是,引入多个副本是必不可少的。但你需要做好副本之间数据一致性的处理,特别是对于网络问题的处理,比如网络抖动、网络分区、副本延迟等问题。
对于副本一致性,你需要知道,试图始终保持地理分布副本的完全一致是徒劳的。
在分布式分区的情况下,实现完美一致性的唯一方法就是牺牲数据的可用性。
所以我一直认为,在分布式系统中,没有所谓的强一致性,都是最终一致性,只不过这个最终一致的时间窗口小到业务可以容忍的范围下。
由于在处理地理分布数据时,网络分区是不可避免的,我们通常会选择运行用户看到副本之间的数据差异的设计,也就是优先考虑可用性。也就是CAP原理的综合选择。
如果我们想处理好多个副本之间数据差异的分歧,我们就需要设立一种策略。这个策略允许副本数据在何时被认可,何时被拒绝。
对于策略,首先想到的是数据顺序策略,后来的数据覆盖前一个数据,顺序可以通过时间戳或发号器的方式解决。
如果逻辑上发现新的请求已经滞后了,直接聚焦请求即可。
另一种策略是因果一致性,就是在业务逻辑上推导出一致性,应该先有什么,再有什么。比如先有文章,才能再有评论,而不是先有了评论,还没有文章。
处理一致性背后有一个好用的原则,就是处理的顺序性,比如有时候单线程处理状态数据顺序性,比多线程处理状态数据的顺序性要简单很多,而且业务效果差不多,所以不是任何时候都需要并行、异步的。
在设计基础的分布式组件时,同样需要注意高内聚、低耦合、SOLID原则。
比如,分布式基础设施api的设计,需要极高的收敛性,因为分布式面对的问题都是非功能性的问题,对调用方越透明越好。
如果api不够收敛,调用方式就会多样,也就会导致各种不同的实现差异和使用差异。
好的api可以见名知意,也更利于单测,因为底层能力的可用性是非常重要的,传统qa的冒烟测试是不够的。