reedsolomon

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2025 License: MIT Imports: 12 Imported by: 0

README

Reed-Solomon 16 (GF(2^16))

English | 中文

Reed-Solomon 16 (GF(2^16)) - 中文说明

Reed-Solomon 16 是一个基于快速傅里叶变换(FFT)的 GF(2^16) Reed-Solomon 编码库,专为大规模分布式存储系统设计。本实现采用创新算法和优化技术,克服了传统GF(2^16)实现的内存和性能瓶颈。

主要优势

┌────────────────────────────┐  ┌────────────────────────────┐
│         性能提升           │  │         内存优化           │
│                            │  │                            │
│ GF(2^8):  O(n²)           │  │ 传统GF(2^16): ~8GB内存     │
│    ↓                       │  │    ↓                       │
│ GF(2^16)+FFT: O(n log n)  │  │ 我们的实现:  <100MB内存    │
└────────────────────────────┘  └────────────────────────────┘
  • 突破内存限制:传统GF(2^16)实现需要存储完整乘法表,占用约8GB内存;我们的实现通过FFT优化算法,仅需<100MB内存
  • 高效算法:基于基数-4和基数-8 FFT实现,将计算复杂度从O(n²)降低到O(n log n)
  • 自适应处理:能够智能处理非2的幂次大小的数据,无需用户担心填充问题
  • 汇编优化:关键路径使用汇编优化,性能提升3-5倍
  • 可扩展性:支持高达65535个分片,远超GF(2^8)的255个分片限制

工作流程

             ┌───────────────┐
原始数据 ───→│  数据分片(k)  │
             └───────┬───────┘
                     │
                     ▼
             ┌───────────────┐
             │  编码运算(n)  │───→ 校验分片(n-k)
             └───────┬───────┘
                     │
         ┌───────────┴───────────┐
         │                       │
         ▼                       ▼
┌─────────────────┐     ┌─────────────────┐
│  分布式存储/传输 │ ←─→ │   分片丢失/损坏  │
└────────┬────────┘     └────────┬────────┘
         │                       │
         └───────────┬───────────┘
                     │
                     ▼
             ┌───────────────┐
             │ 重建丢失分片  │
             └───────┬───────┘
                     │
                     ▼
             ┌───────────────┐
             │   数据恢复    │───→ 完整原始数据
             └───────────────┘

特点

  • 基于 GF(2^16) 实现,支持高达 65536 个分片
  • 采用快速傅里叶变换(FFT)技术,显著降低编码/解码复杂度
  • 针对大规模数据优化,处理速度可媲美专用硬件
  • 支持高效流式处理,适用于 PB 级数据
  • 纯 Go 实现,同时提供多架构优化

数据分片和重建示意图

┌─────────────────────────────────────────────────────────┐
│                     原始数据 (1MB)                       │
└─────────────────────────────────────────────────────────┘
         ↓         ↓         ↓         ↓         ↓
┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
│ 数据分片0│  │ 数据分片1│  │ 数据分片2│  │ 数据分片3│  │ 数据分片4│
│  (200KB) │  │  (200KB) │  │  (200KB) │  │  (200KB) │  │  (200KB) │
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘
                                                        ↓
                       Reed-Solomon 编码                 ↓
                              ↓                         ↓
┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
│ 校验分片0│  │ 校验分片1│  │ 校验分片2│  │ 校验分片3│  │ 校验分片4│
│  (200KB) │  │  (200KB) │  │  (200KB) │  │  (200KB) │  │  (200KB) │
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘

              ↓         ↓    某些分片丢失    ↓         ↓
┌─────────┐  ┌─────────┐     ┌─────────┐     ┌─────────┐  ┌─────────┐
│ 数据分片0│  │    X    │     │ 数据分片2│     │    X    │  │ 数据分片4│
└─────────┘  └─────────┘     └─────────┘     └─────────┘  └─────────┘
┌─────────┐  ┌─────────┐     ┌─────────┐     ┌─────────┐  ┌─────────┐
│ 校验分片0│  │ 校验分片1│     │    X    │     │ 校验分片3│  │    X    │
└─────────┘  └─────────┘     └─────────┘     └─────────┘  └─────────┘

                         重建算法 (解码)
                              ↓
┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
│ 数据分片0│  │ 数据分片1│  │ 数据分片2│  │ 数据分片3│  │ 数据分片4│  
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘
         ↓         ↓         ↓         ↓         ↓
┌─────────────────────────────────────────────────────────┐
│                  恢复的原始数据 (1MB)                    │
└─────────────────────────────────────────────────────────┘

容错能力图示

┌──────────────────────────────────────────────────────────────┐
│                         容错能力示例                          │
├───────────────┬─────────────────────────┬────────────────────┤
│   配置参数    │        分片状态         │      恢复结果      │
├───────────────┼─────────────────────────┼────────────────────┤
│               │  ■ ■ ■ ■ ■ ■ ■ ■ ■ ■   │                    │
│  10+2 (10%)   │  □ □                    │       ✓ 可恢复     │
│               │                         │                    │
├───────────────┼─────────────────────────┼────────────────────┤
│               │  ■ ■ ■ ■ ■ ■ ■ ■ ■ ■   │                    │
│  10+2 (10%)   │  □ □ □                  │       ✗ 无法恢复   │
│               │                         │                    │
├───────────────┼─────────────────────────┼────────────────────┤
│               │  ■ ■ ■ ■ ■ ■ ■ ■       │                    │
│   8+4 (50%)   │  □ □ □ □                │       ✓ 可恢复     │
│               │                         │                    │
├───────────────┼─────────────────────────┼────────────────────┤
│               │  ■ ■ ■ ■ ■ ■           │                    │
│   6+6 (100%)  │  □ □ □ □ □ □            │       ✓ 可恢复     │
│               │                         │                    │
└───────────────┴─────────────────────────┴────────────────────┘
  ■ - 可用分片   □ - 丢失分片

性能对比

指标 GF(2^8)传统实现 GF(2^16)传统实现 我们的FFT实现
最大分片数 255 65535 65535
内存占用 ~64KB ~8GB <100MB
编码速度(10GB数据) 基准 N/A(内存限制) 2-3倍速
大数据适应性 中等 优秀
算法复杂度 O(n²) O(n²) O(n log n)

填充机制优化

我们的实现针对FFT算法要求,采用了智能填充策略:

输入数据 ──┬─► 小数据(<8KB) ────► 直接填充到2的幂次
          │
          ├─► 中等数据 ───────► 优化分块处理
          │
          └─► 大数据(>1MB) ───► 固定大小分块处理
  • 智能填充:只在必要时填充到2的幂次大小
  • 分块处理:大数据使用分块处理,避免过度内存使用
  • 并行计算:自动利用多核处理器加速计算
  • 结果还原:处理完后自动移除填充数据

架构

库的主要组件包括:

┌───────────────────────────────────────────────────────────────────────┐
│                         Reed-Solomon 16 架构                           │
├───────────────────┬───────────────────────────┬───────────────────────┤
│                   │                           │                       │
│  ┌─────────────┐  │  ┌─────────────────────┐  │  ┌─────────────────┐  │
│  │ 编码引擎    │  │  │ FFT处理器           │  │  │ 流处理器        │  │
│  │             │◄─┼─►│                     │◄─┼─►│                 │  │
│  │ ・编码      │  │  │ ・多项式乘法        │  │  │ ・大文件处理    │  │
│  │ ・解码      │  │  │ ・插值计算          │  │  │ ・分段传输      │  │
│  │ ・重建      │  │  │ ・变换优化          │  │  │ ・内存优化      │  │
│  └─────────────┘  │  └─────────────────────┘  │  └─────────────────┘  │
│         ▲         │             ▲              │           ▲           │
│         │         │             │              │           │           │
│         └─────────┼─────────────┼──────────────┼───────────┘           │
│                   │             │              │                       │
│                   │  ┌──────────▼──────────┐   │                       │
│                   │  │ GF(2^16)运算引擎    │   │                       │
│                   │  │                     │   │                       │
│                   │  │ ・基本算术运算      │   │                       │
│                   │  │ ・多项式运算        │   │                       │
│                   │  │ ・查表优化          │   │                       │
│                   │  └─────────────────────┘   │                       │
│                   │                           │                       │
└───────────────────┴───────────────────────────┴───────────────────────┘
  • GF(2^16) 运算引擎:实现在有限域 GF(2^16) 上的算术运算
  • FFT 处理器:实现快速傅里叶变换算法,优化多项式计算
  • 编码引擎:执行编码和解码操作
  • 流处理器:支持大型数据流的分片和重建

目录结构

reedsolomon16/
├── DESIGN.md        - 详细设计文档
├── README.md        - 项目介绍
├── reedsolomon16.go - 核心接口和实现
├── options.go       - 配置选项
├── fft/             - FFT 算法实现
├── gf16/            - GF(2^16) 有限域运算
│   ├── galois16.go        - 基本运算
│   ├── galois16_amd64.go  - AMD64架构接口
│   └── galois16_amd64.s   - AMD64汇编优化
└── encode/          - 编码器实现
└── stream/          - 流式处理接口和实现
├── examples/        - 使用示例

与 reedsolomon 的比较

与原始的 reedsolomon 库相比,reedsolomon16 主要有以下区别:

  1. 使用 GF(2^16) 而非 GF(2^8),支持更多分片
  2. 使用 FFT 替代传统矩阵运算,算法复杂度从 O(n²) 降低到 O(n log n)
  3. 针对超大规模分布式存储系统优化
  4. 内存使用更加高效,避免了大型乘法表的使用
  5. 优化的非2的幂次数据处理机制,自动适应各种数据大小

适用场景

  • 超大规模分布式存储系统:支持更多的存储节点和更复杂的容错策略
  • 高可靠数据传输:如卫星通信、深空通信,需要强大的纠错能力
  • 企业级数据备份和灾难恢复:更高效地处理PB级数据
  • 多层数据保护系统:复杂的数据保护需求下,支持更多灵活的配置
  • 高性能计算环境:需要高吞吐量的数据校验和恢复

实现技术亮点

┌─────────────────────────────────────────────────────────┐
│                     技术创新点                          │
├─────────────────┬─────────────────┬─────────────────────┤
│ 基数-4/8 FFT    │ 优化内存管理    │ 汇编关键路径优化    │
├─────────────────┼─────────────────┼─────────────────────┤
│ 自适应分块      │ 并行处理策略    │ 智能填充机制        │
└─────────────────┴─────────────────┴─────────────────────┘

快速开始

详细使用示例:在examples目录下提供了完整的示例代码,包括基本用法、流式处理和高级选项。如需详细了解,请参考示例文档

安装
go get github.com/bpfs/reedsolomon16
基本概念

Reed-Solomon编码将数据分成多个分片(shards),并生成额外的奇偶校验分片。即使部分分片丢失或损坏,也能使用剩余的分片重建完整数据。

  • 数据分片:原始数据被分割成的多个部分
  • 奇偶校验分片:通过编码生成的冗余数据
  • 总分片数:数据分片数 + 奇偶校验分片数
基本使用示例

以下是一个简单的使用示例,展示基本的编码和恢复流程:

// 创建编码器 (4个数据分片,2个校验分片)
enc, err := rs.New(4, 2)
if err != nil {
    log.Fatal(err)
}

// 分割数据为分片
shards, err := enc.Split(data)
if err != nil {
    log.Fatal(err)
}

// 编码(生成校验分片)
err = enc.Encode(shards)
if err != nil {
    log.Fatal(err)
}

// 模拟丢失分片
shards[1] = nil  // 丢失一个数据分片
shards[4] = nil  // 丢失一个校验分片

// 重建丢失的分片
err = enc.Reconstruct(shards)
if err != nil {
    log.Fatal(err)
}

// 合并分片恢复原始数据
var buf bytes.Buffer
err = enc.Join(&buf, shards, len(data))
可用API

库提供了以下核心API:

  1. 创建编码器New(dataShards, parityShards int, opts ...Option) (ReedSolomon, error)
  2. 数据分片操作
    • Split(data []byte) ([][]byte, error) - 将数据分割为多个分片
    • Join(dst io.Writer, shards [][]byte, outSize int) error - 合并数据分片
  3. 编码与校验
    • Encode(shards [][]byte) error - 生成校验分片
    • Verify(shards [][]byte) (bool, error) - 验证分片完整性
  4. 重建与修复
    • Reconstruct(shards [][]byte) error - 重建丢失的分片
    • ReconstructData(shards [][]byte) error - 只重建数据分片
  5. 流式接口
    • StreamSplit(data io.Reader, dst []io.Writer, size int64) error - 流式分割
    • StreamEncode(inputs []io.Reader, outputs []io.Writer) error - 流式编码
    • StreamReconstruct(inputs []io.Reader, outputs []io.Writer) error - 流式重建
    • StreamJoin(dst io.Writer, inputs []io.Reader, size int64) error - 流式合并
高级选项

可以通过选项函数自定义编码器的行为:

// 创建带选项的编码器
rs, err := reedsolomon.New(10, 3, 
    reedsolomon.WithConcurrentStreams(true),  // 开启并发
    reedsolomon.WithStreamBlockSize(8*1024*1024)) // 设置8MB块大小

常用选项:

  • WithConcurrentStreams - 启用并发流处理
  • WithStreamBlockSize - 设置流处理块大小
  • WithConcurrency - 设置并发级别

性能考虑

  • 对于分片数不超过256的情况,系统会使用8位Galois域实现,性能更好
  • 对于需要超过256个分片的场景,系统会自动切换为16位Galois域实现
  • 使用流式接口处理大文件可以减少内存使用
  • 并发选项可以在多核系统上提高性能

完整的性能优化建议和详细示例请参考示例文档

限制

  • 每个分片的大小必须相同(除了使用流式接口时)
  • 支持的最大分片数取决于Galois域:
    • 8位实现:最多256个分片(数据+奇偶校验)
    • 16位实现:最多65536个分片
  • 丢失的分片数量必须小于或等于奇偶校验分片数量

许可证

该库基于 MIT 许可证发布。详见LICENSE文件。

致谢

本项目基于Klaus Post的原始reedsolomon库扩展,增加了16位Galois域支持。

Reed-Solomon 16 (GF(2^16)) - English

[Original English content follows...]

Documentation

Index

Constants

View Source
const (
	LogLevelNone = iota
	LogLevelError
	LogLevelWarn
	LogLevelInfo
	LogLevelDebug
)

日志级别定义

Variables

View Source
var (
	ErrInvShardNum         = errors.New("无效的分片数量")
	ErrMaxShardNum         = errors.New("分片数量超过最大支持数")
	ErrTooFewShards        = errors.New("可用分片数量不足,无法重建数据")
	ErrShardNoData         = errors.New("分片中没有数据")
	ErrShardSize           = errors.New("分片大小不一致")
	ErrEmptyShards         = errors.New("空分片数组")
	ErrInvalidShards       = errors.New("无效的分片数据")
	ErrInvalidInput        = errors.New("无效的输入数据")
	ErrInvalidOutput       = errors.New("无效的输出缓冲区")
	ErrReconstructRequired = errors.New("需要先进行数据重建")
	ErrInvalidShardSize    = errors.New("分片大小不满足要求,通常是N的倍数")
	ErrShortData           = errors.New("数据不足,无法填充请求的分片数量")
	ErrNotSupported        = errors.New("operation not supported")
	// 流式操作相关错误
	ErrReconstructMismatch = errors.New("一个分片不能同时是输入和输出")
	ErrNilWriter           = errors.New("目标写入器不能为nil")
	ErrSize                = errors.New("无效的大小参数")
)

错误定义

View Source
var GF8Bridge = newGF8Bridge()

创建全局包装实例供适配器使用

Functions

func AllocAligned

func AllocAligned(shards, each int) [][]byte

AllocAligned allocates 'shards' slices, with 'each' bytes. Each slice will start on a 64 byte aligned boundary.

func GaloisAdd

func GaloisAdd(a, b byte) byte

GaloisAdd 执行Galois域加法 (异或)

func GaloisDivide

func GaloisDivide(a, b byte) byte

GaloisDivide 执行Galois域除法 在实际集成时,这将使用原始galois.go中的galDivide函数

func GaloisExp

func GaloisExp(a byte, n int) byte

GaloisExp 计算Galois域中的指数 在实际集成时,这将使用原始galois.go中的galExp函数

func GaloisMultiply

func GaloisMultiply(a, b byte) byte

GaloisMultiply 执行Galois域乘法 在实际集成时,这将使用原始galois.go中的galMultiply函数

func SetLogger

func SetLogger(l Logger)

SetLogger 设置全局日志实例

Types

type Extensions

type Extensions interface {
	// ShardSizeMultiple will return the size the shard sizes must be a multiple of.
	ShardSizeMultiple() int

	// DataShards will return the number of data shards.
	DataShards() int

	// ParityShards will return the number of parity shards.
	ParityShards() int

	// TotalShards will return the total number of shards.
	TotalShards() int

	// AllocAligned will allocate TotalShards number of slices,
	// aligned to reasonable memory sizes.
	// Provide the size of each shard.
	AllocAligned(each int) [][]byte
}

Extensions is an optional interface. All returned instances will support this interface.

type Logger

type Logger interface {
	Error(msg string, args ...interface{})
	Warn(msg string, args ...interface{})
	Info(msg string, args ...interface{})
	Debug(msg string, args ...interface{})
	SetLevel(level int)
}

Logger 接口定义了日志系统

type ReedSolomon

type ReedSolomon interface {
	// 获取配置信息
	DataShards() int   // 返回数据分片数量
	ParityShards() int // 返回奇偶校验分片数量
	TotalShards() int  // 返回总分片数量(数据分片+奇偶校验分片)

	// 内存操作
	Encode(shards [][]byte) error                           // 对数据分片编码,生成奇偶校验分片
	Verify(shards [][]byte) (bool, error)                   // 验证分片数据的一致性
	Reconstruct(shards [][]byte) error                      // 重建丢失的分片(数据和奇偶校验)
	ReconstructData(shards [][]byte) error                  // 只重建丢失的数据分片
	Split(data []byte) ([][]byte, error)                    // 将数据拆分成多个分片
	Join(dst io.Writer, shards [][]byte, outSize int) error // 将分片合并成单个数据块

	// 流式操作
	StreamEncode(inputs []io.Reader, outputs []io.Writer) error          // 流式编码
	StreamVerify(shards []io.Reader) (bool, error)                       // 流式验证
	StreamReconstruct(inputs []io.Reader, outputs []io.Writer) error     // 流式重建
	StreamReconstructData(inputs []io.Reader, outputs []io.Writer) error // 流式重建数据分片
	StreamSplit(data io.Reader, dst []io.Writer, size int64) error       // 流式拆分
	StreamJoin(dst io.Writer, shards []io.Reader, outSize int64) error   // 流式合并

	// 内存管理
	AllocAligned(shards, each int) [][]byte // 分配对齐的内存
	ShardSizeMultiple() int                 // 返回分片大小需要满足的倍数

	// 并发控制
	WithConcurrency(n int) ReedSolomon // 设置并发级别
}

ReedSolomon 接口定义了Reed-Solomon编解码器的通用操作 支持内存操作和流式操作

func New

func New(dataShards, parityShards int) (ReedSolomon, error)

New 创建一个新的Reed-Solomon编解码器 如果总分片数 <= 256,将使用GF(2^8)实现,否则使用GF(2^16)实现

func New8

func New8(dataShards, parityShards int) (ReedSolomon, error)

New8 创建一个基于GF(2^8)的Reed-Solomon编解码器,最多支持256个分片

func New16

func New16(dataShards, parityShards int) (ReedSolomon, error)

New16 创建一个基于GF(2^16)的Reed-Solomon编解码器,最多支持65535个分片

type StreamEncoder8

type StreamEncoder8 interface {
	// Encode 为一组数据分片生成奇偶校验分片
	Encode(inputs []io.Reader, outputs []io.Writer) error

	// Verify 验证奇偶校验分片的正确性
	Verify(shards []io.Reader) (bool, error)

	// Reconstruct 重建丢失的分片
	Reconstruct(inputs []io.Reader, outputs []io.Writer) error

	// Split 将输入流分割成多个分片
	Split(data io.Reader, dst []io.Writer, size int64) error

	// Join 将分片连接起来并将数据段写入dst
	Join(dst io.Writer, shards []io.Reader, outSize int64) error
}

StreamEncoder8 是一个基于GF(2^8)的Reed-Solomon流式编码器接口

type StreamEncoder16

type StreamEncoder16 interface {
	// Encode 为一组数据分片生成奇偶校验分片
	Encode(inputs []io.Reader, outputs []io.Writer) error

	// Verify 验证奇偶校验分片的正确性
	Verify(shards []io.Reader) (bool, error)

	// Reconstruct 重建丢失的分片
	Reconstruct(inputs []io.Reader, outputs []io.Writer) error

	// Split 将输入流分割成多个分片
	Split(data io.Reader, dst []io.Writer, size int64) error

	// Join 将分片连接起来并将数据段写入dst
	Join(dst io.Writer, shards []io.Reader, outSize int64) error
}

StreamEncoder16 是一个基于GF(2^16)的Reed-Solomon流式编码器接口

type StreamReadError

type StreamReadError struct {
	Err    error
	Stream int
}

流读取错误

func (StreamReadError) Error

func (e StreamReadError) Error() string

type StreamWriteError

type StreamWriteError struct {
	Err    error
	Stream int
}

流写入错误

func (StreamWriteError) Error

func (e StreamWriteError) Error() string

Directories

Path Synopsis
examples
advanced command
basic command
stream command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL