纠删码的原理介绍可以参考:
https://www.jianshu.com/p/4abf65ad03af
一般上我们如果要保证数据高可用,主流的有两种策略:
- 多副本
- 纠删码
副本(Replication)策略:
副本,实打实的复制,常见的是三副本,意味着现实世界有三份一样的数据。代价稍高,偏计算类的场景基本都会用该策略,比如虚拟机VM、数据库。如果一个副本挂了,马上切到另外一个,漂移时间非常短。n副本存储效率永远是 1 / n 1/n 1/n。
纠删码(Erasure Code)策略:
纠删码,会把数据进行切分,同时计算校验块。以常见的reedsolomon(RS)纠删码为例,在6数据块+3校验块的情景,可以允许3个块(任意数据块+校验块数量之和为3)损坏。在偏纯存储的场景会用到,例如对象存储。n数据块+m校验块的纠删码配置,存储效率是n/n+m, 但是在重构(Reconstruct)的时候,需要消耗cpu资源,而且有一定延时
golang reedsolomon
minio是一个对象存储服务,存储考虑的是低成本+高可用,其纠删码使用的是RS纠删码,对应的github仓库是
github.com/klauspost/reedsolomon
单核恢复能力超过1GB/s, 特定平台可以通过指令加速。
这个repo的文档比较完善,api的操作具体可以看文档。下面来做一个简单的验证
进入examples目录
$ go build simple-encoder.go && go build simple-decoder.go && rm *.go
$ ls
README.md simple-decoder simple-encoder
首先,以Readme.md为目标,执行encode操作,这一步是为了把文件分割成数据块+校验块
$ md5sum README.md
0076c987f6cc5e98919b0b9403b12b5f README.md
$ mkdir data && cd data
$ ../simple-encoder -out . ../README.md
Opening ../README.md
File split into 6 data+parity shards with 358 bytes/shard.
Writing to README.md.0
Writing to README.md.1
Writing to README.md.2
Writing to README.md.3
Writing to README.md.4
Writing to README.md.5
$ ls
README.md.0 README.md.1 README.md.2 README.md.3 README.md.4 README.md.5
simple-encoder 使用的是4数据块+2校验块的配置,一共会生成6个文件
这个时候我们删除2个数据块,看能否恢复
$ ../simple-decoder -out ./README.md.reconstruct README.md
Opening README.md.0
Error reading file open README.md.0: no such file or directory
Opening README.md.1
Error reading file open README.md.1: no such file or directory
Opening README.md.2
Opening README.md.3
Opening README.md.4
Opening README.md.5
Verification failed. Reconstructing data
Writing data to ./README.md.reconstruct
$ md5sum README.md.reconstruct
0076c987f6cc5e98919b0b9403b12b5f README.md.reconstrut
md5sum 的结果显示,重构后的文件与源文件一致。