1
无论是我们在学校刚开始学编程,还是在刚参加工作开始处理实际问题,写出来的程序都是很简单的。因为面对的问题很简单。
以处理数据为例,可能只是把一个几十 K 的文件解析下,然后生成一个词频分析的报告。很简单的程序,十几行甚至几行就搞定了。
直到有一天,给你扔过来 1000 个文件,有些还特别大,好几百 M 了。你用之前的程序一跑,发现跑的时间有点长。于是想要去优化下。
1000 个文件,互相还没业务联系,用多线程呀,一个线程处理一个文件,结果再汇总就搞定了。总算把学校里学的操作系统知识和编程语言里的多线程库都运用起来了。你很高兴,老师知道了也会很欣慰。
如果多线程效果不够好,比如像 Python 的多线程,没法利用多核的威力,那就用多进程。
如果嫌线程和进程切换开销太大,大到影响整体性能 -- 通常就是所谓的 I/O bound 的场景,还可以用协程这类技术。
无论是线程、进程,还是协程,本质上,目的都是为了计算的并行化,解决的是算的慢的问题。
而如果计算量足够大,就算榨干了机器的计算能力,也算不过来,咋办?
一台机器不够,那就多搞几台机器嘛。所以就从多线程/进程/协程的「计算并行化」,进化到了「计算的分布式化」(当然,分布式一定程度上也是并行化)。
2
这还没完,另一方面,如果处理的数据有 10T,而你手上的机器只有 500G 的硬盘,怎么办?
一种办法是纵向扩展,搞一台几十 T 硬盘的机器;另一种是横向扩展,多搞几台机器,分散着放。前者很容易到瓶颈,毕竟数据无限,而一台机器的容量有限,所以在大数据量的情况下,只能选后者。
把数据分散到多台机器,本质上解决的是存不下的问题。
同时,刚才提到计算分布式化后,总不能所以程序都去同一台机器读数据吧,这样效率必然会受到单台机器性能的拖累,比如磁盘 IO、网络带宽等,也就逼着数据存储也要分散到各个机器去了。
基于这两个原因,数据存储也分布式起来了。
3
前面说计算的分布式化的时候,有这么一句话:
一个线程处理一个文件,结果再汇总就搞定了
先做任务的拆分,然后再做结果的合并。本质上就是分治的思想。很显然,分治是个非常通用和应用无关的方法,没有必要每个应用都去实现一遍,做个通用的库就行了,或者装逼点,我们叫它框架。
解决这个问题之后,再做好抽象,丰富下功能,定义好 API,基本的样子就出来了。
于是,我们有了一个分布式的计算框架。
4
而说存储的分布式化的时候,忽略了一些问题,比如:
这些问题的答案也不难:
当然,问题不只这些,只是举例而已。解决这些问题之后,再加以完善,封装好 API 和服务,一个能存海量数据的框架就有了,或者装逼点,我们叫它引擎。
于是,我们有了一个分布式的存储引擎。
5
分布式存储引擎和分布式计算框架,就是一个分布式系统最基础的组成部分。
广义的分布式系统,当然不只包含这两个东西。但它们是最基础和核心的东西。有了它们,我们就能对海量数据做最基本和通用的处理,而不再被单台机器束缚住。
是的,分布式系统很强大、很有用。但什么时候该用,什么时候又不要高射炮打蚊子呢?
其实也很简单。和分布式系统尝试解决的问题对应起来,就一目了然了:
那很有可能,你需要考虑分布式系统了。
至于多慢叫慢,多大叫大,就区别于应用场景了。
老板每天早上要看的报表,凌晨跑几个小时都能接受;全平台的准实时监控数据,就等不了几个小时了。
同样是做指标统计,几百 G 的用户注册数据可能不算大,但几百 G 的用户行为数据可能就很大了。后者比前者更有可能需要分布式系统,因为增长速度会快一两个数量级。
6
一个乍看起来很无厘头,细想又挺值得思考的问题:微服务是不是分布式系统?
类似的问题还有:分库分表+访问中间件的数据库是不是分布式系统?
广义来讲,都可以算是。
狭义来讲,也是从这个系列关注的角度来看,分布式系统是指大数据领域下,以处理海量数据为目的的系统。
当然,分布式系统远不止这么简单的两个分类,也远不止表面上看起来这样随便弄弄就能用好,还有非常多需要考虑和解决的问题,其中很多恰恰是分布式本身带来的问题(听起来很无奈吧),这也是这个系列后面会花大量篇幅去讲的内容。
这样,我们就对开头提到的 What -- 这个东西是什么,也有了基本的认识。
(看吧,先讲 Why,再讲 What,也没有影响我们学习这个东西。我这么组织,也是想借这点来强调开头提到的多思考 Why 的重要性。)
总结:
这个系列文章关注的分布式系统,是指以处理海量数据为目的的多机系统。
我们之所以需要分布式系统,是为了摆脱单机资源的束缚。再具体点,是为了解决这两个问题:
实际应用中,分布式系统最基础核心的是两种:
知道了为什么要有分布式系统,以及什么时候应该用分布式系统。紧接着一个问题就是,分布式系统都是怎么来的,又是谁做出来的呢?