reed solomon编码实践

2023-12-19 19:38
文章标签 实践 编码 reed solomon

本文主要是介绍reed solomon编码实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

如果大家对于raid原理有所了解的话,对于这个reed solomon(里德-所罗门码)编码就不陌生。下简单介绍原理
第一步先通过Vandermonde 矩阵编码,如下

这里写图片描述

这样原始的ABCD-MNOP的数据就被编码了。此时选用的parity格式是2,那么允许丢失2行数据,如下
这里写图片描述
现在通过对Vandermonde矩阵的逆矩阵相乘得到原始的数据,如下:
这里写图片描述

这个就是演示了一个数据恢复的原理了。
说完原理还是code实践一下吧,这个编码已经有大神实现了,拿来主义。reed-solomon
先看怎么编码:

func main() {// Parse command line parameters.flag.Parse()args := flag.Args()if len(args) != 1 {fmt.Fprintf(os.Stderr, "Error: No input filename given\n")flag.Usage()os.Exit(1)}if *dataShards > 257 {fmt.Fprintf(os.Stderr, "Error: Too many data shards\n")os.Exit(1)}fname := args[0]// Create encoding matrix.enc, err := reedsolomon.NewStream(*dataShards, *parShards)checkErr(err)fmt.Println("Opening", fname)f, err := os.Open(fname)checkErr(err)instat, err := f.Stat()checkErr(err)shards := *dataShards + *parShardsout := make([]*os.File, shards)// Create the resulting files.dir, file := filepath.Split(fname)if *outDir != "" {dir = *outDir}for i := range out {outfn := fmt.Sprintf("%s.%d", file, i)fmt.Println("Creating", outfn)out[i], err = os.Create(filepath.Join(dir, outfn))checkErr(err)}// Split into files.data := make([]io.Writer, *dataShards)for i := range data {data[i] = out[i]}// Do the spliterr = enc.Split(f, data, instat.Size())checkErr(err)// Close and re-open the files.input := make([]io.Reader, *dataShards)for i := range data {out[i].Close()f, err := os.Open(out[i].Name())checkErr(err)input[i] = fdefer f.Close()}// Create parity output writersparity := make([]io.Writer, *parShards)for i := range parity {parity[i] = out[*dataShards+i]defer out[*dataShards+i].Close()}// Encode parityerr = enc.Encode(input, parity)checkErr(err)fmt.Printf("File split into %d data + %d parity shards.\n", *dataShards, *parShards)}

先是打开原始文件,对数据进行分配,先enc.Split做数据切片,然后编码parity通过enc.Encode。我这里面制定4个分片和3个parity,结果如下:

Opening /mnt/download/kubernetes.tar.gz
Creating kubernetes.tar.gz.0
Creating kubernetes.tar.gz.1
Creating kubernetes.tar.gz.2
Creating kubernetes.tar.gz.3
Creating kubernetes.tar.gz.4
Creating kubernetes.tar.gz.5
Creating kubernetes.tar.gz.6
File split into 4 data + 3 parity shards.

当然删除任何3个都是可以恢复的

下面是decode代码

func main() {// Parse flagsflag.Parse()args := flag.Args()if len(args) != 1 {fmt.Fprintf(os.Stderr, "Error: No filenames given\n")flag.Usage()os.Exit(1)}fname := args[0]// Create matrixenc, err := reedsolomon.NewStream(*dataShards, *parShards)checkErr(err)// Open the inputsshards, size, err := openInput(*dataShards, *parShards, fname)checkErr(err)// Verify the shardsok, err := enc.Verify(shards)if ok {fmt.Println("No reconstruction needed")} else {fmt.Println("Verification failed. Reconstructing data")shards, size, err = openInput(*dataShards, *parShards, fname)checkErr(err)// Create out destination writersout := make([]io.Writer, len(shards))for i := range out {if shards[i] == nil {//dir, _ := filepath.Split(fname)outfn := fmt.Sprintf("%s.%d", fname, i)fmt.Println("Creating", outfn)out[i], err = os.Create(outfn)checkErr(err)}}fmt.Println("reconstruct")err = enc.Reconstruct(shards, out)if err != nil {fmt.Println("Reconstruct failed -", err)os.Exit(1)}// Close output.for i := range out {if out[i] != nil {err := out[i].(*os.File).Close()checkErr(err)}}shards, size, err = openInput(*dataShards, *parShards, fname)ok, err = enc.Verify(shards)if !ok {fmt.Println("Verification failed after reconstruction, data likely corrupted:", err)os.Exit(1)}checkErr(err)}// Join the shards and write themoutfn := *outFileif outfn == "" {outfn = fname}fmt.Println("Writing data to", outfn)f, err := os.Create(outfn)checkErr(err)shards, size, err = openInput(*dataShards, *parShards, fname)checkErr(err)// We don't know the exact filesize.err = enc.Join(f, shards, int64(*dataShards)*size)checkErr(err)
}func openInput(dataShards, parShards int, fname string) (r []io.Reader, size int64, err error) {// Create shards and load the data.shards := make([]io.Reader, dataShards+parShards)for i := range shards {infn := fmt.Sprintf("%s.%d", fname, i)fmt.Println("Opening", infn)f, err := os.Open(infn)if err != nil {fmt.Println("Error reading file", err)shards[i] = nilcontinue} else {shards[i] = f}stat, err := f.Stat()checkErr(err)if stat.Size() > 0 {size = stat.Size()} else {shards[i] = nil}}return shards, size, nil
}

这个里面获取到的分片,首先是检查Verify分片是否完整,如果不完整会重建Reconstruct。
下面是例子

rm -rf kubernetes.tar.gz.1
rm -rf kubernetes.tar.gz.3
rm -rf kubernetes.tar.gz.5Opening /mnt/download/kubernetes.tar.gz.0
Opening /mnt/download/kubernetes.tar.gz.1
Error reading file open /mnt/download/kubernetes.tar.gz.1: no such file or directory
Opening /mnt/download/kubernetes.tar.gz.2
Opening /mnt/download/kubernetes.tar.gz.3
Error reading file open /mnt/download/kubernetes.tar.gz.3: no such file or directory
Opening /mnt/download/kubernetes.tar.gz.4
Opening /mnt/download/kubernetes.tar.gz.5
Error reading file open /mnt/download/kubernetes.tar.gz.5: no such file or directory
Opening /mnt/download/kubernetes.tar.gz.6
Verification failed. Reconstructing data
Opening /mnt/download/kubernetes.tar.gz.0
Opening /mnt/download/kubernetes.tar.gz.1
Error reading file open /mnt/download/kubernetes.tar.gz.1: no such file or directory
Opening /mnt/download/kubernetes.tar.gz.2
Opening /mnt/download/kubernetes.tar.gz.3
Error reading file open /mnt/download/kubernetes.tar.gz.3: no such file or directory
Opening /mnt/download/kubernetes.tar.gz.4
Opening /mnt/download/kubernetes.tar.gz.5
Error reading file open /mnt/download/kubernetes.tar.gz.5: no such file or directory
Opening /mnt/download/kubernetes.tar.gz.6
Creating /mnt/download/kubernetes.tar.gz.1
Creating /mnt/download/kubernetes.tar.gz.3
Creating /mnt/download/kubernetes.tar.gz.5
reconstruct
Opening /mnt/download/kubernetes.tar.gz.0
Opening /mnt/download/kubernetes.tar.gz.1
Opening /mnt/download/kubernetes.tar.gz.2
Opening /mnt/download/kubernetes.tar.gz.3
Opening /mnt/download/kubernetes.tar.gz.4
Opening /mnt/download/kubernetes.tar.gz.5
Opening /mnt/download/kubernetes.tar.gz.6
Writing data to /mnt/download/kubernetes.tar.gz
Opening /mnt/download/kubernetes.tar.gz.0
Opening /mnt/download/kubernetes.tar.gz.1
Opening /mnt/download/kubernetes.tar.gz.2
Opening /mnt/download/kubernetes.tar.gz.3
Opening /mnt/download/kubernetes.tar.gz.4
Opening /mnt/download/kubernetes.tar.gz.5
Opening /mnt/download/kubernetes.tar.gz.6

当decode的时候回重建数据。之所以介绍这个编码,是为后续编写对象存储做理论基础。

这篇关于reed solomon编码实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/513449

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

form表单提交编码的问题

浏览器在form提交后,会生成一个HTTP的头部信息"content-type",标准规定其形式为Content-type: application/x-www-form-urlencoded; charset=UTF-8        那么我们如果需要修改编码,不使用默认的,那么可以如下这样操作修改编码,来满足需求: hmtl代码:   <meta http-equiv="Conte

Prometheus与Grafana在DevOps中的应用与最佳实践

Prometheus 与 Grafana 在 DevOps 中的应用与最佳实践 随着 DevOps 文化和实践的普及,监控和可视化工具已成为 DevOps 工具链中不可或缺的部分。Prometheus 和 Grafana 是其中最受欢迎的开源监控解决方案之一,它们的结合能够为系统和应用程序提供全面的监控、告警和可视化展示。本篇文章将详细探讨 Prometheus 和 Grafana 在 DevO

springboot整合swagger2之最佳实践

来源:https://blog.lqdev.cn/2018/07/21/springboot/chapter-ten/ Swagger是一款RESTful接口的文档在线自动生成、功能测试功能框架。 一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,加上swagger-ui,可以有很好的呈现。 SpringBoot集成 pom <!--swagge

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

【HarmonyOS】-TaskPool和Worker的对比实践

ArkTS提供了TaskPool与Worker两种多线程并发方案,下面我们将从其工作原理、使用效果对比两种方案的差异,进而选择适用于ArkTS图片编辑场景的并发方案。 TaskPool与Worker工作原理 TaskPool与Worker两种多线程并发能力均是基于 Actor并发模型实现的。Worker主、子线程通过收发消息进行通信;TaskPool基于Worker做了更多场景化的功能封装,例

vue2实践:第一个非正规的自定义组件-动态表单对话框

前言 vue一个很重要的概念就是组件,作为一个没有经历过前几代前端开发的我来说,不太能理解它所带来的“进步”,但是,将它与后端c++、java类比,我感觉,组件就像是这些语言中的类和对象的概念,通过封装好的组件(类),可以通过挂载的方式,非常方便的调用其提供的功能,而不必重新写一遍实现逻辑。 我们常用的element UI就是由饿了么所提供的组件库,但是在项目开发中,我们可能还需要额外地定义一