2

2019 年 10 月 30 日更新:

=> 请参阅以下讨论以了解对 IPFS 的功能请求:git-diff 功能:提高 IPFS 共享更新文件的效率。减少文件/块重复

=> 请参阅以下讨论以获取更多信息。IPFS 是否提供块级文件复制功能?


例如userA添加了一个大小为 1 GB 的文件。IPFS add file.txtuserB通过 IPFS 将该文件放入他的存储中后来userA发布了一个错误,只更改了文件中的一个字符,并希望与userB共享这个更新版本。

因此,用户 A再次通过 将相同的文件添加到 IPFS 中ipfs add file,而用户B 必须获取该 1 GB 的文件,而不是更新该单个字符。有没有更好的方法来解决这个问题,只有更新的版本应该由userB提取,就像我们 git 的工作方式一样git pull

Git 有更好的方法,请参阅(https://stackoverflow.com/a/8198276/2402577)。IPFS 是否像 Git 一样使用增量压缩进行存储( https://gist.github.com/matthewmccullough/2695758 )?或类似的方法?

进一步的调查:

我做了一个小实验。首先,我在 IPFS 中添加了 1GB 文件。后来,我更新了文件上的一小行,它已经通过 IPFS 共享。我观察到userA再次推送完整的 1GB 文件,而不是只推送包含更改数据的块。在我看来,这是非常昂贵和耗时的。我已经共享了新更新文件的哈希值,并再次通过用户 B 上的 IPFS 下载完整文件,不是仅下载包含更改字符的块。

  • 步骤1:

用户A

$ fallocate -l 1G gentoo_root.img
$ ipfs add gentoo_root.img
 920.75 MB / 1024.00 MB [========================================>----]  89. 92added QmdiETTY5fiwTkJeERbWAbPKtzcyjzMEJTJJosrqo2qKNm gentoo_root.img

用户B

$ ipfs get QmdiETTY5fiwTkJeERbWAbPKtzcyjzMEJTJJosrqo2qKNm
Saving file(s) to QmdiETTY5fiwTkJeERbWAbPKtzcyjzMEJTJJosrqo2qKNm
 1.00 GB / 1.00 GB [==================================] 100.00% 49s

  • 第2步:

用户A

$ echo 'hello' >> gentoo_root.img
$  ipfs add gentoo_root.img   # HERE node pushing 1 GB file into IPFS again. It took 1 hour for me to push it, instead only updated the changed block.
32.75 MB / 1.00 GB [=>---------------------------------------]   3.20% 1h3m34s
added Qmew8yVjNzs2r54Ti6R64W9psxYFd16X3yNY28gZS4YeM3 gentoo_root.img

用户B

# HERE complete 1 GB file is downloaded all over again.
ipfs get Qmew8yVjNzs2r54Ti6R64W9psxYFd16X3yNY28gZS4YeM3
[sudo] password for alper:
Saving file(s) to Qmew8yVjNzs2r54Ti6R64W9psxYFd16X3yNY28gZS4YeM3
 1.00 GB / 1.00 GB [=========================] 100.00% 45s

[Q]此时,通过 IPFS 共享更新文件而不重新共享更新文件的整个版本以及 IPFS 仅共享文件的更新块的最佳解决方案是什么?


在此之上; 每当我这样做时,都在同一个节点上ipfs cat <hash>保持下载相同的哈希值。

$ ipfs cat Qmew8yVjNzs2r54Ti6R64W9psxYFd16X3yNY28gZS4YeM3
 212.46 MB / 1.00 GB [===========>---------------------------------------------]  20.75% 1m48s

$ ipfs cat Qmew8yVjNzs2r54Ti6R64W9psxYFd16X3yNY28gZS4YeM3
 212.46 MB / 1.00 GB [===========>---------------------------------------------]  20.75% 1m48s

分析:

两者(更新文件和原始文件)在 repo 大小上都有相同的增加:

首先我创建 100 MB 文件(file.txt)

NumObjects: 5303
RepoSize:   181351841
StorageMax: 10000000000
RepoPath:   /home/alper/.ipfs
Version:    fs-repo@6

   $ ipfs add file.txt
   added QmZ33LSByGsKQS8YRW4yKjXLUam2cPP2V2g4PVPVwymY16 file.txt
   $ ipfs pin add QmZ33LSByGsKQS8YRW4yKjXLUam2cPP2V2g4PVPVwymY16

这里的对象数量增加了 4. 更改了 repo 大小 (37983)

$ ipfs repo stat
NumObjects: 5307
RepoSize:   181389824
StorageMax: 10000000000
RepoPath:   /home/alper/.ipfs
Version:    fs-repo@6

比我echo 'a' >> file.txt 那时 ipfs add file.txt

在这里,我观察到对象数量增加了 4 个,因此它添加了完整的文件,更改了 repo 大小(38823)

$ ipfs repo stat
NumObjects: 5311
RepoSize:   181428647
StorageMax: 10000000000
RepoPath:   /home/alper/.ipfs
Version:    fs-repo@6
4

3 回答 3

3

IPFS 当前不支持您所描述的场景,因为文件是通过其内容的哈希来索引的。尽管由于文件被分解成块的方式,在某些情况下这会“意外地”起作用。如果更改发生在文件末尾,则文件开头可能具有与传输的“块”相同的哈希值。

可以分析当前存储的数据,看看您是否已经有可以用于块的东西(这与 rsync 实现这一点的方法类似,尽管它使用了为该过程设计的校验和算法)

于 2018-09-09T15:34:24.950 回答
2

IPFS 支持 rabin 分块,这是一种将大文件分成块的神奇方法,其中块边界发生在任何相同数据序列中的相同位置,而不管该数据的对齐方式。这意味着块大小是可变的,在大文件的开头添加一个字节通常会导致第一个块大一个字节,而所有其他块都相同。

因此,rabin 分块将导致 IPFS 有效地重用大文件中的块,只需进行少量更改。

但是,您还应该知道,压缩之类的事情通常意味着输入文件中的单个字节更改会导致压缩输出文件中的几乎每个字节都更改。这意味着压缩文件中的微小更改通常不会有任何可重用的块,无论您如何对它们进行分块。

这就是为什么 rsync 通常不能有效地更新 *.gz 文件。然而 gzip 有一个--rsyncable选项会牺牲少量的压缩来最小化压缩输出的变化。有趣的是,它使用了与 rabin 分块非常相似的东西,但我认为它早于 rabin。用于使用gzip --rsyncablerabin 分块添加到 IPFS 的压缩文件将导致与其他类似压缩/添加但略有不同的文件共享块。

于 2019-10-31T12:26:31.840 回答
0

IPFS 中的文件是内容寻址且不可变的,它们可能难以编辑。但是有 MFS(可变文件系统)可以像处理普通的基于名称的文件系统一样处理文件——您可以添加、删除、移动, 并编辑 MFS 文件,并为您处理更新链接和哈希的所有工作。

于 2019-08-14T09:02:45.050 回答