This commit is contained in:
louzefeng
2024-07-09 18:38:56 +00:00
parent 8bafaef34d
commit bf99793fd0
6071 changed files with 1017944 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
大家好我是Jackey目前在一家创业公司的架构组做Java开发工作。因为工作需要我也会做一些Node、Python以及运维相关的工作所以称自己为“半栈工程师”。今天我想和你说说我学习这个专栏的一些心得。
## 我平时是如何学习的?
我先来和你说说我的经历吧。
本科毕业后,我去了一家国企做项目开发,日常工作就是使用已有框架去快速搭建一套可用的内部管理系统,然后做些定制化。
做了一年多,我感觉工作内容大量重复,所用技术也与行业严重脱节。但同时我也发现,我竟然连自己做的项目是什么原理都说不清楚,没办法通过其他公司的面试。然后,我开始深入研究所用框架,为日后的面试做知识储备。
**当我在调用框架提供的某个方法时,不再停留在是什么、怎么用,而是去研究源码看看它是如何实现的。**比如NIO是怎么实现的为什么用select而不是epoll再比如某个类的实例为什么要用单例单例还有哪些写法又比如某处代码用到了线程池用的是哪种阻塞队列为什么要用有界队列队列的参数是怎么设置的。
每次点开一段源码,我都感觉打开了新世界的大门。每次遇到新知识点,我都会通过搜索引擎去查看官方文档、技术博客或其他资料。在阅读这些技术资料的过程中,我又会发现一些新的知识盲区,进而**通过递归学习去触达更多的知识**。
经过半年多的研究我终于搞清楚当时所用框架的基本原理了。而在这期间我也从一个写Bug的小菜鸟变成了带领他人开发项目的小组长顺利入职了一家AI公司负责自有商城的开发。
团队人数不多,但技术足够新、氛围也很好,并且开发流程非常规范,编码格式要求严格。这,对我的个人成长帮助很大,因为代码就是开发者的名片,“优雅可读”的代码给人的印象总是好于“惨不忍睹”的代码。
因此,我感谢自己之前对技术原理的积累,让我有了一个更好的发展平台。
## 我为什么要学习“分布式技术原理与算法解析”专栏?
后来,因为内部调岗等因素,不想远离技术的我再次选择了离开,这次我打算去一家大公司。
由于我之前积累了比较多的基础知识再加上读过一些Redis源码在一面中的表现都很不错。但二面问到关于系统设计的问题时我就有些无从下手了。
我记得在美团二面时面试官让我设计一个注册中心。我了解一些Eureka的原理所以简单阐述了下自己的想法然后面试官在此基础上增加难度问我如何保证高可用、如何应对高并发。这时我想到了要使用分布式技术但如何做分布式、机器间怎么联系在一起、如何保证机器间数据的一致性呢
当时,我对分布式技术并没有一个清晰的认识,也不了解这些问题具体要如何解决,更不清楚引入分布式系统后会提升多少复杂度。所以,我面试的回答大都止步于提出分布式概念。
这时,我意识到自己需要去学习一些分布式系统的设计方法。互联网发展到今天,稍微有些规模的软件几乎都离不开分布式部署,多数基础组件也都建议进行分布式部署,分布式技术更是高并发、高性能的重要保证。
所以说,作为一名互联网从业者,如果不了解分布式的原理,就快与时代脱节了。也许,你会用“分久必合”来反驳我,但目前来看,硬件的发展已经明显降速,可能很难再看到“合”的场景了。因此,我相信分布式技术将会成为程序员的一项必备基础技能,看到“分布式技术原理与算法解析”专栏时毫不犹豫地就入手了。
## 学习这个专栏,我有哪些收获?
我学习专栏的习惯是,每周一三五更新后,当天上班的地铁上就抓紧学习,如果遇到不懂的知识点,就第一时间去查阅相关资料。看完一篇文章后,我会在评论区留下说说哪里有困惑,以及对应的课后思考题的解答思路,并会关注其他同学的留言,加深对这篇文章的理解。
一路学习下来,所有的辛苦都是值得的,所有的付出都是有收获的。**跟随专栏到现在,对于我来讲是“温故”和“知新”的过程。**
比如,我在学习“[分布式事务all or nothing](https://time.geekbang.org/column/article/144970)”这一篇后,不仅对熟悉的二阶段提交有了更透彻的认识,还学到了它的改良版,三阶段提交的原理。
再比如,我在学习“[分布式锁:关键重地,非请勿入](https://time.geekbang.org/column/article/145505)”这一篇后除了对基于缓存的分布式锁有了更深的理解外还学习到了基于ZooKeeper实现的分布式锁让我在日后的系统设计时又多了一种思路。
目前我们公司还处在搭建基础架构的初期。随着对分布式架构的不断了解我在公司担任的角色也更加重要了设计新系统时Leader也总会听听我的意见。同时我也希望能通过学习这个专栏在公司内做一些关于分布式技术的分享来提升自己的技术影响力。
我觉得,这都是这个专栏给我带来的收获吧。
## 给新同学的一些建议
如果你已经订阅了这个专栏,我的建议很简单,那就是抓紧时间学习吧,早学就是优势。当你养成学习习惯以后,你就发现自己已经比身边的大部分人都优秀了。
另外,我想说的是,学习专栏的过程不要局限于某个知识点,你可以再根据文章内容进行二次发散,去学习更多的知识,由点及面,构建自己的核心知识体系。
如果你还在犹豫的话,可以对比一下我的经历,如果你有所感触的话,真心建议你能认真学完整个专栏,再去挑战大厂,成功率会大很多。

View File

@@ -0,0 +1,187 @@
<audio id="audio" title="特别放送 | 分布式下的一致性杂谈" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/76/db/76a475f126bc8cab29cfa3d1ea76b0db.mp3"></audio>
>
你好,我是聂鹏程。
>
我们常说:“众人齐心,其利断金。”其实说的就是团结一致的重要性。一致性对一个团队如此重要,对于一个分布式系统又何尝不是呢?人心散了,团队会不好带。分布式系统中出现不一致了,也会带来各种各样的问题,甚至导致业务不可用。
>
我在第23讲“[CAP理论这顶帽子我不想要](https://time.geekbang.org/column/article/166582)”时,就解释了分布式系统中一致性和可用性,就像是鱼与熊掌,不可兼得。因此,多年来,在不同场景下,保证一致性的同时尽可能提高可用性,或者保证可用性的同时尽可能提高一致性,成为了众多学术界、工业界仁人志士们研究的课题以及努力的方向。正可谓,分布式技术如此多娇,分布式一致性引无数英雄竞折腰。
>
今天,我特地邀请到我的朋友王启军,来与你分享他对分布式一致性的解读、思考和实践。
>
王启军华为云PaaS团队资深架构师负责 Java和Go微服务框架。他曾任当当网架构师主导电商平台架构设计曾就职于搜狐负责手机微博的研发著有《持续演进的Cloud Native》。
>
话不多说,我们来看看王启军的分享吧。
你好,我是王启军。今天,我来和你聊聊分布式下的一致性。
以前面试别人的时候,我经常会用一些开放性的问题来考察对方的能力。比如我最爱的一个问题是,“如果给你一份数据,要求支撑大规模的并发读写,同时具备横向扩展能力,你该如何拆分、如何同步数据呢?”
此时,候选人想到的通常是复制数据到多台服务器,以提升读的性能;然后对数据进行分区,分布到不同的服务器,以解决写的瓶颈。
如果到了这里,接下来我会问他怎么同步数据,一次性写多条数据,怎么保证多台服务器的一致性呢?如果数据同步存在延迟,怎么保证写后一定能读到呢?
这次追问之后,大部分候选人就会卡住。不知道你在面试的时候有没有遇到过类似的问题,今天我就想和你聊聊这个话题。
## 一致性的分类
业界对一致性的定义有很多种比如CAP理论中的一致性和ACID中的一致性描述的就不太一样不能一概而论。所以在讨论之前你最好弄清楚**一致性的分类**。
为了便于理解,业界通常会把一致性笼统地分为如下三类:
- 弱一致性Weak写入数据A成功后在数据副本上可能读出来也可能读不出来不能保证多长时间之后每个副本的数据一定是一致的。
- 最终一致性Eventually写入数据A成功后在其他副本有可能读不到A的最新值但在某个时间窗口之后保证最终能读到。最终一致性可以看作弱一致性的一个特例这里的重点是“时间窗口”。在读多写少的场景中例如CDN读写比非常悬殊如果网站的运营人员修改了一张图片最终用户延迟一段时间看到这个更新实际上问题不大。我们把这种一致性归结为最终一致性指的就是如果更新的时间间隔比较长那么所有的副本能够最终达到一致性。
- 强一致性Strong数据A一旦写入成功在任意副本任意时刻都能读到A的最新值。
但实际上,**这种分类并不能描述清楚**,弱一致性在生产环境中基本没什么应用场景,最终一致性范围太宽泛,可能会存在多种不同强度的一致性。
相对来说,我更喜欢另外一种对一致性的分类方法,**一致性模型主要从以下两个角度去分类**
- 以数据为中心的一致性模型。从数据的角度来观察,全局考虑,比如从数据库的角度来看,北京和南京的数据是否一致。
- 以客户为中心的一致性模型。从用户的角度来观察,比如我购买了一个商品,存到了北京的数据中心,另外一个人购买了一个商品,存到了南京的数据中心,两个买家之间没有任何关系,无需保持一致,只要是跟我有关系的数据保证一致就行了。
这两种一致性模型,又可以细分为很多类。接下来,我们就一起看看吧。
**以数据为中心的一致性模型,又可以分为**严格一致性Strict Consistency、顺序一致性Sequential Consistency、因果一致性Causal Consistency、FIFO一致性FIFO Consistency、弱一致性Weak Consistency、释放一致性Release Consistency和入口一致性Entry Consistency
限于篇幅,我不会详细介绍每一种一致性的定义,只和你说明几个常用的。
**严格一致性**,要求任何写操作都能立刻同步到其他所有进程,任何读操作都能读取到最新的修改。要实现这一点,要求存在一个全局时钟,也就是说每台服务器的时间都完全一致,但在分布式场景下很难做到。所以,严格一致性在实际生产环境中目前无法实现。
既然全局时钟导致严格一致性很难实现顺序一致性放弃了全局时钟的约束改为分布式逻辑时钟实现。分布式逻辑时钟可以理解为一个分布式ID。
**顺序一致性是指**所有的进程以相同的顺序看到所有的修改。读操作未必能及时得到此前其他进程对同一数据的写更新但是每个进程读到的该数据的不同值的顺序是一致的。举个例子你在手机和PC上看到的聊天室的顺序是一致的吗如果是一致的那就代表满足顺序一致性即使理论上某些先发的消息排在后发的消息后面了也是满足的。
**因果一致性**是一种弱化的顺序一致性,所有进程必须以相同的顺序看到具有潜在因果关系的写操作,不同进程可以以不同的顺序看到并发的写操作。举个例子,在聊天室你看到有人问你:“你吃饭了吗?”,你回答:“我吃过了。”,你是因为看到了问题所以才触发了回答,所以这两条消息之间就存在因果关系,原因必须排在前面。
**以用户为中心的一致性模型包括4类**
- 单调读一致性Monotonic-read Consistency
- 单调写一致性Monotonic-write Consistency
- 写后读一致性Read-your-writes Consistency
- 读后写一致性Writes-follow-reads Consistency
**单调读一致性**是指如果一个进程读取数据项a的值那么该进程对a执行的任何后续读操作总是得到第一次读取的那个值或更新的值。这个比较容易理解说白了就是不能读到新数据后再读到比这个数据还旧的数据如果没读到新数据一直读的还是旧数据单调读一致性并不关心这个问题。
**单调写一致性**是指一个进程对数据项a执行的写操作必须在该进程对a执行任何后续写操作前完成。这个很容易满足注意这里是一个进程所有的写操作都是顺序的。
**写后读一致性**是指一个进程对数据项a执行一次写操作的结果总是会被该进程对a执行的后续读操作看见。这个比较常见比如数据库采用Master-Slave结构部署时写完Master数据库如果从Slave读取有可能读不到就不满足写后读一致性了。
**读后写一致性**是指同一进程对数据项a执行的读操作之后的写操作保证发生在与a读取值相同或比其更新的值上。这个问题经常出现的场景是如果数据存储了多个副本因为没有及时同步在第一个副本上读了数据去第二个副本上写出现不一致的情况。
## 如何满足一致性需求?
当单个存储承受不住压力的时候在读多写少的情况下我们自然会想到使用主从的方式。为了保证写的一致性通常只在主节点写然后主从之间通过状态机Replicated State Machine的方式同步数据。
可以简单地理解为,**主从都有相同的初始状态,在主上执行的所有命令,都同步一份相同顺序的命令到从,这样就可以保证最终数据也相同**。
比如MySQL就可以采用一个Master多个Slave的方式所有的写都在Master上更新所有的读都在Slave上进行但这里存在一个问题就是怎么保证写后读一致性答案就是写后读都在Master上进行。注意并不是所有的读都作用在Master而只对写后读一致性有要求的场景才在Master上读。
当然这样Master的压力可能还是会很大。回到问题本身之所以满足不了写后读一致性原因是主从之间存在延迟。那么我们完全可以设定一个大于延迟时间的阈值小于阈值并且要求写后读一致性的操作作用在Master上其他所有的读都作用在Slave上。
还有一个问题就是,当主挂掉的时候,为了保证可用性,通常要将其中一个从提升为主,这里面就会涉及很多问题,到底选择哪个从作为主节点?发生网络分区的时候,如何避免脑裂?如果旧的主节点又恢复了,如何协调?
关于这些问题如何解决你可以参考Etcd和ZooKeeper的实现方案。
### Quorum机制NWR模型
主从机制要求写必须在主上进行,那能不能让写在所有节点上都可以进行呢?当然可以,不过这已经不是主从模式了。
回到前面的问题如果同时写三份数据如何保证一定能够读取到最新的数据呢简单来说就是利用版本号假设一共三个节点每次写数据的同时我都会记录这条数据对应的版本号读数据的时候读所有的节点然后跟版本号进行对比版本最新的就是最终数据。实际上这就是Quorum机制的原理也可以叫作NWR模型。
简单来说Quorum机制就是要满足公式W+R &gt; N。其中W表示必须至少写入成功的节点数R表示至少读取成功的节点数N表示总节点数。**这个公式把选择权交给了业务用户,让用户来做出最终决策。**
假设现在一共有三个节点,为了满足这个公式:
- 如果我写数据的时候写入三个节点都成功才返回,那我读取的时候只要读取其中任意一个节点就可以得到最新的数据。
- 如果我写数据的时候写入两个节点成功就返回,那我读取的时候只要读取其中任意两个节点就可以得到至少一份最新的数据。
- 如果我写数据的时候写入一个节点成功就返回,那我读取的时候必须读取所有节点才可以得到至少一份最新的数据。
**这里还存在另外一个问题**那就是如果写的时候只写入一个节点就返回当存在并发操作时版本会存在冲突也就是说如果初始版本为1两个进程分别对其中两个节点写数据两个节点版本号都变成了1数据却不一样这个问题如何解决呢
就要求我们写数据的时候最好是遵循W&gt;N/2也就是说写的时候最好大于总节点数的一半在写的过程中进行冲突检测而不是在读的时候检测。
### N阶段提交
还有一种比较经典的做法常用在数据库中那就是N阶段提交。这里的N有一阶段、两阶段、三阶段其中两阶段用得最多。
这里我必须首先说明一下,**两阶段提交不等于XA协议两阶段提交是一种模式**ZooKeeper中提交事务的过程实际上也类似于两阶段提交Google的分布式事务Percolator也是基于两阶段提交**而XA只是一种协议**。它是由X/Open国际联盟提出的X/Open Distributed Transaction ProcessingDTP模型简称XA协议。
<img src="https://static001.geekbang.org/resource/image/14/e8/14a5bb905f1835d472ca3e0388be46e8.png" alt="">
顾名思义两阶段提交的整个过程分为两个阶段第一阶段询问是否可以提交锁定数据如果所有节点都返回可以提交第二阶段提交否则第二阶段回滚。基于XA的两阶段提交就是这种流程这种方式常用于同时更新两个数据库的场景一般常用的关系型数据库都支持这个协议。
由于第一阶段要给数据库加锁,否则会出现不一致的情况,这就会带来很多问题,**XA被诟病的大部分原因都跟这个锁有关**。例如,加锁后,协调者挂掉怎么办?加锁后,性能大幅下降如何处理?
为了解决死锁的问题,可以将加锁的时间缩短,降低死锁的概率,这就是三阶段提交。也就是说把第一阶段分为两个部分,询问是否可以提交,回复可以提交的时候,并不加锁,当所有节点都回复可以的时候,协调者再发一次加锁的请求。但这样的话,系统会变得更复杂。
当然两阶段提交并不是只有XA协议TCC也可以看成是一种两阶段提交协议TCC是Try-Confirm-Cancel的缩写。相对于两阶段提交事务机制它的特征在于不依赖于数据库的协议数据库不需要锁定数据事务过程由业务服务来实现这样也就不会出现死锁的问题性能也会高很多。还有一点容易被忽略这种做法降低了数据库的压力。
<img src="https://static001.geekbang.org/resource/image/61/38/6178edafcb745fe8e0bb95df99b3ba38.png" alt="">
当然,世界上没有免费的午餐,**TCC事务机制也有不好的地方**
- 导致业务变得更复杂,数据库需要增加字段表示状态;
- 需要增加相应接口实现Confirm和Cancel方法
- 业务要自己保证每个方法的幂等,因为这里可能涉及到失败重试的问题。
而一阶段提交,就是没有询问是否可以提交的过程,直接提交,任意一个节点提交失败,就进行重试或者回滚。这种方案对业务的侵入性很大,需要对业务提供一个回滚操作。
## 实践案例
接下来,我就以在华为云的工作场景为例,来给你串下整体的思路吧。
华为云目前的分布式框架采用TCC的模式将协调者从业务中抽离独立为一个服务。主业务发起事务获得全局事务ID调用分支业务时将全局事务ID通过Header传递过去分支业务根据全局事务ID申请分支事务ID所有的状态都会存储到分布式事务服务端服务端根据执行情况进行全局协调。
事务执行的大概步骤,如下所示。
<img src="https://static001.geekbang.org/resource/image/86/3e/86defbf0639770e1f9e2c4deef02eb3e.png" alt="">
- 步骤1进入到发起全局事务的方法内时会先向DTM集群申请注册一个全局事务IDGlobal Transaction ID只有申请成功才可继续后续流程。
- 步骤2.1事务发起者将申请到的全局事务ID透传到所调用的事务参与者中。
- 步骤2.2事务参与者利用得到的全局事务ID向DTM集群注册申请一个分支事务IDBranch Transaction ID只有申请成功才可继续此事务参与者的后续流程。
- 步骤2.3事务参与者完成自身业务逻辑即完成TCC中的Try阶段
- 步骤2.4事务参与者将自身业务逻辑结果上传到DTM集群并示意分支事务结束。
- 步骤3.1~3.4与2.1~2.4类似,完成剩余事务参与者的业务逻辑。
- 步骤4事务发起者发起TCC二阶段。
- 步骤5.1DTM集群根据全局事务ID找到事务参与者发起TCC二阶段。
- 步骤5.2与5.1类似完成剩余事务参与者的TCC二阶段。
- 步骤6DTM集群通告事务发起者全局事务结束。
## 什么时候开始考虑一致性?
在分布式领域,一致性是个永恒的话题,因为在大多数场景下,出于成本考虑,通常会选择性地忽略或者降低对一致性的要求。但是,当系统达到一定规模的时候,不一致的概率就会大大增加,比如原本不一致的概率可能是一万年一次,如果数据量提升一万倍,那可能是一年一次。但,无论发生的概率是多少,研发成本都是一样的,这时候实现更强的一致性就非常有必要了。
凡是涉及钱的系统,对一致性的要求必然很高,除此之外,大多数场景实际上对一致性的要求并没有那么高,比如用户登录时给用户加一个积分,加积分这个操作并没有那么重要,延迟几秒影响也不大,那完全可以做成异步的,保证最终一致性就可以了。
## 有没有什么学习材料?
如果要推荐学习资料的话,我建议你可以多去看看分布式领域的论文,特别是大神莱斯利 · 兰波特Leslie Lamport以及Google、Amazon等硅谷著名企业发布的论文。比如下面这两篇我就非常推荐你去读一读因为很多数据库的分布式事务都是参考了它们 。
- [Percolator的论文](http://research.google.com/pubs/pub36726.html)可以认为是Spanner的类似实现TiDB的实现也是根据此论文得出。
- [DynamoDB的论文](https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf)Dynamo: Amazons Highly Available Key-value Store。
另外你还可以看一些开源框架的实现比如Cassandra、Kafka等这些代码对于你理解分布式一致性会有非常大的帮助。
## 总结
我来简单和你总结一下今天的主要内容吧。
首先,要搞明白分布式一致性,我们就要从其分类开始,除了弱一致性、强一致性、最终一致性这种分类方式外,还有一种更好的分类方式,就是以数据为中心和以用户为中心的一致性分类。
其次如果要满足一致性的需求有很多种方案这里我们介绍了两种最常用的方案Quorum机制和N阶段提交并通过华为云的一个实践案例来加深你对一致性的理解。
最后,在分布式领域,一致性是目前为止解决得最不好的一个领域,也是最复杂的一个领域,解决方案五花八门,我只是与你介绍了其中的一部分内容,如果你要继续学习,可以多阅读一些论文和开源框架的代码。

View File

@@ -0,0 +1,66 @@
>
你好,我是聂鹏程。今天,我要和你分享的是,一名专栏订阅用户“崔新”的一些学习方法,主题是“追根溯源,拨开云雾见青天”。
>
虽然专栏已经更新结束,但我仍会关注会回复你的留言,并针对因时间问题未做到最好的文章做一次迭代。所以,我希望你也可以继续关注专栏,继续与我分享你在学习、工作过程中遇到的问题。
>
话不多说,现在就来看看崔新的故事吧。
大家好,我是崔新,昵称“随心而至”,一名后端开发者,坐标上海,工作一年多,在这里分享下自己学习“分布式技术原理与算法解析”专栏的心得。
## 我为什么要学这个专栏?
说来惭愧,我对单机的很多内容(比如操作系统、计算机组成原理)还是一知半解,但就是对分布式特别感兴趣,想知道成千上万的机器是如何协作共同完成一个任务的,想让自己的见识更广阔些。所以,**我学习这个专栏的初衷,更多的是兴趣,也坚信兴趣就是最好的老师**。
聂老师在开篇词中提到“知识碎片化、不成体系、见树不见林”,感觉一下就点到了我的死穴。我也听说过很多分布式概念,但只知其一不知其二。所以,**通过这个专栏,我想要系统化地学习分布式技术,了解其背后原理。**
另外,分布式框架发展得实在是太快了,如果我只是跟随发展热度去学习,焦虑、疲惫不说,收效甚微也是个大问题。所以,**我选择学习这个专栏的另一个目的是,想要看看技术的源头是什么样的,从根儿消除焦虑。**
我去年大学毕业参加工作Redis、Kafka、MongoDB、Elasticsearch、Storm、Spark、Hadoop等框架几乎是一瞬间同时跳到我眼前只能一个个去学习。学习一段时间后我发现这些框架有很多共性比如通信、选主、复制、协调。之后我开始有针对地去看一些文章对比着学习这些框架但总感觉不得要领学不透。
直到看到聂老师的开篇词我豁然开朗也更坚信“Software comes and goes, but hardware is forever”。只有追溯到技术的源头明白它从哪里来要到哪里去学习起来才能事半功倍。
## 我是怎么学习这个专栏的?
在专栏更新的过程中,我都是按照专栏更新的节奏在学习,大多会利用上班路上的时间,像追剧一样。有时我需要反复看几遍才能理解一个知识点,有时我需要停下来思考一段时间才能搞明白一个知识点,所以充分的学习时间对我来说很重要。追专栏更新的这个过程,也帮助我养成了一个良好的学习习惯。
**说到学习方法,我感触最深的有两点:一是,形象化和类比,可以帮助我更深入地理解知识;二是,实践很重要。**
不知道你有没有注意到,每一篇文章的题目都恰到好处,比如“分布式选举:国不可一日无君”。用熟悉的事件来类比技术问题,一下子就让我明白了这个技术的精髓,可谓四两拨千斤。其实,**我们也可以尝试用熟悉的事件将知识形象化,先有个感性的认识。**
比如聂老师讲到“分布式技术是多台机器集群如何协同完成一件事儿”你会不会想到通过单机的多进程、多线程等场景来理解呢。我对Java还算熟悉所以会用JUC中的知识来类比。适当的类比、举一反三可以帮助我更好地理解新知识和巩固旧知识。
这个专栏的设定是“技术原理与算法解析”,估计很多同学和我开始的想法一样,希望能多一些实践性的内容。但学完几篇文章后,我细想,聂老师想讲的是“道”,是一般性、普适性的原理,而具体的框架、实现只是在这些核心原理的基础上又添加了很多细节。
**在框架中验证原理,可以让我们理解得更深刻;将知识点与业务场景联系起来,才能真正发挥其作用,进而提升自己的业务能力。**
所谓,师傅领进门修行在个人,我觉得要想搞清楚、弄明白一个知识点,学完技术原理后,一定要多实践,去看具体框架的官方文档、源码,并上手操作。
## 学到现在,我的收获和体会
因为我学习这个专栏的目的很明确,所以学完已经更新的这些文章,感觉收获也非常大。
首先,**我的眼界更开阔了,知识也逐渐成体系了**。学习时我经常会遇到自己不甚了解的技术比如Actor、单体调度等感觉非常爽。
同时,不得不说的是,聂老师对分布式技术体系“四纵四横”的划分,非常清晰明了,让我知道应该学习哪些知识,以及这些知识间的内在联系是什么样的。专栏每一站都会讲到最常用的那些技术点,各个站串联起来,就是一张分布式技术的知识地图,我要做的就是,按图索骥、多加实践。
其次,**我逐渐形成了一套自己的学习方法**。我觉得这个专栏最大的一个特点就是都是分布式中最最核心的那部分技术。我可以集中精力去学这些最关键的主干知识然后再去丰富枝叶比如具体的框架实现、知识延伸。这种思路其实就符合80/20法则。
我感触比较深的另一个点是,学习知识要多思考、勤总结。聂老师在每篇文章后都提供了一个知识扩展模块和一张思维导图,不仅有助于我复习,还能帮我从广度和深度上完善自己的知识体系。对我来说,这是一个非常好的方法。
## 我想对专栏初学者说的话
工作一年多来,我总结了些学习方法,也有很多感触,想和你分享、交流。
**首先,基础要扎实,学习要系统。**虽然我是计算机专业出身,但大学时净忙着学习各种编程语言了,反倒是计算机基础知识没打牢。意识到这一点后,我开始系统地学习计算机组成原理、操作系统、数据库、数据结构与算法等基础知识了。
如果你的基础也和我一样不那么扎实的话,不要着急,静下心来一点一点地学习就好了。
**其次,眼光放长远,关注复利效应。**现在市面上充斥着各种速成系列,我觉得要离这些东西远一些,否则会一直在低水平重复。不求速成,日拱一卒才更适合我。只要保持增长,即使增长速度没那么快,日积月累的效果也会很可观。这,就是复利效应的魔力。

View File

@@ -0,0 +1,91 @@
<audio id="audio" title="特别放送 | 徐志强:学习这件事儿,不到长城非好汉" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f7/5f/f70e22e25b2eb5c60120a44a1e29825f.mp3"></audio>
>
你好,我是聂鹏程。今天,我要和你分享的是,一名专栏订阅用户“徐志强”的学习经历与方法,主题是“学习这件事儿,不到长城非好汉”。
>
你在学习专栏的过程中,有没有什么独特的学习方法和心路历程呢?欢迎你写在留言区,我很期待能跟你在这里交流、讨论,一起学习进步。
>
话不多说,现在就请你返回文稿看看徐志强的故事吧。
大家好我是徐志强一名Java开发者从事互联网金融工作三年了。
从2016年毕业到现在我从一枚“小白”变成了“熟练工”。但我一直不甘心从“小熟练工”变成“老熟练工”所以我来了“极客时间”。回过头来看自学的这三年我收获很多也走了不少弯路。所以我想把自己的学习经历分享出来希望能帮你避开些弯路。
## 我是如何学习的?
我自学的三年,可以分为以下三个阶段。
**第一阶段**:啥都不懂,啥都想学。我买了非常多的书,数据库、操作系统、分布式等每个知识领域都买了一两本,但只是停留在“看了”的阶段。工作中遇到问题时,我不能融会贯通地用到所学知识,或者说我自学的知识基本用不到工作中。这就像大脑里装了很多武器,但我只记得它们的说明书,无法根据它们的特性做出选择。
其实在这个阶段,我们都很容易有个误解:觉得只要看了足够多的书、学了足够多的框架,能力自然就会得到提高,但其实蜻蜓点水般的学习收效甚微。所以,在我看来,广度学习虽然容易,但其实只算是到了长城脚下,只是起点。
**第二阶段**:调整思路,有选择地精读某些内容。觉察到不对后,我把之前那些书重新找了出来,并调整学习思路:挑选关键知识点采取精读的方式复习,并开始啃一些框架和库的源码。
“如果不了解核心原理,我始终都是一枚小白或者熟练工” 这是我经常暗示自己的话。为此我曾经通宵Debug就是为了搞明白一段很复杂的源码。每次我在源码中发现了书中描述的知识点后都非常有成就感原来就是这样呀这也让我持续有动力去啃源码。
但我发现,学习源码并没有提升程序设计能力,我又进入了新的困惑期:怎样才能更好地消化和理解知识、怎样才能做到举一反三,养成解决问题的能力。为了爬上长城,我继续寻找答案。
**第三阶段**:学习一些架构方面的知识,形成知识点和问题的映射。当精读某一领域的知识内容后发现,我在系统设计上短板暴露了出来。因为做系统设计需要有全局思维,需要对整个系统架构的技术栈有清楚的认识,能对比分析不同技术的差异和特性,而不能局限于一个分支。
于是,我开始学习架构方面的知识,学习知识点和问题间的映射关系。每遇到一个问题我都会多思考几套解决方案并进行对比分析,每学到一个新知识点就思考它可以用在哪些场景,以及各个知识点有什么共性和联系。
说到这里,我再分享一段我的面试经历吧。去年年初我去参加面试,因为平时看了不少书、也阅读了不少源码,可以很轻松地通过一面、二面,但最后一面我就有点招架不住了。后来,我请教面试官,自己还欠缺哪方面的知识和能力。他告诉我,单论某一个知识点我掌握得还不错,但我不能将所有知识由点串成线,由线串成面,最终形成网,建议我平时多思考、多总结。
他的这番话对我影响非常大,一下就点醒了我,帮我找到了困惑许久的问题答案。正处于第三阶段学习的我,或许后面我还会有新的困惑,但方法总比问题多。现在,虽然我不知道自己爬到了长城的第几级台阶,但我坚信自己终将站上最高的烽火台!
**总结我的学习经历,我觉得有下面几个点值得注意:**
1. 一定要坚持学习充电,否则很快就会被淘汰。
1. 不要惧怕学习新技术,新技术不管怎么变化,原理和本质都是不变的。
1. 一定不要只漂在技术的表面,一定要学原理,否则漂的时间久了你自己都不知道漂到哪了。
1. 师傅领进门很关键。学一门新技术,最好是找一本经典的书,或者一门经典的课程系统地学习。
1. 多思考,才能构建自己的知识体系和思维模式,才能将知识化作解决问题的方案。在学习时,我们要思考各个知识点的共性和内在联系,思考这个知识点能解决什么问题,以及遇到的问题能用什么知识点去解决。这样,脑中储存的知识,才能真正为我们所用。
## 为什么要学习分布式技术和原理?
分布式是当前技术领域的趋势之一,它扩展了计算机的计算边界,是区块链、人工智能、机器学习、大数据等众多前沿技术的基石。
所以,如果你不想永远当一枚小白或者熟练工,也不想被行业淘汰的话,就必须学习分布式技术,且一定要把原理学明白,不能局限于皮毛。我们不能一直随着浪花漂荡,要尝试将自己沉入海底,这样才能经受得住惊涛骇浪的洗礼,最终到彼岸。
我学习的第一个中间件是Kafka刚开始学的时候就被它的分区、选主、备份等概念搞得晕头转向后来又学习了Redis和Elasticsearch。这时我发现这些中间件有一些共同特点都会考虑分区来提高吞吐量都会考虑备份来保证容错和可用性多个备份之间都会选举一个主来提供服务。
慢慢地,对这些概念越来越熟悉后,我发现它们在分布式场景下都会遇到些类似的问题,只是各自的解决方案不同而已。因此,我心中萌生了系统学习分布式技术和原理的想法,因为只有弄清楚了分布式技术的本质和原理,才能在各种眼花缭乱的技术框架中游刃有余。
于是,我开始在网上搜集各种学习资料,又来到了极客时间,来到了“分布式技术原理与算法解析”这个专栏。
## 我是怎么学习这个专栏的?
说到我是怎么学习这个专栏的,因为之前已经自学过些分布式技术原理,所以可能会和其他人的方法不太一样。
首先,我不是利用碎片时间单篇文章地去学习,而是会找一个比较长的空闲时间,一气呵成地学习完一个模块的内容。这样我可以联系上下文,一下搞定相关知识点。
其次,学完每篇文章,我都会梳理、总结自己对这篇文章的理解,并尝试回答课后思考题,在评论区留言。同时,我也会关注其他同学的留言问题,并尝试做解答。在这个过程中,针对文章中的疑惑点,我会先去搜索相关资料学习,然后将具体的疑惑点留言给老师,等他的解答。
最后,关于知识点的思考和联想很重要。老师讲的很多分布式技术知识点都是通用的,在很多的中间件和框架中都有体现,根据这些理论去思考具体的组件是如何实现的,可以帮助我理解得更深刻。
## 学习到现在,我最大的收获和体会
到现在为止整个专栏已经更新了18篇文章可以说帮助我建立了对分布式技术和原理比较全面、系统的认知越往后的体会越深。
其实在学习这个专栏前我就对分布式的一些概念比如分布式事务、BASE理论、CAP理论、分布式锁等有些了解但这些知识点在我脑中是独立没有关联起来的。所以这个专栏对我最大的帮助是帮我打通了这些知识点有了一个系统化的认知。
此外,这个专栏给了我极大的信心。因为,聂老师的讲述是由浅入深的,并且还有大量形象的比喻和深刻的类比。比如,用事务模型来解释共享状态的分布式调度,在我看来就很形象、很有深度。
因此,这个专栏给我的感觉是“分布式技术和原理原来就是这么回事呀”,完全消除了我之前的畏难情绪。虽然学完这个课程不代表能透彻掌握分布式的技术原理和算法,但这肯定是一个非常棒的开始。
## 留给朋友们的建议
如果你之前没有接触过分布式的技术和中间件的话,我建议你先花点时间去补些基础,但这也不妨碍你将这个专栏作为你的“分布式技术和原理导论”来学习。
如果你之前了解过一些分布式技术和分布式组件,但是学得不深入的话,我觉得这个专栏可以帮你建立全面的分布式知识体系,直接带你练习上乘内功。非常值得拥有,我现在也正处于这个阶段。
如果你已经对分布式技术和常用组件都很熟悉了的话,我觉得这个专栏可以带你到更高的层次,去思考分布式的核心本质,帮助你更好地造轮子。
每个人都有自己的一座长城,有些人爬了一年数个月,有些人爬了十年,而有些人爬了一辈子,他们在长城上看到风景肯定大有不同。技术学习件事,我希望自己当一回好汉,爬上自己的长城,也祝愿各位小伙伴能爬上自己的长城!

View File

@@ -0,0 +1,137 @@
<audio id="audio" title="特别放送 | 那些你不能错过的分布式系统论文" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b3/9e/b358793b95b47c22983440809017ad9e.mp3"></audio>
>
你好,我是聂鹏程。
>
古人云“以史为鉴,可以知兴替。”说的就是追本溯源的力量。通过学习和思考技术的发展和演进,我们方能更好地把握未来。而对分布式技术追本溯源的方式,无疑就是精读相关经典轮文了。
>
为此,今天我特地邀请了我的朋友刘梦馨,来与你系统分享下分布式系统领域的经典论文。你有时间和耐力的话,可以逐一阅读、学习下这些论文。
>
刘梦馨是灵雀云容器平台高级研发工程师负责容器平台的架构、容器网络方案的设计和实现也是开源Kubernetes网络插件 Kube-OVN 作者。他平时非常喜欢阅读论文,也总结了很多高效阅读论文的方法。
>
话不多说,我们来看刘梦馨的分享吧。
你好,我是刘梦馨。
分布式系统领域有着最令人费解的理论全链路的不确定性堪比物理中的量子力学。同时分布式系统领域又有着当代最宏伟的计算机系统Google、Facebook、亚马逊遍布全球的系统支撑着我们的信息生活。
显然,能够征服分布式系统的,都是理论和实践两手抓两手都要硬的强者。然而,分布式系统领域还有着最高的上手门槛,没有大规模的基础设施、没有潮水般的流量,分布式领域幽灵般的问题并不会浮出水面。
那么,我们应该**如何开启征服分布式系统的征程**呢?
好在这条路上我们并不孤独。学术大牛们在五十年前就开始探索各方面理论上的问题,全球规模的互联网公司也有着丰富的实践和经验。而这些分布式领域人类的智慧,最终都沉淀为了一篇篇的经典论文。
和普通的技术文章相比,论文的发表有着极为严格的要求,随之而来的也是极高的质量。通过阅读分布式领域的经典问题,我们可以快速吸收前人的智慧,领略大型系统的风采,并收获最为宝贵的实战经验。
现在,就让我们从一篇篇经典论文开始,踏上征战分布式系统的征程吧!
我**按照从理论到实践的顺序**,将经典的分布式系统论文分成了分布式理论基础、分布式一致性算法、分布式数据结构和分布式系统实战四类,帮助你快速找到自己需要的论文。
这些论文我都给到了标题你可以直接去Google 学术里搜索。
## 分布式理论基础
分布式理论基础部分的论文,主要从宏观的角度介绍分布式系统中最为基本的问题,从理论上证明分布式系统的不确定、不完美,以及相互间的制约条件。研读这部分论文,你可以了解经典的 CAP定理、BASE理论、拜占庭将军问题的由来及其底层原理。
有了这些理论基础,你就可以明白分布式系统复杂的根源。当再碰到一些疑难杂症,其他人不得其解时,你可以从理论高度上指明方向。
以下就是分布式理论基础部分的论文:
- Time, Clocks, and the Ordering of Events in a Distributed System
- The Byzantine Generals Problem
- Brewers Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services
- CAP Twelve Years Later: How the “Rules” Have Changed
- BASE: An Acid Alternative
- A Simple Totally Ordered Broadcast Protocol
- Virtual Time and Global States of Distributed Systems
## 分布式一致性算法
只要脱离了单机系统,就会存在多机之间不一致的问题。因此,分布式一致性算法,就成了分布式系统的基石。
在分布式一致性算法这一部分我将与你推荐2PC、Paxos、Raft和ZAB等最知名的一致性算法。分布式算法的复杂度比普通算法要高出几个数量级所以这部分论文是最为烧脑的一部分。
搞明白这部分论文,你的空间想象力和统筹规划能力都会得到质的提升。
- A Brief History of Consensus, 2PC and Transaction Commit
- Paxos Made Simple
- Paxos Made Practical
- Paxos Made Live: An Engineering Perspective
- Raft: In Search of an Understandable Consensus Algorithm
- ZooKeeper: Wait-Free Coordination for Internet-Scale Systems
- Using Paxos to Build a Scalable, Consistent, and Highly Available Datastore
- Impossibility of Distributed Consensus With One Faulty Process
- Consensus in the Presence of Partial Synchrony
## 分布式数据结构
分布式数据结构部分的论文,将与你介绍管理分布式存储问题的知名数据结构原理。通过它们,你可以构建自己的分布式系统应用。
这部分论文的涵盖范围大致包括两部分一是分布式哈希的四个著名算法Chord、Pastry、CAN 和 Kademlia二是Ceph 中使用的 CRUSH、LSM-Tree 和 Tango算法。
和分布式一致性算法类似,分布式数据结构也极其考验空间想象力和统筹规划能力。不过,在经过分布式一致性算法的锻炼后,相信这些对你来说已经不再是问题了。
- Chord: A Scalable Peer-to-Peer Lookup Service for Internet Applications
- Pastry: Scalable, Distributed Object Location, and Routing for Large-Scale Peer-to-Peer Systems
- Kademlia: A Peer-to-Peer Information System Based on the XOR Metric
- A Scalable Content-Addressable Network
- Ceph: A Scalable, High-Performance Distributed File System
- The Log-Structured-Merge-Tree
- HBase: A NoSQL Database
- Tango: Distributed Data Structure over a Shared Log
## 分布式系统实战
分布式系统实战部分的论文,将介绍大量互联网公司在分布式领域的实践、系统的架构,以及经验教训。
Google的新老三驾马车Facebook、Twitter、LinkedIn、微软、亚马逊等大公司的知名系统都会在这一部分登场。你将会领会到这些全球最大规模的分布式系统是如何设计、如何实现的以及它们在工程上又碰到了哪些挑战。
- The Google File System
- BigTable: A Distributed Storage System for Structured Data
- The Chubby Lock Service for Loosely-Coupled Distributed Systems
- Finding a Needle in Haystack: Facebooks Photo Storage
- Windows Azure Storage: A Highly Available Cloud Storage Service with Strong Consistency
- Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing
- Scaling Distributed Machine Learning with the Parameter Server
- Dremel: Interactive Analysis of Web-Scale Datasets
- Pregel: A System for Large-Scale Graph Processing
- Spanner: Googles Globally-Distributed Database
- Dynamo: Amazons Highly Available Key-value Store
- S4: Distributed Stream Computing Platform
- Storm @Twitter
- Large-scale Cluster Management at Google with Borg
- F1 - The Fault-Tolerant Distributed RDBMS Supporting Googles Ad Business
- Cassandra: A Decentralized Structured Storage System
- MegaStore: Providing Scalable, Highly Available Storage for Interactive Services
- Dapper, a Large-Scale Distributed Systems Tracing Infrastructure
- Kafka: A distributed Messaging System for Log Processing
- Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases
以上就是我为你准备的分布式系统经典论文清单了。这个清单里的每一篇论文,都是经典中的经典。很多论文对之后的工业界及学术界产生了翻天覆地的影响,开创了一个又一个火热的产业。
希望你没有被这个清单吓到,当你翻开这些论文后,就会发现它们的内容并不是高高在上,包含了很多很实际、很具体的问题。认真读下去,你甚至会有掌握了屠龙之技的快感,一发而不可收拾。
为了帮助你高效阅读这些论文,并汲取其中的精华,我再和你说说我阅读论文的一些心法吧。
## 如何高效地阅读论文?
一般来说,单篇论文大概会有 15 到 20 页的内容,**如果你是第一次读论文可以把重点放在前面的背景介绍、相关工作和概要设计上**。好的论文通常会很仔细地介绍背景知识,帮助你从宏观上先对整个问题有一个初步认识,了解当前现状。
接下来,你可以再**根据自己的兴趣,选择是否仔细阅读论文涉及的详细原理和设计**。这一部分,通常是论文中最精华的部分,包含了最具创新的理念和做法,内容通常也会比较长,需要花费较多的时间和精力去研究。这时,你可以根据自己的情况,选择一批论文重点突破。
论文最后通常是评测和数据展示部分。这部分内容对我们最大的参考价值在于,**学习作者的评测方法、用到的测试工具和测试样例**,以便将其运用到工作中。
阅读完一篇论文后,如果你觉得内容还不错的话,可以通过 Google 学术去搜索相关的文章,找到所有引用这篇论文的新作品。这样一来,你就可以通过一篇经典论文不断深入,全面掌握一个领域。
最后,我希望你可以通过经典论文的助力,迅速建立起自己的知识武器库,来攻克日常工作中的难题。

View File

@@ -0,0 +1,10 @@
你好从12月18日更新结束语到今天我们一共收到了93位同学填写的问卷。在这里我首先要感谢各位同学给我们的反馈。当然这些反馈里有指出我们做得好的地方也有指出我们可以继续优化的地方。
本着“对专栏的改进最有帮助”的原则我们和聂鹏程老师一起从中挑选了5位用户送出“Git/Redis快捷口令超大鼠标垫”或者价值99元的极客时间课程阅码。中奖名单如下<br>
<img src="https://static001.geekbang.org/resource/image/85/90/85b77186fa961e250c685d5e495e6c90.jpg" alt=""><br>
感谢以上5位同学提出的宝贵意见也恭喜他们
当然,专栏的结束是另一种开始,我们会和聂老师继续迭代、优化专栏内容,聂老师也会持续关注并回复你的留言,所以也希望你可以继续关注本专栏,并将你的问题或者建议,通过留言反馈给我们!