IPFS 原理与实践 (24):IPFS 底层基础 2.3

阅读数:1 2019 年 12 月 21 日 18:57

IPFS原理与实践(24):IPFS底层基础 2.3

(版本控制(Git))

内容简介
这是一部从实现原理和工程实践两个维度深入讲解 IPFS 和 Filecoin 的著作。作者是中文社区内非常有影响力的三位 IPFS/Filecoin 布道者,本书得到了 IPFS&FileCoin 创始人以及 IPFS 官方(协议实验室)的高度认可和强烈推荐。
为 * 大化满足读者需求,书中不仅介绍 IPFS 技术细节、区块链相关知识、Filecoin 项目技术细节,还加入了大量作者们在开发中的经验和技巧。为了适配当下及未来较长时间内读者的实际使用环境,书中所有案例都是基于生态链中较新的软件开发工具和前沿的软件开发技术编写的。
本书分为三大部分:
第一部分 基础篇(第 1 章)
全面介绍了 IPFS 的源起,概念、优势和应用领域,旨在帮助读者了解 IPFS 相关基础背景知识,从宏观层面认识 IPFS 技术所具有的创新性。
第二部分 原理篇(第 2~5 章)
旨在帮助读者深入理解 IPFS 和 Filecoin 的运行原理与工作机制。首先深入分析了分布式哈希表、块交换协议、版本控制、自验证文件系统 Merkle DAG 和 Merkle Tree 等底层基础知识,然后对 IPFS 协议栈中包含的 7 层子协议了进行了剖析,接着解析了 Multi-Format、libp2p、IPLD 三大 IPFS 核心模块,最后用了一整章的篇幅详细剖析了 Filecoin 项目。
第三部分 实战篇(第 6~8 章)
以工程化的方式,从基础至进阶,介绍了 IPFS 技术的实际使用,包括安装、配置、交互、入网、API、内容发布、数据保存、私网搭建等内容,之后通过两个不同风格的实际项目案例向读者展示了基于不同语言所实现的 IPFS 协议栈的使用方法。

  1. 版本控制类型

版本控制系统是用于记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。例如我们在做开发时,版本控制系统会帮我们实现对每一次修改的备份,可以方便地回到之前的任意一个版本。实现版本控制的软件有很多种类,大致可以分为三类:本地版本控制系统、中心化版本控制系统、分布式版本控制系统。

(1)本地版本控制系统

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单,但是特别容易犯错。有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖其他文件。为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。

其中最流行的一种称为 RCS,现今许多计算机系统上都还能看到它的踪影。甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 RCS 命令。它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。

(2)中心化版本控制系统

接下来人们又遇到一个问题:如何让不同系统上的开发者协同工作?于是,中心化版本控制系统(Centralized Version Control Systems,CVCS)应运而生,如图 2-3 所示。这类系统,诸如 CVS、Subversion 及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-3 中心化版本控制系统

这种做法带来了许多好处,特别是相较于老式的本地 VCS 有优势。每个人都可以在一定程度上看到项目中的其他人正在做些什么,而管理员也可以轻松掌控每个开发者的权限。并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。这种方案最显而易见的缺点是中央服务器的单点故障。如果中央服务器宕机 1 小时,那么在这 1 小时内,谁都无法提交更新,也就无法协同工作。如果中心数据库所在的磁盘发生损坏,又没有及时做备份,毫无疑问你将丢失所有数据,包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

(3)分布式版本控制系统

为了避免中心化版本控制系统单点故障的风险,分布式版本控制系统(Distributed Version Control System,DVCS)面世了。这类系统有 Git、Mercurial、Bazaar 及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。它的系统架构如图 2-4 所示。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-4 分布式版本控制

更进一步,许多这类系统都可以指定与若干不同的远端代码仓库进行交互。借此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

  1. 快照流

Git 和其他版本控制系统的主要差别在于 Git 保存数据的方法。从概念上来区分,其他大部分系统以文件变更列表的方式存储信息,这类系统(CVS、Subversion、Perforce、Bazaar 等)将它们保存的信息看作一组随时间逐步累积的文件差异关系,如图 2-5 所示。

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-5 每个文件与初始版本的差异

Git 不按照以上方式保存数据。反之,Git 更像把数据看作对小型文件系统的一组快照,如用 2-6 所示。每次你提交更新或在 Git 中保存项目状态时,它将为全部文件生成一个快照并保存这个快照的索引。为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。Git 保存数据的方式更像是一个快照流。

Git 存储的是数据随时间改变的快照。

这是 Git 与其他版本控制系统的重要区别。因此 Git 综合考虑了以前每一代版本控制系统延续下来的问题。Git 更像一个小型的文件系统,提供了许多以此为基础构建的优秀工具,而不只是一个简单的版本控制系统。稍后我们在讨论 Git 分支管理时,将探究这种方式带来的好处。

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-6 文件快照存储
  1. 本地执行操作

在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其他计算机的信息。相比于中心化版本控制系统严重的网络延时,在本地加载 Git 要快许多。因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间就完成了。

举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来,它只需直接从本地数据库中读取,你就能立即看到项目历史。如果你想查看当前版本与一个月前的版本之间引入的修改,Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再在本地处理。

这也意味着当你处于离线状态时,也可以进行几乎所有的操作。比如:在飞机或火车上想做些工作,你能愉快地提交,直到有网络连接时再上传;回家后 VPN 客户端不正常,你仍能工作。而使用其他系统,做到如此是不可能的或很费力的。比如,用 Perforce,你没有连接服务器时几乎不能做任何事;用 Subversion 和 CVS,你能修改文件,但不能向数据库提交修改(因为你的本地数据库离线了)。这看起来不是大问题,但是你可能会惊喜地发现它带来的巨大的不同。

  1. 只添加数据

我们所执行的 Git 操作,本质都是在 Git 数据库中增加操作数据。Git 上的操作几乎都是可逆的。同其他 VCS 一样,未提交更新将有可能丢失或弄乱修改的内容;一旦你将修改快照提交到 Git 系统中,就难再丢失数据。这使得 Git 在版本控制领域成为一个非常优秀的工具,因为我们可以尽情做各种修改尝试,而仍有回流的机会。

  1. 完整性校验

Git 中所有数据在存储前都会计算校验和,然后以校验和来引用。这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。这个功能由 Git 在底层实现。若你在编辑过程中丢失信息或损坏文件,Git 就能发现。

Git 用以计算校验的哈希算法是 SHA-1。Git 会将文件的内容或目录结构一同计算,得出它们的哈希值,确保文件和路径的完整性。Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引的,而不是文件名。

  1. 工作区与工作状态

Git 有 3 种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。已提交表示数据已经安全地保存在本地数据库中;已修改表示修改了文件,但还没保存到数据库中;已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

由此引入 Git 项目的 3 个工作区域的概念:工作目录、Git 仓库及暂存区域。Git 仓库包括本地仓库和远程仓库。

1)工作目录:直接编辑修改的目录。工作目录是将项目中某个版本独立提取出来的内容放在磁盘上供你使用或修改。

2)Git 仓库:保存项目的元数据和对象数据库。这是 Git 中最重要的部分,从其他计算机复制仓库时,复制的就是这里的数据。

3)暂存区域:是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库中。有时候也被称作“索引”,不过一般还是叫暂存区域。

定义了这 3 个工作区域,工作流程就很清晰了。基本的 Git 工作流程如下:

1)在工作目录中修改文件。

2)暂存文件,将文件的快照放入暂存区域。

3)提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库。

如果 Git 仓库中保存着的特定版本文件,就属于已提交状态。如果做了修改并已放入暂存区域,就属于已暂存状态。如果自上次取出后,做了修改但还没有放到暂存区域,就是已修改状态。

  1. 分支

为了理解 Git 分支的实现方式,我们需要回顾一下 Git 是如何储存数据的。Git 保存的不是文件差异或者变化量,而是一系列文件快照。在 Git 中提交时,会保存一个提交(commit)对象,该对象包含一个指向暂存内容快照的指针,包含本次提交的作者等相关附属信息,包含零个或多个指向该提交对象的父对象指针:首次提交是没有直接祖先的,普通提交有一个祖先,由两个或多个分支合并产生的提交则有多个祖先。

为直观起见,我们假设在工作目录中有 3 个文件,准备将它们暂存后提交。暂存操作会对每一个文件计算校验和,然后把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 类型的对象存储这些快照),并将校验和加入暂存区域。

复制代码
$ git add README test.rb LICENSE
$ git commit -m 'initial commit of my project'

当使用 git commit 新建一个提交对象前,Git 会先计算每一个子目录(本例中就是项目根目录)的校验和,然后在 Git 仓库中将这些目录保存为树(tree)对象。之后 Git 创建的提交对象,除了包含相关提交信息以外,还包含着指向这个树对象(项目根目录)的指针,如此它就可以在将来需要的时候,重现此次快照的内容了。

现在,Git 仓库中有 5 个对象:3 个表示文件快照内容的 blob 对象;1 个记录着目录树内容及其中各个文件对应 blob 对象索引的 tree 对象;以及 1 个包含指向 tree 对象(根目录)的索引和其他提交信息元数据的 commit 对象。概念上来说,仓库中的各个对象保存的数据和相互关系看起来如图 2-7 所示。

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-7 单一提交对象的数据结构

做些修改后再次提交,那么这次的提交对象会包含一个指向上次提交对象的指针。两次提交后,仓库历史会变成图 2-8 所示的样子。

现在来谈分支。Git 中的分支本质上仅是个指向 commit 对象的可变指针。Git 使用 master 作为分支的默认名字。第一个分支也常被称为主干。主干可被克隆为其他分支,每条分支的可变指针在每次提交时都会自动向前移动,如图 2-9 所示。

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-8 多个提交对象之间的链接关系

IPFS原理与实践(24):IPFS底层基础 2.3

图 2-9 分支中的历史提交

IPFS原理与实践(24):IPFS底层基础 2.3

购书地址 https://item.jd.com/12665074.html?dist=jd

评论

发布