Reed - códigos de Solomon en RAID 6

Hay muchos artículos en Internet sobre la recuperación de datos en una matriz RAID-6 y cómo realizar su propia implementación de dicha matriz. Pero la mayoría de estos artículos están repletos de fórmulas matemáticas. Para comprender el algoritmo real, debes dedicar mucho tiempo.



En este artículo intentaré mostrar un ejemplo sencillo de mi propio sistema de corrección de errores basado en RAID-6. En particular, considere una situación en la que necesite proporcionar redundancia al sistema para que pueda soportar la falla de una o dos unidades.



Como beneficio adicional, información sobre cómo funciona la corrección de errores en RAID-5, porque RAID-6 es una versión mejorada de RAID-5.



Visión de conjunto



Digamos que tiene tres discos con algunos datos. Llamémoslos D1, D2 y D3. Para utilizar un sistema RAID-6, necesita dos unidades adicionales: PD y RS. En unos minutos, describiré lo que significan PD y RS. Entonces, un total de cinco unidades: D1, D2, D3, PD y RS.







Entonces la situación:



  • D1, D2 y D3 contienen datos arbitrarios . Digamos fotos de gatos.

  • Un disco especial PD (Parity Drive, a veces P en la documentación) contiene datos ampliados generados automáticamente desde D1, D2 y D3.

  • Segundo disco especial RS (códigos Reed-Solomon, a veces llamado Q) para los mismos datos que PD.


Veamos cómo realizar operaciones básicas en tal matriz.



Cómo funciona la recuperación



Si calcula la PD y RS correctamente, puede sobrevivir sin dolor a una falla de hasta dos discos. El procedimiento de recuperación depende de qué unidades en particular fallan. Generalmente se consideran siete situaciones. A continuación, están ordenados de fáciles a complejos.



  1. Pérdida de EP (solo un disco).







    Un caso muy sencillo. La unidad PD contiene solo datos generados automáticamente, por lo que se puede recuperar utilizando los datos originales en las unidades D1, D2 y D3.



  2. : D1, D2 D3 ( ).







    , , , RAID-5: PD . PD, . RS ( ).



  3. RS ( ).







    1: , RS,  — .



  4. PD RS ( ).







    1 3. , PD, RS.



  5. RS ( ).







    , . PD, , № 2. , RS.



  6. PD ( ).







    . ( D3), PD, . RS (D1 D2), D3. PD. ,  — .



  7. ( ).







    . PD, RS .  — .


En las siguientes secciones, exploraremos estos casos con más detalle y veremos el código fuente (en Python) que realiza la recuperación de datos real.



Tenga en cuenta que las matrices RAID-6 reales no asignan una unidad completa para PD o RS. Estos datos se distribuyen en todas las unidades. Diferentes controladores usan diferentes métodos: asíncrono a la izquierda o síncrono a la derecha, puede haber un cambio en relación a los datos RAID, latencia, etc. Dejemos de lado la discusión de por qué sucede esto y cómo se ven las franjas reales. RAID-6. Centrémonos específicamente en los códigos Reed-Solomon.



Datos de prueba



Definamos "datos de usuario". Para simplificar, establezcamos el tamaño de cada "disco" en 5 bytes.



Disco Datos ASCII Datos en HEX
D1



primero 0x66, 0x69, 0x72, 0x73, 0x74
D2



segundo 0x73, 0x65, 0x63, 0x6e, 0x64
D3



tercero 0x74, 0x68, 0x69, 0x72, 0x64


Ahora echemos un vistazo más de cerca a los escenarios mencionados.



Situación 1. Pérdida de disco de DP



Para generar PD, solo se necesitan discos de datos de usuario. En nuestro caso, estos son D1, D2 y D3. El disco PD simplemente se XOR de todos los datos del usuario.



Para generar el desplazamiento 0 para PD, todos los bytes del desplazamiento 0 deben comprimirse en todos los discos. Lo mismo ocurre con el desplazamiento 1 y así sucesivamente:



PD [0] = D1 [0] xo D2 [0] xo D3 [0]
PD [1] = D1 [1] xo D2 [1] xo D3 [1]
PD [2] = D1 [2] xo D2 [2] xo D3 [2]
PD [3] = D1 [3] xo D2 [3] xo D3 [3]
PD [4] = D1 [4] xo D2 [4] xo D3 [4]


Ejemplo:



PD [0] = 0x66 xor 0x73 xor 0x74 => 0x61
PD [1] = 0x69 xor 0x65 xor 0x63 => 0x64
PD [2] = 0x72 xor 0x63 xor 0x69 => 0x78
PD [3] = 0x73 xor 0x6e xor 0x72 => 0x6f
PD [4] = 0x74 xor 0x64 xor 0x64 => 0x74


Si, es muy simple. Haga esto para discos completos (en nuestro caso, 5 bytes) y obtenga un PD generado correctamente:



Disco Datos en HEX
PD



0x61, 0x64, 0x78, 0x6f, 0x74


Por lo tanto, si solo falla el PD, es bastante trivial restaurarlo desde D1, D2 y D3.



Situación 2. Pérdida de uno de los almacenes de datos: D1, D2 o D3



Por cierto, así es como funciona la reparación de errores RAID-5. Si solo falla un disco de datos de usuario, podemos usar el disco de PD para volver a calcular los datos de usuario que faltan.



Digamos que D2 se pierde. D1, D3, PD y RS permanecieron en stock. En este caso, ni siquiera toque RS. Solo se necesitan las unidades D1, D3 y PD. Para calcular los datos faltantes, puede volver a utilizar la función XOR como en la situación anterior.



Para recuperar los datos de usuario del desplazamiento 0, xorime los bytes de los desplazamientos cero de los discos de datos del usuario que quedan (D1 y D3) con el byte del desplazamiento cero PD. Repita para el desplazamiento 1, y así sucesivamente:



D2 [0] = D1 [0] xo D3 [0] xo PD [0]
D2 [1] = D1 [1] xo D3 [1] xo PD [1]
D2 [2] = D1 [2] xo D3 [2] xo PD [2]
D2 [3] = D1 [3] xo D3 [3] xo PD [3]
D2 [4] = D1 [4] xo D3 [4] xo PD [4]


Ejemplo:



D2 [0] = 0x66 xor 0x74 xor 0x61 => 0x73 (s)
D2 [1] = 0x69 xor 0x63 xor 0x64 => 0x65 (e)
D2 [2] = 0x72 xor 0x69 xor 0x78 => 0x63 (c)
D2 [3] = 0x73 xor 0x72 xor 0x6f => 0x6e (n)
D2 [4] = 0x74 xor 0x64 xor 0x74 => 0x64 (d)


Como puede ver, es muy fácil recuperar datos de un disco perdido. No importa qué disco falte: la función XOR siempre funciona.



Situación 3. Pérdida de disco RS



Ahora entran en juego los códigos de campo de Reed-Solomon y Galois. Pero no se preocupe, no es necesario ser matemático para usarlos.



Cuando solo perdemos la unidad RS o creamos un nuevo sistema como RAID-6, solo necesitamos volver a generar los códigos. Para hacer esto, utilice las tablas gflog y gfilog con contenido inmutable, así como los datos de las unidades D1, D2 y D3 existentes.



La tabla gflog siempre se ve así:



0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf.


La tabla gfilog también es persistente:



0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01.


No es necesario incluir estas tablas en el programa, puede utilizar el siguiente algoritmo de generación en tiempo de ejecución:



# gflog_tables.py

def generate_tables():
    polynomial = 0x11d
    s = 8
    gf_elements = 1 << s

    gflog = gf_elements * [0]
    gfilog = gf_elements * [0]

    b = 1
    for i in range(0, gf_elements):
        gflog[b] = i & 255
        gfilog[i] = b & 255
        b <<= 1
        if b & gf_elements:
            b ^= polynomial

    gflog[1] = 0;
    return (gflog, gfilog)

def dump_table(caption, tab):
    item = 0
    print("--- {} ---".format(caption))
    for i in tab:
        print("0x{:02x}, ".format(i), end="")
        item += 1
        if item % 16 == 0:
            item = 0
            print()
    print("")

(gflog, gfilog) = generate_tables()

# Uncomment if you want to see the tables on the console:
#
# dump_table("gflog", gflog)
# dump_table("gfilog", gfilog)
      
      





Una vez declaradas las tablas, es necesario definir algunas operaciones. Ahora estamos trabajando en un campo finito ( campo de Galois), por lo que las operaciones aritméticas básicas tienen una implementación diferente (aunque el significado es algo similar). Necesita redefinir las operaciones básicas: suma, multiplicación y división:



# rs_functions.py

from gflog_tables import *

# Addition
def gf_add(*args):
    result = 0
    for arg in args:
        result ^= arg

    return result

# Indexing
# First drive is 1, second drive is 2, etc...
def gf_drive(index):
    global gfilog

    return gfilog[index - 1]

# Multiplication
def gf_mul(a, b):
    global gflog
    global gfilog

    if a == 0 or b == 0:
        return 0
    else:
        return gfilog[(gflog[a] + gflog[b]) % 255]

# Division helper
def sub_gf8(a, b):
    if a > b:
        return a - b
    else:
        return (255 - (0 - (a - b)))

# Division
def gf_div(a, b):
    global gfilog
    global gflog

    return gfilog[sub_gf8(gflog[a], gflog[b])]
      
      





Dado que las funciones auxiliares están declaradas, intentemos generar los datos del disco RS.



# case 3 -- recover_rs.py

from rs_functions import *

# Here are our drives, together with their data.
image1 = [ ord('f'), ord('i'), ord('r'), ord('s'), ord('t') ]
image2 = [ ord('s'), ord('e'), ord('c'), ord('n'), ord('d') ]
image3 = [ ord('t'), ord('h'), ord('i'), ord('r'), ord('d') ]

# This is a placeholder for our RS drive. It will be regenerated
# in the lines below.
imageRS = [0] * 5

# And this is our loop that generates the RS data using nothing more
# than the user data drives.
for i in range(0, 5):
    imageRS[i] = gf_add(gf_mul(gf_drive(1), image1[i]),
                        gf_mul(gf_drive(2), image2[i]),
                        gf_mul(gf_drive(3), image3[i]))

dump_table("imageRS", imageRS)
      
      





Después de ejecutar el script recover_rs.py



, el disco RS contiene los siguientes datos:



Disco Datos en HEX
RS



0x4d, 0x1e, 0x0d, 0x7a, 0x31


Por el momento, las unidades D1, D2 y D3 están protegidas por el algoritmo completo de corrección de errores RAID-6, ya que hemos generado correctamente PD y RS.



Es importante recordar que los datos RS actuales solo son válidos para D1, D2 y D3 en ese orden en particular . Por lo tanto, el RS para D1, D2 y D3 será diferente de D3, D2 y D1, incluso si los datos reales en las unidades son los mismos. Es importante recordar esto porque al recuperar datos RAID-6, necesita conocer la secuencia correcta de discos dentro de la matriz. Afortunadamente, si la matriz es pequeña, puede forzar la generación de datos RS para encontrar la secuencia de disco correcta.



Situación 4. Pérdida de PD y RS



Esta también es una situación simple: primero ejecutamos el escenario # 1, y luego el # 3.



Repito, en este caso los datos del usuario no se ven afectados. Podemos usarlos para crear un PD. Luego para crear RS. Ambos casos ya se han descrito en los puntos 1 y 3.



Situación 5. Pérdida de RS y un disco de datos



Y aquí no es difícil. Perdimos un disco de datos, pero todavía tenemos un PD, por lo que podemos ejecutar el escenario n. ° 2 para recuperar el disco de datos que falta. Luego use todos los discos de datos para la regeneración de RS como en el escenario # 3. Ahora se recupera el conjunto completo de discos.



Situación 6. Pérdida de PD y un disco de datos



El enfoque general es recuperar primero el disco de datos que falta utilizando otros discos en combinación con RS, y luego, después de que se hayan recuperado todos los discos de datos, proceder a regenerar el PD (escenario # 2).



En esta situación, debe hacer algunos cálculos. Supongamos que junto con PD perdimos el disco de datos D2. Entonces tenemos D1, D3 y RS en stock.



Gracias al disco RS, podemos restaurar D2 combinando D1, D3 y RS, así:



# case 6 -- recover_d2_and_pd.py

from rs_functions import *

# We have these drives...
image1 = [ ord('f'), ord('i'), ord('r'), ord('s'), ord('t') ]
image3 = [ ord('t'), ord('h'), ord('i'), ord('r'), ord('d') ]
imageRS = [ 0x4d, 0x1e, 0x0d, 0x7a, 0x31 ]

# ...and these drives are dead
imagePD = [0] * 5
image2 = [0] * 5

for i in range(0, 5):
    partialRS = gf_add(gf_mul(gf_drive(1), image1[i]),
                       imageRS[i],  # Use RS drive instead of the dead drive.
                       gf_mul(gf_drive(3), image3[i]))

    # gf_drive(2) is our dead drive.
    div_result = gf_div(1, gf_drive(2))

    # This will generate the data from the dead D2 drive.
    image2[i] = gf_mul(div_result, partialRS)

    # This will generate the data from the dead PD drive.
    imagePD[i] = gf_add(image1[i], image2[i], image3[i])

dump_table("image2", image2)
dump_table("imagePD", imagePD)
      
      





Primero, necesita generar un valor partialRS



agregando (gf_add) los valores de retorno gf_mul



para todos los bytes de todos los discos válidos junto con el valor RS en lugar del disco de datos que falta (en nuestro caso, D2).



Luego usamos el valor partialRS



para regenerar los datos D2 dividiendo uno por el índice de disco muerto ( gf_drive(2)



) y multiplicando el resultado por partialRS



. El argumento gf_drive(2)



indica el índice de nuestro disco muerto. Si D1 falla, lo usaríamos aquí gf_drive(1)



.



Después de regenerar D2, restaure todos los discos de datos. En este caso, realizamos la regeneración de PD como en el escenario # 1: en el código anterior, esto se hace agregando (gf_add) datos de todos los discos. Si recuerda, hay gf_add



una operación XOR simple en el campo de Galois, por lo que en lugar de grabar manualmente los bytes de todos los discos de datos, puede usar la operación gf_add



.



Situación 7. Pérdida de dos recopiladores de datos



Este es el escenario más interesante y más difícil. Suponga que los discos D2 y D3 están fuera de servicio. En este caso, debe utilizar de alguna manera los discos D1, PD y RS para regenerar los discos que faltan.



Este es un enfoque diferente al de los casos anteriores. El enfoque general es generar primero datos para D2 y luego usar la misma estimación que en el escenario # 2 para generar datos para D3. Aquí está el código:



# case 7 -- recover_d2_and_d3.py

from rs_functions import *

# These drives are still alive.
image1 = [ ord('f'), ord('i'), ord('r'), ord('s'), ord('t') ]
imagePD = [ 0x61, 0x64, 0x78, 0x6f, 0x74 ]
imageRS = [ 0x4d, 0x1e, 0x0d, 0x7a, 0x31 ]

# These drives are dead, we can't read from them.
image2 = [0] * 5
image3 = [0] * 5

for i in range(0, 5):
    partialPD = gf_add(image1[i]) # add other drives if they exist
    partialRS = gf_add(gf_mul(gf_drive(1), image1[i])) # add other drives if they exist

    g = gf_div(1, gf_add(gf_drive(2), gf_drive(3)))
    xoredPD = gf_add(partialPD, imagePD[i])
    xoredRS = gf_add(partialRS, imageRS[i])
    mid = gf_add(gf_mul(gf_drive(3), xoredPD), xoredRS) # gf_drive(3) is the second drive we've lost

    # Regenerate data for D2.
    data = gf_mul(mid, g)
    image2[i] = data

    # Regenerate data for D3.
    image3[i] = gf_add(image1[i], image2[i], imagePD[i])

    # or:
    #
    # image3[i] = gf_add(data, xoredPD)

dump_table("image2", image2)
dump_table("image3", image3)
      
      





Primero, debe agregar todos los bytes de todos los discos de datos existentes para generar partialPD



. En este ejemplo, solo tenemos un disco de datos, por lo que el parámetro partialPD



será simplemente el contenido del disco D1. Pero las matrices RAID-6 abarcan varias unidades. Por lo tanto, si tenemos más de un disco de datos, por ejemplo, tres discos de datos en vivo, entonces el cálculo de la PD parcial se vería así:



partialPD = gf_add(image1[i], image2[i], image3[i])
      
      





A continuación, necesitamos un parámetro partialRS



. Se puede calcular agregando datos de discos existentes de la siguiente manera:



partialRS = gf_add(A, B, C, ..., Z)

where A = gf_mul(gf_drive(1), image1[i])
      B = gf_mul(gf_drive(2), image2[i]) if we have drive 2
      C = gf_mul(gf_drive(3), image3[i]) if we have drive 3

etc.
      
      





En nuestro caso, solo queda una unidad de datos (D1), por lo que la nuestra partialRS



es simple gf_mul(gf_drive(1), image1[i])



.



Luego, debe generar el parámetro g



dividiendo uno por la suma de los índices de disco muerto (D2 y D3).



Luego viene el parámetro xoredPD



; se calcula sumando el contenido de la PD al parámetro partialPD



calculado previamente. El siguiente parámetro se xoredRS



calcula de manera similar, agregándolo partialRS



al contenido de RS.



Ahora la parte complicada. Puede calcular los datos del primer disco roto, es decir, del disco D2. Para hacer esto, necesita multiplicar el índice del segundo disco roto(D3) al parámetro xoredPD



y agregue el parámetro al resultado xoredRS



. Luego, después de multiplicar el resultado por un parámetro g



, obtenemos el contenido del disco D2.



Dado que acabamos de recuperar datos para D2, este caso no es diferente del escenario n. ° 2: pérdida de un disco de datos (D3). Para crear una unidad D3, todas las unidades de datos en vivo (D1 y D2) deben agregarse al PD.



¡Hecho! Devolvimos un juego completo de discos.



Epílogo



Elegí Python para demostrar que corregir errores con códigos Reed-Solomon no requiere mucha capacidad de programación o procesamiento. Todo es muy rápido y la implementación puede ser bastante compacta. Por supuesto, se debe escribir una implementación más eficiente teniendo en cuenta el paralelismo. Dado que cada byte se calcula independientemente de los demás, la paralelización no es difícil.



Cabe señalar que el método de recuperación de datos descrito no tiene que usarse en discos físicos separados. Los "discos" pueden considerarse como "búferes" en el proceso de transmisión de datos a través de un canal no confiable, y dicha corrección de errores sigue siendo efectiva. Requiere cálculos más intensivos que con los códigos de Hamming, pero se pueden generar dos corrientes caídas. Esta es una característica de resistencia poderosa.



Por supuesto, RAID-6 está lejos de ser un invento nuevo, y los códigos Reed-Solomon son incluso más antiguos. Fueron utilizados en la misión Voyager 2 , lo cual es bastante bueno.



Entre las alternativas más modernas para los códigos Reed-Solomon están los códigos turbo  ; espero tener la oportunidad de profundizar en ellos también.



All Articles