例如 userA 添加了1 GB的文件。 IPFS add file.txt
和 userB 通过IPFS将该文件存入其存储空间。后来 userA 发布了一个错误,只更改了该文件中的一个字符,并希望与 userB 共享此更新版本。
所以 userA 再次添加了相同的文件,通过ipfs add file
对IPFS进行了少量更改, userB 必须获取1 GB的文件,而不是更新单个字符。有没有更好的方法来解决这个问题,只有更新版本应由 userB 提取,就像我们git pull
时git的工作方式一样?
Git有更好的方法,请参阅(https://stackoverflow.com/a/8198276/2402577)。 IPFS是否像Git一样使用增量压缩进行存储(https://gist.github.com/matthewmccullough/2695758)?或类似的方法?
进一步调查:
我做了一个小实验。 首先,我将1GB文件添加到IPFS中。后来,我在文件上更新了一个小行,已经通过IPFS共享了。我观察到 userA 再次推送完整的1GB文件,而只是推送包含已更改数据的块。在我看来,这是非常昂贵和耗时的。我已经共享了新更新文件的哈希值,并且再次通过 userB 上的IPFS下载完整文件,而不是仅下载包含已更改字符的块。
用户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
用户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
[问] 此时,通过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
分析:
两者(更新文件和原始文件)在回购邮件大小上都有相同的增加:
首先我创建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.更改回购物大小(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个,所以它添加了完整的文件,更改了回购大小(38823)
$ ipfs repo stat
NumObjects: 5311
RepoSize: 181428647
StorageMax: 10000000000
RepoPath: /home/alper/.ipfs
Version: fs-repo@6
答案 0 :(得分:1)
IPFS当前尚不支持您所描述的方案,因为文件是通过其内容的哈希值编制索引的。在某些情况下,尽管由于文件分解成块的方式而导致此操作“意外”发生。如果更改发生在文件的末尾,则文件的开头可能具有与传输的“块”相同的散列。
可以分析当前存储的数据,并查看是否已经有一些可用于该块的数据(这与rsync的实现方法类似,尽管它使用了为此目的设计的校验和算法)过程)
答案 1 :(得分:1)
IPFS支持Rabin分块,这是一种将大文件分解为块的神奇方法,在该块中,块边界发生在任何相同数据序列的相同位置,而与该数据的对齐方式无关。这意味着块大小是可变的,并且在大文件的开头添加单个字节通常会导致第一个块大一个字节,而所有其他块都相同。
因此rabin块化将使IPFS只需很小的更改即可有效地重用大型文件中的块。
但是,您还应该知道,诸如压缩之类的事情通常意味着输入文件中的单个字节更改会导致压缩输出文件中的几乎每个字节更改。这意味着,无论您如何分块,压缩文件中的微小更改通常都不会包含任何可重用的块。
这就是为什么rsync通常无法有效地更新* .gz文件的原因。但是,gzip具有--rsyncable
选项,该选项将牺牲少量压缩以最小化压缩输出中的更改。有趣的是,它使用了与Rabin块非常相似的东西,但我认为它早于Rabin。将gzip --rsyncable
用于使用Rabin分块添加到IPFS的压缩文件将导致与其他类似压缩/添加但略有不同的文件共享块。
答案 2 :(得分:0)
IPFS中的文件是内容寻址且不可变的,编辑起来可能很复杂。但是有MFS(可变文件系统)可用于处理文件,就像处理普通的基于名称的文件系统一样-您可以添加,删除,移动和编辑MFS文件,并为您完成所有更新链接和哈希的工作。