Restic: Implementar compresión

Creado en 15 nov. 2014  ·  167Comentarios  ·  Fuente: restic/restic

Este problema es un problema de seguimiento a los efectos de realizar un seguimiento de las discusiones y otros problemas / RP relacionados con la solicitud de implementación de la compresión.

Los siguientes problemas / RP están relacionados con este tema (y, por lo tanto, pueden cerrarse a favor de este):

  • PR # 2441
backend backup feature suggestion tracking

Comentario más útil

Creo que ha habido suficiente discusión sobre el tema de agregar compresión. Puedo ver que es una característica muy esperada. Abordaré esto después de terminar el nuevo código de archivador (ver # 1494).

Por favor, no agregue más comentarios, ¡gracias!

Todos 167 comentarios

Al implementar esto, agregue puntos de referencia y, especialmente, observe el uso de la memoria con -benchmem y benchcmp.

lz4, lzo, lzma, nulo. bz2 es bastante lento.

rápido es rápido con compresión moderada

Si la compresión se realiza por fragmento, se debe tener cuidado de que no deje las copias de seguridad restringidas abiertas a ataques de marcas de agua / huellas dactilares.

Este es esencialmente el mismo problema que discutimos relacionado con la toma de huellas digitales del proceso de deduplicación de CDC:
Con CDC "ingenuo", se puede verificar la existencia de un archivo de "texto sin formato conocido" dentro de la copia de seguridad si un atacante puede observar el tamaño de los bloques individuales, utilizando CDC en el archivo en paralelo y comparando la cantidad resultante de fragmentos y longitudes de trozos.
Como se discutió anteriormente, esto se puede mitigar un poco salando el algoritmo CDC con un valor secreto, como se hizo en el ático.

Con CDC salado, supongo que la compresión se produciría en cada fragmento individual, después de dividir el archivo problemático en fragmentos. Los fragmentos Restic están en el rango de 512 KB a 8 MB (pero no distribuidos uniformemente, ¿verdad?).

  • El atacante sabe que el algoritmo de CDC utiliza una sal secreta, por lo que el atacante genera un rango de fragmentos que consta de los primeros 512 KB a 8 MB del archivo, uno por cada longitud de fragmento válida. El atacante también puede determinar la longitud de los trozos comprimidos.
  • Luego, el atacante comprime ese fragmento utilizando el algoritmo de compresión.
  • El atacante compara las longitudes de los fragmentos resultantes con el primer fragmento de los conjuntos de copias de seguridad restos.
  • SI se encuentra una longitud de bloque coincidente, el atacante repite el ejercicio con el siguiente fragmento, y el siguiente fragmento, y el siguiente fragmento, ... y el siguiente fragmento.
  • Creo que con archivos suficientemente grandes, y teniendo en cuenta el hecho de que el algoritmo CDC está "sesgado" (a falta de mejores palabras) hacia la generación de bloques de aproximadamente 1 MB, esto sería suficiente para determinar si un determinado tamaño grande El archivo existe en la copia de seguridad.

Como siempre, una corriente de conciencia paranoica y muy poco científica.

¿Pensamientos?

Interesante. No entiendo cómo el ataque que describe depende de si se usa compresión, ¿es necesario en absoluto? ¿No funciona este ataque con y sin compresión?

Por el momento estoy pensando en cómo implementar el # 56. ¿Qué opina de agrupar varios blobs en un solo archivo?

El funcionamiento exacto de la implementación de los CDC no me queda claro:

  • ¿Se divide en límites de bytes exactos o los bloques de 512 KB - 8 MB están "redondeados" a un múltiplo de algo?
  • (La verdadera pregunta es: ¿hay (15 * 512 * 1024) / (16 debido a AES-CTR) tamaño de fragmento posible, o menos?)
  • También tengo curiosidad acerca de cuán factible sería reconstruir la semilla con suficientes trozos de un archivo conocido; no es muy factible, supongo.

Para responder a su primera pregunta:
Con el CDC sembrado, la "huella dactilar" depende del (contenido + la semilla secreta), pero la diferencia es que cuando se realiza la compresión _después_ de la fragmentación, y asumiendo que puede distinguir bloques individuales entre sí, tiene una huella dactilar / marca de agua (la tasa de compresión de un determinado bloque) que depende únicamente del contenido, en este escenario un texto plano conocido.

Ejemplo:
Si el archivo con marca de agua contiene 64 MB (8-128 fragmentos) de "AAAA", luego 64 MB de "ABCABCABCABC", luego 64 MB de datos aleatorios, los primeros 16-256 fragmentos serían muy pequeños (porque esas secuencias se comprimen muy bien , donde los fragmentos 8-128 se comprimirían bastante mal).
El atacante también podría trabajar al revés, comenzando con el último fragmento (24º - 384º) y comprimir 512 KB-8 MB hasta que el atacante encuentre un tamaño que se comprima exactamente al mismo tamaño de fragmento. Una vez que se encuentra, los "siguientes" 512 KB-8 MB del texto sin formato original se comprimen para averiguar qué longitud se comprime a la longitud del penúltimo bloque (23º - 383º), y así sucesivamente, hasta que el atacante se encuentre con el pequeños trozos que son el resultado de las cadenas "AAAA".
Esto no permite a un adversario confirmar positivamente que un archivo con marca de agua está almacenado en la copia de seguridad, pero creo que estadísticamente puede crear resultados bastante claros, con suficientes datos.

Veo algunas posibles soluciones, quizás tengas más ideas:

  • Permitir desactivar la compresión y / o la deduplicación para ciertos directorios (probablemente el más fácil de implementar)
  • Aleatorizar los diccionarios de compresión (realmente no lo he pensado bien, pero parece una idea interesante)
  • Evite que los atacantes aprendan la longitud de los fragmentos comprimidos individuales, por ejemplo, rellenando (potencialmente bastante caro) o agrupando varios fragmentos pequeños y rellenando el resto (más complejidad, pero más eficiente)

Gracias por su explicación, ahora comprendo su escenario.

Probablemente no habrá ninguna opción para desactivar la deduplicación en restic, porque eso es realmente difícil de hacer dada la estructura actual del programa, restic se basa en CDC. Agregar soporte de compresión es de baja prioridad en este momento y no es un objetivo para la versión alfa.

Su tercera idea se implementará en el n. ° 56 (agrupando varios fragmentos), estoy trabajando en eso ahora mismo. Y probablemente agregaré más documentación a doc/Design.md sobre cómo funciona el fragmento.

¡Gracias de nuevo por traer a colación este escenario!

No estoy seguro de si sigo a @cfcs , ¿no es el tamaño comprimido como un hash increíblemente malo? Dado un tamaño de archivo comprimido, la cantidad de posibles entradas que generan ese tamaño de archivo es infinita. Pero probablemente no lo entiendo.

De todas formas. Solo quería señalarle descaradamente una biblioteca deflate / gzip modificada que hice. Puede que le interese que establezca un modo de compresión de tiempo constante , que permite un rendimiento de ~ 150 MB / s / núcleo en CUALQUIER dato, lo que lo hace casi invisible en escenarios de copia de seguridad. También hay un paquete gzip paralelo que comprime archivos más grandes en varios núcleos.

@klauspost : Tenga en cuenta que estamos discutiendo los tamaños comprimidos de fragmentos individuales en lugar de archivos. Un archivo de 100 GB con un tamaño de fragmento promedio de 1 MB tendrá aproximadamente 100 x 1024 fragmentos, cada uno de los cuales pierde la relación de compresión para una determinada parte del archivo. Esto da como resultado muchos más datos estadísticos que el tamaño de un solo archivo comprimido, lo que hace posible comparar un texto plano conocido con un archivo comprimido y fragmentado incluso si se desconoce la sal CDC (y, por lo tanto, los bordes de alineación exactos de los fragmentos).

Sin embargo, 151 se ha fusionado, por lo que probablemente esto no sea un problema ahora.

En mi opinión, esta fuga de información es solo de menor importancia, considerando que tenemos un fragmento inicial (a través del polinomio personalizado por repositorio) y un paquete de blobs (donde un atacante no puede ver fragmentos individuales, sino solo grupos de fragmentos y la cantidad de fragmentos) en un grupo, a través de la longitud del encabezado de texto sin formato). Creo que es una buena idea ofrecer la desactivación de la compresión por completo por cuestiones de velocidad o privacidad, pero el valor predeterminado (cuando se implemente) probablemente sea "habilitar".

@klauspost Definitivamente miraré tu biblioteca, ¡gracias por señalarlo!

Estoy de acuerdo con sus observaciones anteriores, @ fd0 , pero me gustaría agregar que creo que puede haber otro caso de uso importante para deshabilitar selectivamente la compresión para archivos / directorios / dispositivos de destino específicos, por ejemplo, al realizar copias de seguridad de formatos multimedia que ya archivos binarios comprimidos con alta entropía que no se comprimen bien, o al realizar copias de seguridad incrementales de volúmenes cifrados.

@cfcs - ok - de su texto, pensé que insinuaba que podía deducir los datos. Entonces, para que esto marque la diferencia, necesitaría los datos originales, lo cual es raro.

Con respecto a los archivos no comprimibles, esa es la razón por la que mencioné el modo de solo Huffman de tiempo constante que puse en desinflar, ya que el nombre lo indica, comprime todos los datos a la misma velocidad y tiene un respaldo automático para almacenar datos sin comprimir. Entonces, la sobrecarga máxima es de aproximadamente 0.04% si el contenido está comprimido.

A continuación se muestran algunos puntos de referencia . El más aplicable para las copias de seguridad es probablemente en la "compresión media", que es un contenido mixto de 10 GB, comprimible y no comprimible.

La opción predeterminada para gzip Huffman solo y tener la opción de especificar un nivel de compresión que consume más CPU podría tener sentido.

En mi opinión, podría ser valioso habilitar / deshabilitar selectivamente la compresión por separado para los datos y los objetos de árbol. Los objetos de árboles especialmente grandes deberían comprimirse realmente bien.

Observé algunos "puntos" en los que podría tener sentido insertar compresión. El lugar más transparente y versátil estaría en algún lugar entre el repositorio y el backend.

Analicé brevemente la modificación de Repository.Encrypt y Repository.DecryptTo , pero no tenemos tipos, y los diferentes tamaños harían un lío de cosas.

Mi propuesta es implementar la compresión y el _encryption_ como un "backend", que ambos escriben en un backend subyacente. Esto hará que la compresión y el cifrado sean transparentes para el repositorio.

La razón por la que necesitamos separar el cifrado es que los datos cifrados no se comprimen (como probablemente sepa).

repositorio.Repositorio

El algoritmo de compresión solo se puede configurar en la inicialización, y se supone que todo, excepto la configuración, está comprimido con ese algoritmo.

repositorio.Config

La configuración no se puede comprimir. Agregamos una cadena que indica el tipo de descompresión que se utilizará para todo. Empty ("") no está comprimido. De lo contrario, es la última parte del nombre del paquete de la biblioteca de compresión utilizada.

Tenga en cuenta que los niveles de compresión se pueden cambiar entre cada ejecución / tipo. No hay ningún problema en tener un repositorio donde algunas instantáneas / tipos se desinflan en el nivel 0 (almacenamiento) y otras en el nivel 9 (mejor compresión), siempre que el descompresor sea el mismo.

type Config struct {
    Version           uint        `json:"version"`
    ID                string      `json:"id"`
    ChunkerPolynomial chunker.Pol `json:"chunker_polynomial"`
+   Compression       string
}

La compresión se agrega como parámetro de creación:

-func CreateConfig(r JSONUnpackedSaver) (Config, error) {
+func CreateConfig(r JSONUnpackedSaver, compression string) (Config, error) {

El backend se reemplaza después de LoadConfig / CreateConfig. A continuación, se muestra un ejemplo de cómo podría verse:

// SearchKey finds a key with the supplied password, afterwards the config is
// read and parsed.
func (r *Repository) SearchKey(password string) error {
    key, err := SearchKey(r, password)
    if err != nil {
        return err
    }

-   r.key = key.master
-   r.keyName = key.Name()
    r.Config, err = LoadConfig(r)
+   r.be, err = FindCompressor(r.Config.Compression, Encryption(key, r.be))
    return err
}

Implementación de compresión

El compresor puede implementar compresión selectiva / ajustable para algunos tipos. Dado que se ve como un "backend", el tamaño comprimido nunca será visible para el repositorio. El compresor debe ser summetric con todos los ajustes.

Cuestiones

HELPME / FIXME: Los archivos "empaquetados" parecen un problema, ya que el cifrado se reinicia en cada archivo. Si el cifrado se traslada al backend, el cifrado será para todo el blob, no para cada archivo. Supongo que es un problema y no tengo una buena solución.

TODO: Encuentre una buena manera de enviar parámetros / configuración al compresor. No es necesario para una primera implementación.

TODO: ¿Nos preocupamos por los tamaños en disco? Si se implementa lo anterior, el repositorio no lo sabrá.

Gracias por compartir tus pensamientos, estos son los míos:

Creo que la compresión y el cifrado deben integrarse entre sí, pensaré en esto. Por el momento, no me gusta la idea de abstraer completamente la capa de compresión / cifrado entre sí. Como ya describiste, debemos tener cuidado de no hacer cosas estúpidas, por ejemplo, comprimir datos cifrados. Además, deberíamos ofrecer una opción para deshabilitar la compresión a favor de la velocidad y / o problemas de seguridad. Con respecto al cifrado: puede haber un modo no criptográfico para resticir más adelante, pero por ahora el cifrado no es opcional.

Además, los archivos empaquetados son un nivel de abstracción en sí mismos (por ejemplo, las cosas se pueden volver a empaquetar), lo que no funciona con la abstracción de cifrado.

Creo que el objeto Repository es demasiado complejo y necesita una revisión general antes de abordar esto. Realmente no tengo un buen plan listo para ello en este momento.

Con respecto a los diferentes algoritmos y opciones de compresión: creo que deberíamos seleccionar un algoritmo (incluido un conjunto de parámetros) para los datos, y tal vez un segundo para comprimir las estructuras del árbol JSON, pero eso es todo. Para todas las cosas opcionales (por ejemplo, diferentes algoritmos y / o parámetros de compresión configurables) me gustaría tener una consideración sólida que pondera el beneficio frente a la complejidad agregada y la cantidad de código adicional.

Por favor, no me malinterpretes, me gustaría agregar funciones a Restic, pero especialmente para los cambios que modifican el formato en disco, necesito muy buenos argumentos. En el caso general de agregar compresión, puedo ver el beneficio, pero la complejidad y los cambios en el formato en disco deben ser manejables.

necesitará diferentes algoritmos y parámetros (y no solo por repositorio, sino incluso por ejecución de copia de seguridad), no existe una compresión "mejor para cada caso de uso".

solo como un ejemplo práctico:

Hago copias de seguridad desde el servidor de mi empresa a mi servidor de copia de seguridad en casa. enlace ascendente dsl con ~ 700 kbit / s.
para esto quiero la mejor compresión (como lzma + alto nivel). la CPU tiene mucho tiempo libre por la noche mientras espera que la mala conexión acepte el siguiente paquete.

en el mismo repositorio también hago una copia de seguridad de mi computadora portátil cuando estoy en casa, allí tengo una conexión inalámbrica "N". Por supuesto, no quiero ralentizar la conexión usando lzma + high level allí, sino que quiero algo muy rápido que no se ralentice en absoluto, como lz4. Sin embargo, todavía quiero compresión, no usar lz4 tomaría aproximadamente el doble de espacio.

Quiero lzma aquí pero lz4 allá (reformulado :-))

Eso es todo, en mi humilde opinión ... Escojamos un valor predeterminado razonable y no expongamos demasiada configuración, eso solo introducirá mucha complejidad por poca ganancia, en mi humilde opinión.

Creo que el objeto Repository es demasiado complejo y necesita una revisión general antes de abordar esto. Realmente no tengo un buen plan listo para ello en este momento.

Lo suficientemente justo. Comencé a buscar en repository.go y encontré todos los lugares en los que insertaría un paso de compresión / descompresión, y la complejidad adicional no fue algo bueno. Al implementarlo como una interfaz backend , podría eliminar repentinamente todo el cifrado y convertirlo en parte de una cadena de backend. Puede realizar una prueba genérica que garantice la simetría de las partes del backend, incluida la compresión y el cifrado.

Con respecto al cifrado: puede haber un modo no criptográfico para resticir más adelante, pero por ahora el cifrado no es opcional.

Es por eso que el encadenamiento de backend lo hace tan agradable. Simplemente omite el cifrado (o crea un backend de transferencia) y funciona a la perfección.

En el caso general de agregar compresión, puedo ver el beneficio, pero la complejidad y los cambios en el formato en disco deben ser manejables.

Esta fue la forma menos intrusiva que pude ver. Si hay una forma de solucionar el problema del "archivo empaquetado", los repositorios sin comprimir siguen siendo totalmente compatibles con versiones anteriores; el cliente antiguo podrá operar en ellos como antes junto con los nuevos.

Los repositorios comprimidos obviamente no lo harán, pero podemos cambiar version a 2 solo si el repositorio está comprimido, esto hará que los clientes más antiguos fallen. Entonces, obviamente, la verificación debería cambiarse a if cfg.Version > RepoVersion { , pero eso no tiene problemas de compatibilidad.

Eso es todo, en mi humilde opinión ... Escojamos un valor predeterminado razonable y no expongamos demasiada configuración, eso solo introducirá mucha complejidad por poca ganancia, en mi humilde opinión.

De acuerdo. La mayoría de los algoritmos (lzma / deflate) tienen mucha flexibilidad dentro del mismo formato de descompresión.

Para probar la compresibilidad, existe DataSmoke: https://github.com/Bulat-Ziganshin/DataSmoke

Además, pcompress elige una buena variedad de algoritmos de compresión: https://github.com/moinakg/pcompress

La biblioteca de abstracción de compresión de squash tiene una buena lista de algoritmos y un punto de referencia: https://quixdb.github.io/squash/

Hay un punto de referencia de compresión de texto aquí: http://mattmahoney.net/dc/text.html

El enfoque fácil es filtrar siempre dentro de las funciones crypto/crypto.go Encriptar / Desencriptar.

gzip-compressch-v1.patch.txt es una prueba de concepto diferencial que podría aplicarse al encabezado.

Gracias por probar @mappu , pero antes de implementar esto necesitamos acordar una estrategia. Las preguntas abiertas (desde lo alto de mi cabeza) son al menos:

  • ¿Cuándo se aplica la compresión? (¿Datos? ¿Metadatos / JSON?)
  • ¿Qué algoritmo debemos implementar? Creo que @klauspost tiene algunas sugerencias para nosotros :)
  • ¿Cómo almacenamos esto en un repositorio sin dañar a los clientes?

¿Cuándo se aplica la compresión? (¿Datos? ¿Metadatos / JSON?)

Datos, obviamente, sí.
Metadata / json, tal vez no tenga sentido, pero creo que podría ayudar para archivos de metadatos grandes ya que los datos JSON son principalmente ASCII y se beneficiarían de la codificación aritmética / fase huffman (gzip tiene).

Dado que los datos / metadatos siempre están encriptados, creo que agregar a la rutina de encriptar / desencriptar es una forma simple de capturar todos los usos, sin esto "Comencé a buscar en repository.go y encontré todos los lugares donde insertaría un paso de compresión / descompresión, y la complejidad añadida no fue nada bueno ". de @klauspost .
Además, dado que los blobs se almacenan con el nombre hash (texto plano) no hash (texto cifrado) {{obviamente es necesario para la deduplicación, de lo contrario el IV aleatorio destruiría la dedup}}, es seguro hacer esto sin dañar la dedup.

¿Qué algoritmo debemos implementar? Creo que @klauspost tiene algunas sugerencias para nosotros :)

no me importa Aunque estoy de acuerdo con @ThomasWaldmann en que debería ser configurable. Al menos para un caso de uso de --best y --fast .

Sugeriría gzip solo porque es puro, está en la biblioteca estándar de golang y recibe atención de rendimiento de Google. xz es una compresión lenta mucho más fuerte. lz4 es una compresión rápida mucho más débil. gzip es equilibrado y se ajusta fácilmente, incluso si no llega a ninguno de los extremos.

¿Cómo almacenamos esto en un repositorio sin dañar a los clientes?

El repositorio debe ser compatible solo en una dirección. Creo que está bien si el viejo restic no puede leer un nuevo repositorio, siempre que el nuevo restic pueda leer el antiguo repositorio.

Quizás podría agregar un byte de etiqueta después del MAC. No presente - sin compresión (antiguo restic). Entonces, el byte también puede indicar qué algoritmo de compresión se utilizó. 0x01 gzip 0x02 lz4 más o menos.

Parece que está presente el mismo (o peor) problema que en el ático (no se utilizan bytes de tipo / parámetro de compresión en el formato actual).

En ático (borg) tuve suerte ya que el formato anterior era solo gzip y el formato gzip se puede detectar desde los primeros 2 bytes. Así que mantuve gzip sin bytes adicionales (igual que los repositorios antiguos) y agregué bytes de tipo (para ninguna o otra compresión) que nunca son ambiguos con los primeros 2 bytes de gzip.

Obviamente, no puede hacerlo así si el formato anterior es solo datos brutos y arbitrarios.

No. Pero hay otras formas de señalar esta información. por ejemplo, si IV al comienzo del fragmento cifrado es exactamente "NEWFORMAT" (1 :: 2 ^ xyz posibilidad de colisión), entonces analice como nuevo formato. No es tan "limpio" pero creo que está bien en la práctica.

como se hace con EXTENDEDPROTOCOL en nmdc lock handshake.

Oh no, no haremos algo tan feo como esto, y no es necesario. Si decidimos implementar esto, los archivos del paquete tienen un campo type para cada blob. Este es un uint8 , y por el momento solo definido para data y tree , podemos agregar fácilmente compressed data y compressed tree . https://github.com/restic/restic/blob/master/doc/Design.md#pack -format

Por el momento, no considero esta función una prioridad alta.

Agregar nuevos tipos de blobs al formato de paquete está bien para la compresión de datos, pero no proporciona compresión de índice. Dado que los índices pueden volverse grandes y JSON tiene una buena relación de compresión, y tal vez el índice no tenga caché local, creo que también es importante comprimir los índices.

Es importante que new-restic funcione con el antiguo repositorio para permitir una fácil actualización. Debe ser transparente (preferido) o tener una herramienta restic upgrade-repo (no preferido).

Entonces, ¿qué tal esto?

Todos los comandos restic ya cargan primero + descifran el config .

  • si el primer byte config es { (es el primer byte del objeto json), entonces todo el repositorio tiene un formato antiguo (sin comprimir)
  • de lo contrario, el primer config byte es {tag byte} y el repositorio completo tiene un formato nuevo. {tag byte} al comienzo de los datos descifrados indica el formato de compresión. ejemplo 0x00 sin comprimir 0x01 gzip

Gracias por la propuesta. Creo que no es necesario comprimir la configuración, ya que este es solo un archivo muy pequeño y siempre puede permanecer en formato JSON, y podemos agregar campos según sea necesario, por ejemplo, si los archivos de índice están comprimidos o no.

Ayer encontré restic mientras buscaba una buena solución de respaldo. Una de mis principales preocupaciones es limitar la cantidad de espacio que ocupan mis datos. Especialmente si envío datos a lugares por los que pago, como S3. Dedup definitivamente ayudará, pero esperaba que la compresión fuera parte integral de una solución de respaldo ... En https://github.com/restic/restic/issues/21#issuecomment -185920429 usted ( @ fd0 ) dice esto es una prioridad baja, ¿podría explicar por qué? ¿Existe una hoja de ruta que pueda ver en cualquier lugar?

Además, +1. ;)

En este momento estoy trabajando para eliminar los datos de respaldo antiguos (# 518). No es fácil conseguir una compresión correcta y segura al mismo tiempo, y necesito pensar un poco más sobre cómo integrar esto en el formato del repositorio.

Implementaremos la compresión (después de todo eso de lo que se trata este problema), simplemente no se ha hecho todavía. restic es un proyecto bastante nuevo, por favor tengan paciencia con nosotros :)

Este problema está relacionado con el n. ° 116. Debido al cifrado, no podemos comprimir la copia de seguridad después con otras herramientas, ¿no es así? ¿Qué prioridad tiene entre la compresión y hacer que el cifrado sea opcional? (¡Apuesto por la compresión primero!)
_Lamento hacer presión sobre esto, ¡tienes razón en que el formato del repositorio debe tomarse con cuidado! _

Esto es fácil de responder: primero se implementará la compresión.

Esto se debe a que no tengo ningún plan en este momento para que el cifrado sea opcional. Creo que también es muy difícil hacerlo bien. Tendríamos que pensar en la integridad, ya que esto es algo que no debería ser opcional, pero (al menos por el momento) está estrechamente relacionado con el cifrado.

@ fd0 Gracias por responder a mi pregunta. Me hace desear que mis habilidades de desarrollo me ayuden en esto. Pero apenas he tocado ir, y la mayoría de mis otros xp están en scripts webdev o sysadmin.

Estoy totalmente de acuerdo en que debe asegurarse de que la compresión se realice de manera "correcta y segura". Si eso retrasa las cosas, que así sea. :sonrisa:

Implementé compresión rápida en restic aquí: https://github.com/viric/restic/tree/snappy

Es solo una propuesta. Básicamente, agregué compresión / descompresión rápida para blobs en paquetes, y uso un poco del byte de tipo blob como marca. También agregué un campo en los índices del paquete: PLength (longitud del texto sin formato), que hasta entonces no se almacenaba, sino que se calculaba como "bloblength - crypto.Extension".

Noté que para algunas de mis copias de seguridad no solo ocupa menos espacio, sino que incluso funciona más rápido (menos datos que manejar).

Todas las pruebas resticidas pasan bien. Puede funcionar sobre repositorios restic anteriores, pero el restic normal (el del maestro) no puede manejar los nuevos blobs.

Usé snappy (https://github.com/golang/snappy) porque pensé que afectaría menos el objetivo de velocidad de @ fd0.

Se agregó una recompensa de $ 50 por aterrizaje de compresión en el maestro

Bountysource

Como se mencionó anteriormente, debería haber una forma automatizada y no configurable para evitar intentar comprimir archivos no comprimibles como medios, cifrados o ya comprimidos. El problema se ve agravado por algunos formatos de contenedor como PDF, cuyo contenido a veces es comprimible, a veces no.

Sería más fácil usar un algoritmo que maneje esto de manera transparente, como el modo de compresión de tiempo constante mencionado en el primer comentario de @klauspost.

De lo contrario, habría una necesidad de listas de tipos de archivos: una lista negra que nunca se comprimirá, una lista blanca que siempre se comprimirá, una heurística para el resto que intenta comprimir una pequeña fracción del archivo y se rinde si la reducción de tamaño no es suficiente. sobre un umbral dado.

No estoy seguro de qué tan bien se mapeará esto en el fragmento, en lugar de a nivel de archivo.

Yo argumentaría en contra de agregarlo al pase de cifrado / descifrado.
No queremos mezclar diferentes tipos de datos, ya que algunos de ellos pueden ser predecibles y las longitudes de paquete / blob resultantes pueden filtrar información sobre el texto sin formato de los datos impredecibles / secretos.
Creo que debería ser por archivo, incluso si esto lo hace "menos agradable". Eso, sin embargo, viene con el beneficio de no tener que hacer una descompresión perdida de toneladas de archivos de paquetes (donde solo importa una gota en cada uno) para leer un archivo.

@teknico

Como se mencionó anteriormente, debería haber una forma automatizada y no configurable para evitar intentar comprimir archivos no comprimibles como medios, cifrados o ya comprimidos.

Mi paquete de desinflado modificado implementa la omisión de datos ya comprimidos y lo hace a una velocidad de ~ 250 MB / s por núcleo. El desinflado Go 1.7 solo lo admite en los niveles de compresión más rápidos.

Snappy y LZ4 admiten funciones de omisión similares.

Sería más fácil usar algún algoritmo que maneje esto de manera transparente, como el modo de compresión de tiempo constante.

Definitivamente debería ser una opción. En Go 1.7 (ahora llamado HuffmanOnly y mi equivalente) este modo admite ~ 200 MB / s por núcleo sin importar la entrada. Sin embargo, la compresión se ve seriamente obstaculizada en comparación con la "mejor velocidad", que normalmente funciona a 80 MB / s / núcleo.

@cfcs

Creo que debería ser por archivo, incluso si esto lo hace "menos agradable".

Generalmente estoy de acuerdo. Tendré que leer sobre restic. ¿El tamaño binario de cada tamaño de paquete está disponible sin cifrar?

@klauspost Parece que algunas de tus mejoras se fusionaron en el modo Go 1.7 DEFLATE "BestSpeed", ¿es correcto? Quizás eso sería un valor predeterminado razonable.

La ventaja de usar el formato DEFLATE es que hay muchos compresores diferentes disponibles que producen flujos de bits compatibles, por lo que es completamente transparente para el descompresor.

Debido a la naturaleza de cómo funciona restic (dividir archivos en blobs, solo maneja blobs después) la forma más fácil de agregar compresión es en el nivel de blobs. Quizás podríamos agregar algunas heurísticas para decidir si un blob debe comprimirse o no, pero ese puede ser el segundo paso.

Los blobs se combinan en archivos de paquete, que luego se almacenan en el repositorio. Un archivo de paquete contiene varios blobs (cifrados por separado), seguidos de un encabezado (cifrado), seguido de la longitud del encabezado (sin cifrar). Los atacantes sin la clave de descifrado solo ven el texto cifrado, la longitud del encabezado y la longitud del archivo. Entonces, según el tamaño del archivo del paquete y la longitud del encabezado, los atacantes podrían calcular el tamaño promedio de un blob en un archivo de paquete en particular, pero eso es todo. Los archivos de índice también contienen todos los datos (tamaño, tamaño encriptado y más tarde tal vez el tamaño comprimido), pero también están encriptados. No veo ningún riesgo aquí.

Una heurística de prueba "comprimible" es propensa a errores y bastante cara. Estimaría que sería difícil superar los 200 MB / s / core; esa es la velocidad de búsqueda de la orden 1 en el paquete de deduplicación en AMD64.

Además, dependería mucho del compresor utilizado. Snappy no podría comprimir datos aleatorios de base 64, pero desinflaría, por ejemplo, así que dejaría esa parte al compresor; la tenemos incorporada para Snappy, LZ4 y desinflar.

@ fd0 lo siento, quise decir por blob, no por archivo.
A menos que elijamos un algoritmo liviano, es probable que la compresión, que es algo pesada en la CPU, se convierta en un cuello de botella (al lado de AES, que en el futuro se espera que se encargue de AES-NI).

@ fd0 - Hice un "estimador de compresibilidad" rápido: https://play.golang.org/p/Ve5z3txkyz - estima la previsibilidad y la entropía de datos arbitrarios. Aunque, como mencioné, debería ser el compresor quien decida.

borg 1.1 tendrá 2 "decisiones de compresión":

  1. decidir por archivo en función de la coincidencia del patrón de ruta ( *.zip , *.mp3 , /htdocs/photos/* , ...)
  2. si no está decidido, decida por fragmento, use lz4 como prueba de compresibilidad; si se comprime, vuelva a comprimir con la compresión deseada (lz4, zlib, lzma), si no, no comprima.

@klauspost hm, esa prueba no es tan mala en mi máquina:

BenchmarkCompressibility-4           100      10345544 ns/op     810.84 MB/s

El código de referencia está aquí: https://gist.github.com/908c23123dda275a479cf931f2784f5d

Lz4 no tiene un codificador de entropía, por lo que será falso negativo muchas veces
¿probablemente?

Creo que necesitamos tres modos (globalmente):

  • Comprima todos los blobs de datos con un compresor de tiempo lineal (predeterminado)
  • Sin compresión
  • Compresión máxima (para personas con mucha potencia de CPU, pero solo pequeño ancho de banda)

Me gustaría comprimir siempre los objetos de árbol (JSON), por lo que deberíamos seleccionar un algoritmo adecuado para el texto ASCII.

De lo contrario, trabajaré con @viric para construir un prototipo, luego podremos razonar sobre una implementación concreta.

¿Pensamientos?

@klauspost hm, esa prueba no es tan mala en mi máquina

Siempre olvido lo increíblemente bien que puede hacer el nuevo compilador de Go. Al menos el doble de lo que esperaba.

Creo que necesitamos tres modos (globalmente):

Deflate hace los 3 bastante bien, aunque hay compresores más eficientes (en su mayoría LZMA). Por supuesto, desinflar sin compresión no es necesario, pero por supuesto es rápido y con una sobrecarga mínima, por lo que se podría utilizar un enfoque de desinflado general, con la posibilidad de especificar otros más adelante.

Empecé a buscar otra aceleración , que estaría entre el nivel 1 y Huffman tanto en términos de velocidad como de compresión. Sin embargo, el tiempo es un poco valioso en este momento, y todavía necesito probar un backport de algunos de los cambios finales de

Si solo desea un algoritmo de compresión único, debe echar un vistazo al nuevo contendiente zstd: https://github.com/facebook/zstd

Fue desarrollado por el mismo desarrollador que lz4 y tiene una mejor relación de compresión que gzip mientras que es más de 3 veces más rápido: https://code.facebook.com/posts/1658392934479273/smaller-and-faster-data-compression-with -zstandard /

zstd parece muy prometedor, aunque no pude encontrar una implementación en Go.

El sitio oficial http://facebook.github.io/zstd/#other -languages ​​enlaza con esta implementación de Go: https://github.com/DataDog/zstd

¿O te refieres a una implementación pura de Go?

Sí, significó una implementación pura de Go. Por el momento, restic no depende de ningún código C, e idealmente me gustaría mantenerlo así.

¿Existe alguna previsión para implementar la compresión?

La implementación de la compresión depende de cambiar el formato del repositorio (la planificación / ideas están en el n. ° 628), lo que requiere mucho cuidado. Entonces, no, no hay una fecha definitiva en la que se agrega la compresión;)

¿Hay algo que podamos hacer o contribuir para ayudar a que esto suceda?

No lo creo, lo siento: guiño:, solo necesita tiempo.

Así que pensé que podía usar mi banco de pruebas del n. ° 790 una vez más. En mi versión de restic eliminé todo el cifrado y luego hice una copia de seguridad completa una vez más. Tenía el mismo tamaño que el cifrado, sin sorpresas aquí. Pero luego comprimí el repositorio y lo que encontré es:

35G backup-unencrypted
6.4G    backup-unencrypted.tgz2

¡Que diferencia! A modo de comparación, aquí está el tamaño de un solo volcado de base de datos comprimido:

1.7G    single-backup.sql.gz

Tengo 29 de estos arriba. ¡Aproximadamente 100 veces más ahorros en comparación con las copias de seguridad regulares!

Como encontré todos los lugares donde se agregó el cifrado, creo que puedo agregar una compresión configurable muy simple con una implementación de stock gzip , con la posibilidad de usar un motor de compresión diferente en el futuro. ¿Alguna objeción?

(Probablemente me daré dos semanas de tardes para tener éxito o fracasar).

¡Gracias por su investigación y por publicar los resultados aquí! Esperaba resultados similares. Para ser honesto contigo: no fusionaré nada que elimine la criptografía, o incluso que la haga opcional. Eso es algo que podemos hacer más tarde, pero debe planificarse cuidadosamente.

Agregar compresión puede parecer fácil al principio, pero no lo es. Debemos tener mucho cuidado de no hacer que restic sea vulnerable a ataques inesperados (esto le ha sucedido al protocolo TLS varias veces seguidas (sí, soy consciente de que esta es una situación diferente)).

Lo más importante de todo el proyecto no es el código: es el formato del repositorio. Los usuarios nos confían sus datos y dependen de poder restaurarlos después de usar restic durante mucho tiempo, por lo que la estabilidad del formato del repositorio es de suma importancia. Entonces, para admitir la compresión, primero debemos decidir (e implementar) la próxima versión del formato del repositorio. La discusión está aquí: https://github.com/restic/restic/issues/628

Puedo ver que está muy ansioso por implementar esto (e incluso contribuir con el código), pero no dedique tiempo a esto hasta que estemos de acuerdo con el formato del repositorio y hayamos discutido todos los ángulos de este problema. ¡Gracias!

En cuanto a la criptografía eliminada, no voy a proponer fusionar eso. Hice eso solo para ver si funcionaba una compresión. Y sí, esto tuvo que planearse cuidadosamente (nadie quiere perder repentinamente la capacidad de verificar un repositorio con el cifrado deshabilitado).

Como usamos json.Unmarshal , podríamos agregar tantas claves nuevas a la configuración como queramos. Si no se encuentran en el JSON, solo mantendrán sus valores predeterminados.

La elección del algoritmo no es el punto principal, entendido: pero solo para referencia futura, Brotli parece un fuerte contendiente.

Por lo que sé, la compresión Brotli es muy lenta (iirc 60 veces gzip), por lo que se recomienda para los datos que se leen con mucha frecuencia en comparación con los que se escriben y comprimen, lo que probablemente no sea común para las copias de seguridad. Pero sí, no entremos en detalles todavía :)

Esto ofrece una buena descripción de los diferentes algoritmos de compresión.

Brotli siempre es más rápido o tiene una mejor compresión. Depende del nivel de compresión.

@ibib ¿Cómo llegas a esa conclusión? Me parece que brotli parece más lento que la mayoría de los demás (en los conjuntos de datos mixtos) sin lograr tasas de compresión particularmente sorprendentes. ¿Quizás sea mejor para tipos específicos de datos estructurados?

Como se enumera en las comparaciones en el punto de referencia de Squash, hay tres parámetros a seguir:

  • Relación de compresión lograda: es importante saber qué tan bien se comprime para ahorrar espacio en disco (y E / S en el backend).

  • Velocidad de compresión: es importante porque vamos a realizar esta operación cada vez que agregamos un bloque, por lo que realmente queremos algo que pueda mantenerse al día con AES-NI y E / S general para no convertirse en un cuello de botella. Probablemente no queramos elegir un algoritmo que comprima más lento de lo que descomprime, ya que tenemos el caso de uso opuesto de navegadores web que estos nuevos algoritmos (como zstd , lz4 , brotli ) están optimizados para (tenemos "comprimir a menudo, descomprimir pocas veces" en lugar de "comprimir una vez, descomprimir a menudo").

  • Velocidad de descompresión: La velocidad de descompresión solo es relevante cuando estamos restaurando. Si estamos de acuerdo con una restauración lenta, podemos aceptar una velocidad de descompresión lenta. Por otro lado, también tenemos metadatos que no queremos descomprimir lentamente, por lo que incluso podrían justificar dos algoritmos diferentes.

Parece que density encuentra entre los más rápidos, aunque no es particularmente eficiente en términos de relación de compresión. En términos de no ser un cuello de botella, parece que nos dará (en promedio) una relación de compresión de 2: 1 casi gratis. Si queremos 4: 1, tendremos que elegir un algoritmo diferente, pero luego terminaremos sentados y esperando.

También tenemos dos (¿al menos?) Tipos diferentes de datos: los índices; y los fragmentos de datos. Los dos se usan de manera diferente, y supongo que podría discutirse si tendría sentido elegir diferentes algoritmos para ellos. Personalmente, creo que deberíamos ceñirnos a un algoritmo (el que elijamos) para que la reimplementación de Restic (en un nuevo idioma o lo que sea) no resulte excesivamente difícil. Y para que no nos expongamos a errores de dos emocionantes algoritmos de compresión, ya que son difíciles de probar para casos de esquina.

Tengo que estar en desacuerdo con sus compensaciones recomendadas. Las copias de seguridad se pueden ejecutar en segundo plano en un momento conveniente (tal vez con buenos 10). Restaurarlos ocurre bajo presión de tiempo. La compensación relevante que veo es entre el tamaño del bloque y la relación de compresión. Los bloques demasiado pequeños no se comprimirán bien y aumentarán la sobrecarga de metadatos. Los bloques demasiado grandes reducen la tasa de deduplicación. Para la mayoría de los algoritmos de compresión, los ajustes de nivel más alto no mejorarán las relaciones de compresión para entradas pequeñas.

Además, las relaciones de compresión más altas permiten a los usuarios mantener más versiones de sus datos en el mismo espacio.

Recuerde que mis pruebas con snappy tuvieron el resultado de: 1) un tamaño de copia de seguridad más pequeño (se comprime, normal) y 2) una copia de seguridad y restauración más rápida (menos cifrado de datos, HMAC y transferencia). Usando una computadora portátil muy barata.

@cfcs Me
image
Aquí brotli tiene siempre la compresión mejor y más rápida.

@Crest Eso es bastante justo, probablemente tengamos diferentes casos de uso, simplemente no uso restic la misma manera que tú. Hago copias de seguridad de mi computadora portátil y quiero que termine rápidamente para poder irme con mi computadora portátil. Supongo que está hablando de copias de seguridad de servidores u otras máquinas conectadas constantemente donde la tasa de copia de seguridad no es tan importante. De manera similar, nunca necesito restaurar todos mis datos bajo presión de tiempo; si hay una presión de tiempo (¿porque lo usa en contextos profesionales?), puedo restaurar selectivamente los datos que necesito y proceder a hacer el resto más adelante.

Hace un muy buen punto sobre las "muchas veces pequeñas entradas";

@viric El efecto al que te refieres se considera en los puntos de referencia de Squash en la sección llamada Transfer + Processing :-)

@ibib ¡ah, te

@ibib, ¿puedes vincular de dónde

He estado haciendo algunas pruebas con brotli y zstd, y noté que mis resultados no coinciden en absoluto con los del punto de referencia de squash. Entonces entendí que ese punto de referencia tiene 1,5 años.

zstd funciona muy bien para mí. Relación rápida + alta, y su "nivel" permite un intervalo muy grande entre la relación rápida y alta. Gran cosa.

Brotli trabaja muy lento para mí, sin mejor relación de compresión que un zstd mucho más rápido. Y brotli parece centrado en pequeños archivos de textos en inglés (incluye un diccionario en inglés). Para compresión html o similar.

Puntos de referencia más recientes que encontré: https://github.com/inikep/lzbench

Así que lancé mi banco de pruebas una vez más contra zbackup con compresión LZMA.

35G backup-unencrypted
6.4G    backup-unencrypted.tgz
2.5G    zbackup

Impresionante, ¿no?

Basta decir que zbackup tiene su propio conjunto de limitaciones e inconvenientes.

Entonces, de acuerdo con el enlace @viric lzbench, el compresor más apropiado es uno que no ralentiza las copias de seguridad (¿alta velocidad de compresión ?,> 200 MB / seg), que en realidad tiene una buena relación de compresión (> = 50), ¿verdad?

Entonces, he filtrado los resultados de la tabla ordenada por razón.

También hice una búsqueda _rápida_ de implementaciones de Go (por eso las he guardado en la tabla). Tachado significa que no encontré ninguna implementación, lo que eliminó casi todo. Como solo fue una búsqueda rápida, conservo los resultados. Excepción para zstd que es solo un contenedor.

| Nombre del compresor | Compresión Descomprimir. Compr. tamaño | Proporción |
| --------------- | ----------- | ----------- | ----------- | ----- |
| zstd 1.1.4 -1 | 242 MB / s | 636 MB / s | 73654014 | 34,75 |
| lagarto 1.0 -30 | 258 MB / s | 867 MB / s | 85727429 | 40,45 |
| densidad 0,12,5 beta -3 | 253 MB / s | 235 MB / s | 87622980 | 41,34 |
| gipfeli 2016-07-13 | 233 MB / s | 451 MB / s | 87931759 | 41,49 |
| conciso 2011-12-24 -9 | 257 MB / s | 1263 MB / s | 90360813 | 42,63 |
| conciso 2011-12-24 -6 | 295 MB / s | 1268 MB / s | 92090898 | 43,45 |
| quicklz 1.5.0 -1 | 346 MB / s | 435 MB / s | 94720562 | 44,69 |
| lagarto 1.0 -20 | 284 MB / s | 1734 MB / s | 96924204 | 45,73 |
| conciso 2011-12-24 -3 | 352 MB / s | 1222 MB / s | 97255186 | 45,89 |
| lzrw 15-jul-1991 -4 | 243 MB / s | 392 MB / s | 100131356 | 47,24 |
| lzo1x 2.09 -1 | 394 MB / s | 551 MB / s | 100572537 | 47,45 |
| lz4 1.7.5 | 452 MB / s | 2244 MB / s | 100880800 | 47,60 |
| fastlz 0,1 -2 | 243 MB / s | 469 MB / s | 100906072 | 47,61 |
| lzo1y 2,09 -1 | 397 MB / s | 556 MB / s | 101258318 | 47,78 |
| lzo1x 2.09 -15 | 406 MB / s | 549 MB / s | 101462094 | 47,87 |
| densidad 0,12,5 beta -2 | 480 MB / s | 655 MB / s | 101706226 | 47,99 |
| lzf 3.6 -1 | 251 MB / s | 565 MB / s | 102041092 | 48,14 |
| snappy 1.1.4 | 327 MB / s | 1075 MB / s | 102146767 | 48,19 |
| blosclz 2015-11-10 -9 | 220 MB / s | 696 MB / s | 102817442 | 48,51 |
| conciso 2011-12-24 -0 | 384 MB / s | 1221 MB / s | 103072463 | 48,63 |
| lzo1x 2.09 -12 | 418 MB / s | 550 MB / s | 103238859 | 48,71 |
| lagarto 1.0 -10 | 360 MB / s | 2625 MB / s | 103402971 | 48,79 |
| fastlz 0,1 -1 | 235 MB / s | 461 MB / s | 104628084 | 49,37 |
| lzrw 15-jul-1991-3 | 226 MB / s | 449 MB / s | 105424168 | 49,74 |
| lzf 3.6 -0 | 244 MB / s | 550 MB / s | 105682088 | 49,86 |
| lzo1x 2.09 -11 | 424 MB / s | 560 MB / s | 106604629 | 50,30 |
| lz4fast 1.7.5 -3 | 522 MB / s | 2244 MB / s | 107066190 | 50,52 |
| tornado 0.6a -1 | 233 MB / s | 334 MB / s | 107381846 | 50,66 |
| memcpy | 8657 MB / s | 8891 MB / s | 211947520 | 100,00 |

¿LZ4 parece el compresor más apropiado?

Supongo que quiere lz4 (> = 1.7.0 r129) y zstd (> = 1.3.0), si corresponde. también los usamos para borgbackup.

PERO zstd es muy sintonizable con un solo entero, desde la velocidad lz4 hasta mejor
que la compresión xz. Eso haría a los usuarios felices de densos más lentos
compresión y los de compresión rápida. Sin mencionar que zstd
se descomprime muy rápido, independientemente del esfuerzo de compresión.

lz4 tiene un propósito bastante limitado.

El sábado 16 de diciembre de 2017 a las 09:50:49 AM -0800, TW escribió:

Supongo que quiere lz4 y zstd, si corresponde. también los usamos para borgbackup.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/restic/restic/issues/21#issuecomment -352199097

-
(Escriu-me xifrat si saps PGP / Escribe cifrado si conoces PGP)
Clave PGP 7CBD1DA5 - https://emailselfdefense.fsf.org/

Bueno ... de acuerdo con https://github.com/restic/restic/issues/21#issuecomment -250983311 de mantener libre la dependencia restic, zstd no es una opción, por ahora. Además, hay algunos hilos sobre cuestiones de patentes / licencias.

En cuanto a xz y relaciones de compresión altas, incluso para las configuraciones de compresión más bajas, según la tabla, la compresión más rápida es de aproximadamente 15 MB / seg.

Si se reduce el requisito de copia de seguridad rápida, digamos,> = 30 MB / seg, podríamos agregar:

| Nombre del compresor | Compresión Descomprimir. Compr. tamaño | Proporción |
| --------------- | ----------- | ----------- | ----------- | ----- |
| xz 5.2.3 -9 | 1,70 MB / s | 56 MB / s | 48745306 | 23,00 |
| xz 5.2.3 -6 | 1,89 MB / s | 58 MB / s | 49195929 | 23,21 |
| xz 5.2.3 -3 | 4,18 MB / s | 55 MB / s | 55745125 | 26,30 |
| zstd 1.1.4 -8 | 30 MB / s | 609 MB / s | 61021141 | 28,79 |
| zling 2016-01-10 -2 | 32 MB / s | 136 MB / s | 61917662 | 29,21 |
| xz 5.2.3 -0 | 15 MB / s | 44 MB / s | 62579435 | 29,53 |
| zling 2016-01-10 -0 | 38 MB / s | 134 MB / s | 63407921 | 29,92 |
| zstd 1.1.4 -5 | 88 MB / s | 553 MB / s | 64998793 | 30,67 |
| lzfse 2017-03-08 | 48 MB / s | 592 MB / s | 67624281 | 31,91 |
| libdeflate 0,7 -6 | 64 MB / s | 609 MB / s | 67928189 | 32.05 |
| brotli 2017-03-10 -2 | 98 MB / s | 289 MB / s | 68085200 | 32,12 |
| zstd 1.1.4 -2 | 185 MB / s | 587 MB / s | 70164775 | 33,10 |
| tornado 0.6a -4 | 91 MB / s | 197 MB / s | 70513617 | 33,27 |
| libdeflate 0,7 -3 | 96 MB / s | 602 MB / s | 70668968 | 33,34 |
| xpack 2016-06-02 -1 | 98 MB / s | 506 MB / s | 71090065 | 33,54 |
| tornado 0.6a -3 | 119 MB / s | 188 MB / s | 72662044 | 34,28 |
| libdeflate 0,7 -1 | 117 MB / s | 570 MB / s | 73318371 | 34,59 |
| lagarto 1.0 -42 | 90 MB / s | 938 MB / s | 73350988 | 34,61 |
| zstd 1.1.4 -1 | 242 MB / s | 636 MB / s | 73654014 | 34,75 |

Hay varias implementaciones de desinflado, pero no estoy seguro de si son comparables.
Izquierda xz para referencia
zstd parece tan prometedor. Lástima que no haya implementación de Go

@viric zstd no es del todo velocidad lz4.

pero si uno quisiera tener un solo compresor en lugar de varios, zstd es más flexible.

Perdona mi tardanza. Algunos comentarios:

Velocidad de compresión: es importante porque vamos a realizar esta operación cada vez que agregamos un bloque, por lo que realmente queremos algo que pueda mantenerse al día con AES-NI y E / S general para no convertirse en un cuello de botella. Probablemente no queramos elegir un algoritmo que se comprima más lento de lo que se descomprime, ya que tenemos el caso de uso opuesto de los navegadores web para los que estos nuevos algoritmos (como zstd, lz4, brotli) están optimizados (tenemos "comprimir a menudo, descomprimir pocas veces" en lugar de "comprimir una vez, descomprimir a menudo").

No, no es necesario comprimir a velocidades AES aceleradas por hardware. La compresión se trata de cambiar tiempo por tamaño. Es de esperar que las copias de seguridad comprimidas tarden más.

Por ejemplo, en lugar de usar restic en mis copias de seguridad personales, sigo usando Obnam, porque en uno de los pequeños servidores en los que las guardo, si no estuvieran comprimidas, no encajarían. Las copias de seguridad ya llevan horas y se ejecutan en segundo plano, por lo que ni siquiera me doy cuenta.

No me importa si las copias de seguridad comprimidas de restic tardan más. De hecho, espero que lo hagan, y es la compensación que necesito hacer. Sin este tipo de compresión, restic no me sería útil.

Velocidad de descompresión: La velocidad de descompresión solo es relevante cuando estamos restaurando. Si estamos de acuerdo con una restauración lenta, podemos aceptar una velocidad de descompresión lenta. Por otro lado, también tenemos metadatos que no queremos descomprimir lentamente, por lo que incluso podrían justificar dos algoritmos diferentes.

Las restauraciones se realizan con mucha menos frecuencia que las copias de seguridad, por lo que la velocidad de descompresión no es tan importante. Alguien mencionó que a menudo se realizan bajo presión de tiempo: esto es cierto, pero no significa que las restauraciones deban ser tan rápidas como las copias de seguridad, o en cualquier lugar cercano.

También tenemos dos (¿al menos?) Tipos diferentes de datos: los índices; y los fragmentos de datos. Los dos se usan de manera diferente, y supongo que podría discutirse si tendría sentido elegir diferentes algoritmos para ellos.

Puede que no sea necesario (o necesariamente una buena idea) comprimir los índices en absoluto. Al ser índices, parece poco probable que se compriman bien en primer lugar, ya que todo su propósito es almacenar datos únicos.

Personalmente, creo que deberíamos ceñirnos a un algoritmo (el que elijamos) para que la reimplementación de Restic (en un nuevo idioma o lo que sea) no resulte excesivamente difícil. Y para que no nos expongamos a errores de dos emocionantes algoritmos de compresión, ya que son difíciles de probar para casos de esquina.

Entiendo estas preocupaciones, pero creo que sería un error. Como mínimo, el formato de repositorio debe permitir múltiples algoritmos de compresión para que se puedan agregar nuevos en el futuro. Probablemente debería haber módulos conectables para la compresión para que los usuarios puedan seleccionar los que quieren usar, por ejemplo, podría imaginar paquetes Debian como restic-xz , restic-zstd , etc.que los usuarios podrían instalar si quisieran. utilizar esos algoritmos. La compresión de los datos de respaldo debe abstraerse de modo que a restic le entregue algunos datos a una función de compresión y los vuelva a comprimir, y a restic no le debería importar lo que suceda en el medio; lo mismo para la descompresión.

Si se reduce el requisito de copia de seguridad rápida, digamos,> = 30 MB / seg, podríamos agregar

Eso me parece razonable. Recuerde que las copias de seguridad locales son de un solo tipo; es menos probable que las copias de seguridad de la red sufran un cuello de botella debido a la velocidad de compresión.

Pero, de nuevo, los usuarios deberían poder ajustar esto para que puedan seleccionar la solución adecuada para sus necesidades.

Se agregó una recompensa de 10 $ por una: cerveza: :)
image

🍺 ++

Aquí hay un enlace a BountySource si alguien más quisiera contribuir
badge
https://api.bountysource.com/badge/issue?issue_id=6096108

Me pregunto si esto se puede implementar de una manera configurable por el usuario, de modo que la elección de la velocidad frente al tamaño quede en manos del usuario. Preferiría una compresión más alta por defecto.

Decidamos cuando lleguemos. Para el registro: estoy de acuerdo con darle al usuario un poco de control en términos de velocidad versus tamaño.

+1 para restic que necesita una implementación de compresión. Estoy usando restic para hacer una copia de seguridad de las imágenes de la máquina virtual para retroceder y me encantaría poder comprimirlas antes de cargarlas. En mi caso de uso, cambiaría una cantidad casi infinita de tiempo / CPU para reducir el tamaño de los datos transferidos / almacenados. Sin embargo, me doy cuenta de que la velocidad es una preocupación mayor para algunos. Tener una arquitectura conectable donde se pueden seleccionar múltiples algoritmos es clave.

Me complace ayudar a probar, ya que esto se analiza más a fondo.

@ fd0 Ha pasado un tiempo desde que trabajé en la base del código restic. ¿Es posible que me dé una dirección rápida sobre un buen enfoque y hacia dónde debería mirar?

@klauspost No se trata tanto de agregar compresión a nivel técnico, es bastante fácil de hacer, sino de cómo manejamos la actualización del formato de repositorio de una manera compatible con versiones anteriores. Actualmente estoy ocupado reescribiendo la parte del archivador (para que las cosas feas como el # 549 desaparezcan), después de eso me gustaría agregar compresión y luego cambiar al repositorio v2.

¿Cuál es su opinión sobre qué algoritmo de compresión deberíamos usar? Estoy pensando en admitir tres modos:
1) Sin compresión
2) Compresión de "tiempo lineal" (no agrega mucha carga de CPU)
3) "Compresión máxima"

Tal vez el primer y segundo modo sea el mismo, no estoy seguro si

Sería increíble poder usar algo como zstd, pero como código nativo de Go. Damian insinuó que puede que no sea mucho trabajo portar la versión Java o C: https://twitter.com/dgryski/status/947259359628738560, ¿hay algo que pueda hacer para que te interese probar eso? :)

He examinado las especificaciones del formato zstd y, para mí, no es trivial de implementar (bueno). Las fuentes de Java son solo descompresión.

Para una compresión rápida, LZ4 debería funcionar muy bien. El puerto Go es excelente. zstd sería mejor, pero optaría por un paquete probado y comprobado, a menos que desee utilizar la implementación de cgo.

Para el medio de la carretera, la compresión de desinflado sigue siendo una buena velocidad / compresión. Bien probado, etc.

La alta compresión es un poco más complicada. Sin embargo, parece que hay una implementación nativa de LZMA (2) Go en el paquete github.com/ulikunitz/xz . Hay algunas advertencias sobre la estabilidad y el rendimiento en el archivo README. No es necesario el contenedor xz, ya que ya tiene el tamaño y el hash sin comprimir. Puedo darle una vuelta y ver cómo se compara.

Eché un vistazo a la fuente para encontrar el lugar natural para insertar el paso de compresión. Lo que tenía sentido para mí era tener compresión aquí y descompresión aquí . Pero veo el desafío de identificar y realizar un seguimiento de la compresión.

También puede echar un vistazo a un "estimador de compresibilidad" que hice. Le dará una estimación rápida de qué tan comprimible es una masa de datos. Por lo general, opera a> 500 MB / s, por lo que podría usarse para rechazar rápidamente datos difíciles de comprimir.

También puede echar un vistazo a un "estimador de compresibilidad" que hice. Le dará una estimación rápida de qué tan comprimible es una masa de datos. Por lo general, opera a> 500 MB / s, por lo que podría usarse para rechazar rápidamente datos difíciles de comprimir.

¡Me encanta el estimador de compresibilidad! Evitar los intentos de comprimir datos no comprimibles ganaría mucha velocidad.

Zstd tiene algo como eso integrado: [1]

Zstd pasa más rápido sobre datos incompresibles. Espere algo> 1 GB / s

Aunque no he encontrado ningún punto de referencia explícito de eso.

El paquete xz parece una buena oferta para lzma. Hice algunas pruebas rápidas con la configuración predeterminada:

| algoritmo | nivel | insize | descomunal | millis | mb / s | relación |
| ----------- | ------- | ------------ | ----------- | ---- ---- | -------- | -------- |
| lz4 | - | 1000000000 | 625968314 | 5454 | 174,85 | 62,60% |
| flatekp | 1 | 1000000000 | 391051805 | 12367 | 77,11 | 39,11% |
| flatekp | 5 | 1000000000 | 342561367 | 20164 | 47,3 | 34,26% |
| flatekp | 9 | 1000000000 | 324191728 | 43351 | 22 | 32,42% |
| lzma2 | | 1000000000 | 291731178 | 149437 | 6,38 | 29,17% |
| lzma | | 1000000000 | 291688775 | 161125 | 5,92 | 29,17% |

Compensación de velocidad / compresión muy razonable. Todos son rendimiento de un solo núcleo en enwik9 : cuerpo de texto de compresión media. Obviamente, no tuve tiempo para probar una imagen de VM completa o algo como el corpus de 10GB con más contenido mixto.

No parece que lzma2 ofrezca mucho en su implementación actual sobre lzma estándar. Dado que se trata de bloques pequeños, la diferencia debería ser bastante pequeña.

Zstd tiene algo así incorporado

Sí, al igual que lz4 y desinflar, sin embargo, no lo he visto tan rápido como una función dedicada.

zstd es realmente impresionante, sin duda. Benchmarks usando la implementación de cgo:

| nivel | insize | descomunal | millis | mb / s | relación |
| ------- | ------------ | ----------- | -------- | ------- - | -------- |
| 1 | 1000000000 | 358512492 | 5100 | 186,96 | 35,85% |
| 2 | 1000000000 | 332265582 | 6264 | 152,24 | 33,23% |
| 3 | 1000000000 | 314403327 | 8099 | 117,75 | 31,44% |
| 4 | 1000000000 | 310346439 | 8588 | 111.04 | 31,03% |
| 5 | 1000000000 | 305644452 | 12739 | 74,86 | 30,56% |
| 6 | 1000000000 | 292551252 | 18531 | 51,46 | 29,26% |
| 7 | 1000000000 | 287414827 | 23212 | 41,08 | 28,74% |
| 8 | 1000000000 | 282783804 | 27811 | 34,29 | 28,28% |
| 9 | 1000000000 | 280432907 | 31752 | 30,03 | 28,04% |

Perdóname si me perdí algo, pero no vi que estas preguntas respondieran antes.

  1. Parece que estamos hablando de compresión a nivel de fragmentos, no a nivel de archivos, ¿correcto?
  2. Si es así, eso obviamente limita la efectividad, ya que los datos duplicados en varios fragmentos de un solo archivo se almacenarán y comprimirán para cada fragmento.
  3. Sin embargo, eso obviamente también depende del tamaño del fragmento.
  4. Entonces, ¿cuál es el tamaño medio de un fragmento? Parece que este es un factor importante en la utilidad de la compresión.
  5. Si el tamaño del fragmento es bastante pequeño, tal vez deberíamos considerar la compresión de fragmentos previos de archivo completo para archivos altamente comprimibles (por ejemplo, utilizando el estimador de @klauspost ). Por ejemplo, es probable que un archivo de texto de 50 MB (por ejemplo, archivos de registro, archivos grandes en modo Org, etc.) sea altamente comprimible como un solo archivo. Pero si se fragmenta primero y luego cada fragmento se comprime individualmente, sin compartir un índice, eso limitará en gran medida la efectividad de la compresión (IIUC).

Gracias.

Si comprimiéramos archivos completos, eso podría alterar el algoritmo de deduplicación, posiblemente haciéndolo menos eficiente.

Aparte de eso, no olvidemos que cualquier compresión, si bien ofrece enormes ventajas en cuanto al espacio , nos abre a un ataque de canal lateral. A partir del tamaño de los datos comprimidos, se puede hacer una suposición fundamentada sobre el contenido de los datos. Creo que esto se mencionó antes, pero aún así.

@alphapapa

Parece que estamos hablando de compresión a nivel de fragmentos, no a nivel de archivos, ¿correcto?

Sí, a nivel de fragmentos.

Si es así, eso obviamente limita la efectividad, ya que los datos duplicados en varios fragmentos de un solo archivo se almacenarán y comprimirán para cada fragmento. Sin embargo, eso obviamente también depende del tamaño del fragmento. Entonces, ¿cuál es el tamaño medio de un fragmento? Parece que este es un factor importante en la utilidad de la compresión.

Nuestro objetivo es 1MiB, pero puede ser tan grande como 8MiB.

Si el tamaño del fragmento es bastante pequeño, tal vez deberíamos considerar la compresión de fragmentos previos de archivo completo para archivos altamente comprimibles (por ejemplo, utilizando el estimador de @klauspost ). Por ejemplo, es probable que un archivo de texto de 50 MB (por ejemplo, archivos de registro, archivos grandes en modo Org, etc.) sea altamente comprimible como un solo archivo. Pero si se fragmenta primero y luego cada fragmento se comprime individualmente, sin compartir un índice, eso limitará en gran medida la efectividad de la compresión (IIUC).

Al principio, me gustaría integrar la compresión a nivel de fragmentos y ver qué tan bien funciona en escenarios de la vida real. Podemos retomar esta idea más tarde.

@klauspost Muchas gracias por tomarse el tiempo para comparar algunos algoritmos / implementaciones y sus recomendaciones, ¡se lo agradezco! Si bien sería bueno tener zstd, creo que no depender de cgo es mucho más importante para el proyecto en su conjunto. Y usar un estimador de compresibilidad es una gran idea, eso me encanta.

Los lugares que mencionaste para agregar compresión / descompresión suenan bien, pero necesitamos rastrear los metadatos para eso en otro lugar. Creo que probablemente agregaremos significado a los bits en el byte en el encabezado del paquete, consulte http://restic.readthedocs.io/en/latest/100_references.html#pack -format. Esta es la parte que debe hacerse con mucho cuidado.

Entonces, déjeme terminar con el # 1494, luego veremos que esto se resuelva.

@sanmai re: side-channels: lo
Se sugirieron varias soluciones, personalmente me contentaría con:

  • tener opciones de configuración para el uso de compresión en listas blancas / negras (similar a lo que tenemos para la inclusión de archivos)

Otra idea era tratar de ocultar los límites de los fragmentos en los archivos de paquete, lo que teóricamente lo haría más difícil, pero creo que aún podría cronometrar las escrituras de red y los canales laterales, como en qué extensión del sistema de archivos se escribió el fragmento. y así sucesivamente podrían usarse para inferir los límites, por lo que creo que lo más seguro / más fácil sería simplemente aconsejar no comprimir datos confidenciales.

¡Esto sería genial! : cerveza: + $ 10

Simplemente lanzándolo por ahí, pero dejando de lado lzma o cualquiera de los algoritmos de compresión más generales, ¿qué pasa con la codificación de longitud de ejecución o el aplastamiento cero? ¿O esto no sería lo suficientemente útil para suficientes personas?

(Tengo un perro en esta cacería, a menudo hago copias de seguridad de archivos WAV enormes con mucho silencio).

+ $ 15

Simplemente lanzándolo por ahí, pero dejando de lado lzma o cualquiera de los algoritmos de compresión más generales, ¿qué pasa con la codificación de longitud de ejecución o el aplastamiento cero? ¿O esto no sería lo suficientemente útil para suficientes personas?

También es útil para realizar copias de seguridad de unidades de VM con espacio mayormente vacío / archivos dispersos (no estoy seguro si restic ya admite copias de seguridad / restauración de archivos dispersos)

@bherila restic aún no admite el archivado / restauración de archivos dispersos, los archivos se almacenarán en el repositorio como si solo contuvieran muchos ceros. Estos grandes bloques de ceros se deduplican, por lo que no ocuparán mucho espacio en el repositorio. Sin embargo, para la restauración, terminará con un archivo normal (no disperso) sin "agujeros".

Solo quería comprobar, ¿ya existe algún tipo de compresión? He hecho una copia de seguridad de varias computadoras, incluida una con 50 GB de datos, y obtengo un número mucho menor en el servidor:

# du -shc /home/restic/
40G     /home/restic/
40G     total

@Alwaysin Probablemente sea la deduplicación , a menos que se hayan excluido algunos archivos, por supuesto.

@rawtaz gracias, no estaba al tanto de la deduplicación, ¡debe ser eso!

El aplastamiento de

@klauspost, ¿viste esto? https://github.com/mvdan/zstd

Sí, pero honestamente, un decodificador de flujo es la parte fácil. He terminado la decodificación / codificación FSE y tengo un codificador Huffman listo. Una vez que se realiza la decodificación de Huffman, un decodificador de flujo zstd es bastante sencillo, y el codificador completo es la parte final.

LZ4 es perfectamente suficiente y también sería una victoria rápida.

¿Por qué no agregar lz4 y crear otro PR para admitir zstd?

¿Por qué no agregar lz4 y crear otro PR para admitir zstd?

@ dave-fl porque debemos tener mucho cuidado cuando modificamos el formato del repositorio. Debe hacerse de una manera compatible con versiones anteriores. La parte más importante de todo el proyecto es el formato de repositorio, no la implementación. La gente depende de nosotros para no estropear el formato y poder restaurar sus datos :)

Creo que no podemos esperar demasiado con la compresión. Acabo de hacer algunas pruebas en algunos repositorios de copias de seguridad de servidores, ¡exactamente no gano nada cuando gzipé el repositorio! Como @Alwaysin , ya gano un 30% con la deduplicación.

Acerca de la forma compatible con versiones anteriores, ¿quiere decir que Restic debería leer ambos formatos o herramientas para migrar del antiguo al nuevo? Cuando Restic no está en v1.0.0, creo que está bien migrar.

Acabo de hacer algunas pruebas en algunos repositorios de copias de seguridad de servidores, ¡exactamente no gano nada cuando gzipé el repositorio!

Uhm, eso es lo esperado: todos los datos en el repositorio están encriptados, por lo que apenas se pueden comprimir. Si se utiliza compresión, se debe realizar en los datos antes de cifrarlos.

No veo cómo el uso de LZ4 hace que las cosas no sean compatibles con versiones anteriores. La compresión es compresión. ¿Por qué no admitir varios formatos?

Tienes razón, no pensé en eso.
Sin embargo, cuando gzip la fuente no gano más del 30%, la deduplicación ya es muy eficiente en un directorio grande con muchos duplicados. Pero, por supuesto, con ambos puede ser impresionante.
Con zpaq, que realiza compresión y deduplicación, gano un poco más, no tanto.
Estoy muy abierto a probar una rama con compresión, ¡no importa si no es compatible!

No veo cómo el uso de LZ4 hace que las cosas no sean compatibles con versiones anteriores. La compresión es compresión. ¿Por qué no admitir varios formatos?

¿Qué sucede si 2 clientes están usando el mismo repositorio pero 1 de ellos usa una versión anterior de restic que no admite compresión? Esta característica debe diseñarse cuidadosamente teniendo en cuenta todos los posibles casos de esquina.

Preferiría sin compresión sobre una solución de trabajo a la mitad que posiblemente rompa las copias de seguridad anteriores.

Creo que ha habido suficiente discusión sobre el tema de agregar compresión. Puedo ver que es una característica muy esperada. Abordaré esto después de terminar el nuevo código de archivador (ver # 1494).

Por favor, no agregue más comentarios, ¡gracias!

@dimejo Lo que estás diciendo no tiene nada que ver con lo que te he propuesto. El hecho de que elija implementar zstd o lz4 afectaría a ambos casos.

Me atrevo a decir que la versión CGO de zstd parece algo portátil :)

Miré cuán factible sería escribir una implementación golang de zstd, muy brevemente, basada en la especificación .

zstd en su mayoría, todos los algoritmos internos, pero (opcionalmente) se basa en la suma de verificación de errores, y hay un puerto golang de eso . dado que los bits opcionales son, bueno, opcionales, no tendría que implementar esas partes para obtener soporte zstd para un lector / escritor en restic. zstd admite el concepto de "dictionarios" para optimizar la compresión; no estoy seguro de cómo interactuaría con restict, pero sería un área de investigación interesante para comprimir partes específicas del archivo, por ejemplo, JSON o flujos de metadatos. de lo contrario, esa implementación también podría omitirse, ya que es opcional.

Donde se vuelve más complicado, por supuesto, es donde entra en juego la codificación de entropía. Zstd usa un enfoque novedoso llamado Entropía de estado finito (FSE, una variación de [ANS] (https://en.wikipedia.org/wiki/Asymmetric_numeral_systems#, de los cuales solo existe una implementación en C. Otros bits de codificación de entropía se implementan con codificación huffman , de los cuales hay varias implementaciones, incluidas dos en la biblioteca estándar: una en compress.flate y otra en net.http2.hpack , que es más bien extraño.

Por lo que puedo decir, todo lo demás está pegado encima de eso ... Algunos árboles, secuencias, marcos y bloques de Huffman. También hay propiedades interesantes en la forma en que se construyen los bloques y los marcos que podrían mapearse bien en blobs resticulares, lo que podría hacer posible comprimir el repositorio en su conjunto mientras se mantienen los blobs separados en el interior, aunque no he analizado eso en detalles. . También puede hacer que el acoplamiento entre el formato del repositorio y la compresión sea inaceptable.

zstd es mucho más complicado que gzip o xzip, con aproximadamente 70k líneas de código (según cloc) en comparación con 36k y 12k, respectivamente. eso incluye pruebas, sin embargo, que son numerosas: cuando se ignoran, la implementación en sí es comparable con gzip (~ 34k).

así que, en resumen, es solo cuestión de tiempo antes de que esto se implemente en marcha. Creo que un motor de este tipo también podría aprovechar el paralelismo de golang porque los "marcos" de zstd son independientes entre sí. Sin embargo, no me queda claro cómo se usan los marcos: la mayoría de las transmisiones que probé tenían solo uno ( zstd /etc/motd ) o dos ( zstd isos/Fedora-Workstation-Live-x86_64-27-1.6.iso ) marcos (según lo encontrado por binwalk -R "\x28\xb5\x2f\xfd" ), así que tal vez no haya tanta ganancia allí, porque los bloques están interrelacionados y son menos paralelizables ...

de todos modos, todo es discutible a menos que alguien aquí realmente quiera sentarse y transferir eso, pero pensé que compartiría lo que encontré mientras leía la cosa ... considerando que zstd es una expansión de LZMA parte de la familia de compresores LZ77, no debería no sería factible babor ...

¿Alguna actualización sobre la compresión? Sé que mucha gente quiere esperar zstd , pero ¿qué sería de malo implementar lz4 o lzo o lzma ?

Si hubiera una actualización, este problema se actualizaría.

Mientras tanto, tratemos de respetar la solicitud del autor:

Por favor, no agregue más comentarios, ¡gracias!

@ fd0 , solo quería señalar que parece haber una implementación Go pura del algoritmo zstd https://github.com/klauspost/compress/tree/master/zstd . No lo he probado yo mismo. Pero esto me entusiasmó con la posibilidad de soporte de compresión en restic.

No conozco las cosas de Go zstd (¿velocidad? ¿Calidad de código? ¿Mantenimiento?), Pero las cosas de C zstd son todo lo que necesita una herramienta de copia de seguridad, ya que admite una amplia gama de compresión rápida / pequeña a más lenta / alta.

Si no tuviéramos ya todos los otros algoritmos de compresión (lz4, zlib, lzma) en borgbackup y comenzáramos a agregar compresión ahora, supongo que podríamos vivir con solo zstd y ninguno.

Como cuestión de gusto / preferencia, el valor predeterminado podría ser ninguno (como era antes) o un nivel zstd muy rápido (que en general aún hace que la mayoría de las copias de seguridad sean más rápidas ya que hay menos datos para transferir).

Hola,
en mi opinión, la compresión no es una característica imprescindible para restic. He comparado la copia de seguridad de mis datos realizada con Duplicati (con compresión) y restic (sin compresión) y el espacio utilizado en general fue realmente similar.
Necesito restic solo para obtener una copia de seguridad incremental rápida y confiable. No es necesario romper el bit ...
La restauración también es importante y el restic es adecuado para la recuperación ante desastres. Duplicati es una pesadilla porque si pierde la base de datos local, la tarea de reparación lleva días ...

¡Gracias @ fd0 y gracias a todos los colaboradores!

@filippobottega si no vio una gran diferencia en su experimento, eso significa:

  • que sus datos no eran (mucho) comprimibles (pero este no es el caso en general), o
  • que duplicati tenía una peor eficiencia de almacenamiento no relacionada con la compresión (por ejemplo, debido a un formato de almacenamiento diferente, granularidad, algoritmos, lo que sea ...), por lo que los ahorros de compresión se compensaron con pérdidas en otras áreas.

ambos no significa que la compresión sea inútil.

@ThomasWaldmann No veo una gran diferencia por la primera razón.
Hoy en día, los datos ya están comprimidos de muchas formas: docx, xlsx, pptx, zip, 7z, jpeg, tif, etc., son todos formatos comprimidos. Y también las imágenes iso contienen archivos comprimidos. Por esta razón, la compresión no tiene sentido en restic, creo.

@filippobottega Su punto de vista es un poco estrecho sobre los datos que la gente está usando restic para respaldar. ¿Qué pasa con los volcados de SQL, el código fuente, los conjuntos de datos, las imágenes sin procesar, etc.? La deduplicación está haciendo un gran trabajo al reducir el tamaño delta entre copias de seguridad, sin embargo, no hace nada para reducir el tamaño original del conjunto de datos. En el caso de formatos sin comprimir, esto podría significar muchos gigabytes. Sin mencionar que almacenar un formato sin comprimir y luego comprimir + deduplicar podría producir mejores resultados que deduplicar los archivos ya comprimidos.

Los volcados de SQL fueron lo primero que pensé, pero restic también hace una copia de seguridad de mi servidor de correo y aparentemente obtiene una mejor compresión general basada en algunas instantáneas RAR que tomé al pasar de Duplicati a restic.

Puedo ver el caso de uso para hacer que la compresión sea opcional y tener una lista predeterminada de tipos de archivos, pero la compresión me ahorraría una cantidad razonable de dinero.

@mrschyte

Su punto de vista es un poco estrecho sobre qué datos están usando las personas restic para respaldar.

Ahora ahora, no hay necesidad de ser personal. Su perspectiva es tan válida como la tuya y vale la pena considerarla. Descubrí que la mayoría de los datos de los que hago copias de seguridad ya están comprimidos debido a los formatos de archivo.

¿Qué pasa con los volcados de SQL?

¿Realmente almacena sus volcados SQL sin comprimir? Utilizo todos los míos antes de hacer una copia de seguridad, porque no tengo necesidad de almacenarlos sin procesar.

código fuente, conjuntos de datos, imágenes sin procesar, etc.

Creo que el único caso de uso válido para la copia de seguridad comprimida es con archivos grandes sin comprimir con mucha repetición _ que se están utilizando activamente y, por lo tanto, no están almacenados comprimidos ya_. En mi experiencia (que incluye años de gestión de datos de otras personas), muy pocos datos entran en esta categoría. Al menos, no lo suficiente como para marcar una gran diferencia en esos casos.

sin embargo, no hace nada para reducir el tamaño original del conjunto de datos.

Podría decirse que ese no es el trabajo de un programa de respaldo. No debería tocar los datos originales.

Sin mencionar que almacenar un formato sin comprimir y luego comprimir + deduplicar podría producir mejores resultados que deduplicar los archivos ya comprimidos.

Muchos algoritmos de compresión se basan en la duplicación para hacer su trabajo (ver los diccionarios de flate), así que no estoy convencido por esto _ en general_ aunque estoy de acuerdo en que esto es correcto al menos algunas veces.

(No estoy diciendo que la compresión en restic sea mala cuando se hace correctamente, solo estoy argumentando que no tiene por qué ser una prioridad, especialmente en comparación con los problemas de rendimiento persistentes, y debemos respetar las limitaciones de tiempo de @ fd0 y deseos con respecto a la visión.)

@mholt Estoy de acuerdo en general, sin embargo, hacer una copia de seguridad de root (a través de algún volcado o incluso iterando en el contenido de /), produce una buena relación de compresión para mí. No es esencial , ya que el total utilizado ya es pequeño, pero obtengo alrededor del 50% de ahorro, y siempre es bueno tenerlo "gratis" en lo que respecta al usuario final.

Prueba esta prueba.

  1. tomar un volcado de SQL o algún otro archivo sin comprimir. Comprímalo y luego
    use restic respaldarlo.
  2. eliminar una tabla de la base de datos SQL, realizar un segundo volcado, luego comprimirla,
    luego use restic para respaldarlo.

Creo que encontrará eso porque la compresión se realiza ANTES
deduplicación, derrotará casi por completo el algoritmo de deduplicación de Restics.
Sin embargo, si restic pudo manejar la compresión DESPUÉS de deduplicarlo
debería obtener una salida general mucho menor.

En la industria del almacenamiento empresarial con herramientas como DataDomain siempre es
Se recomienda alimentar los datos al dispositivo de almacenamiento en un formato sin comprimir.
formatee y deje que el dispositivo realice la deduplicación y luego la compresión. los
El orden general en el que se deben aplicar estas herramientas es la deduplicación,
compresión, luego cifrado. Piense en esto por un segundo ...
realmente quiero gastar toda la CPU extra comprimiendo los mismos datos múltiples
veces solo para que se deduzca y se descarte esencialmente de todos modos? Su
generalmente aceptado que es mejor reducir el conjunto de datos a través de la deduplicación primero
antes de gastar la potencialmente pesada tarea de hacer compresión.

El viernes 2 de agosto de 2019 a la 1:29 p.m. Brandon Schneider [email protected]
escribió:

@mholt https://github.com/mholt Estoy de acuerdo en general, sin embargo
una copia de seguridad raíz (a través de algún volcado o incluso iterando sobre el contenido de /),
produce una buena relación de compresión para mí. No es esencial , ya que el total
usado ya es pequeño, pero obtengo alrededor del 50% de ahorro, y eso siempre es bueno
tener "gratis" para el usuario final.

-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/restic/restic/issues/21?email_source=notifications&email_token=AC3I762ZVGTTJL4TF3ODZILQCRVIXA5CNFSM4AXPP352YY3PNVWWK3TUL52HS4DFVREXG43VMDVBW63 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AC3I767IQQD3CZBIWM37C6TQCRVIXANCNFSM4AXPP35Q
.

¿Realmente almacena sus volcados SQL sin comprimir? Utilizo todos los míos antes de hacer una copia de seguridad, porque no tengo necesidad de almacenarlos sin procesar.
Podría decirse que ese no es el trabajo de un programa de respaldo. No debería tocar los datos originales.

¿Siente que este tipo de vista dificulta el almacenamiento eficiente de datos? La idea de que cada programa y operación de exportación debe implementar su propio formato de compresión ad hoc es algo de lo que estoy tratando de alejarme, porque evita que la deduplicación / compresión / etc. funcione en cualquier cosa que no sea un alcance predefinido por archivo (o directorio tarball). . La compresión de archivos individualmente pierde la capacidad de encontrar puntos en común entre diferentes archivos / volcados / etc. y, posteriormente, pierde todos los beneficios de la deduplicación. Mantener las cosas sin comprimir permite que un sistema de archivos (zfs, btrfs, etc.) haga todo esto por usted, y mejor, ya que puede comprimir y deduplicar en carpetas, instantáneas, etc. y abstraer todo esto mientras conserva la compatibilidad con las herramientas que deben funcionar. con los datos sin comprimir.

La compresión se puede ver solo como una optimización adicional en la deduplicación de Restic superior, pero parecen incompatibles entre sí si se hacen por separado ... Sugerir que uno debe comprimir y preprocesar los archivos antes de realizar una copia de seguridad lleva todo de regreso a un flujo de trabajo en el que también puede hacerlo. simplemente use rsync / rclone en su lugar, entonces, ¿por qué usar restic en primer lugar?

¿Siente que este tipo de vista dificulta el almacenamiento eficiente de datos? La idea de que cada programa y operación de exportación debe implementar su propio formato de compresión ad hoc es algo de lo que estoy tratando de alejarme, porque evita que la deduplicación / compresión / etc. funcione en cualquier cosa que no sea un alcance predefinido por archivo (o directorio tarball). . La compresión de archivos individualmente pierde la capacidad de encontrar puntos en común entre diferentes archivos / volcados / etc. y, posteriormente, pierde todos los beneficios de la deduplicación. Mantener las cosas sin comprimir permite que un sistema de archivos (zfs, btrfs, etc.) haga todo esto por usted, y mejor, ya que puede comprimir y deduplicar en carpetas, instantáneas, etc. y abstraer todo esto mientras conserva la compatibilidad con las herramientas que deben funcionar. con los datos sin comprimir.

No se trata solo del almacenamiento eficiente de datos, también son los flujos de trabajo existentes. Quiero un producto de respaldo para respaldar mis datos de manera confiable y eficiente, no hacer cumplir los flujos de trabajo en otros aspectos del sistema. Es mucho más importante que las copias de seguridad (que se conservan, potencialmente indefinidamente) se almacenen de manera eficiente, mientras que los datos de trabajo en vivo deben almacenarse en el mejor formato para su uso activo.

Ahora bien, hay casos en los que tiene sentido comprimir antes de almacenar, especialmente con datos muy comprimibles en sistemas de almacenamiento lentos, pero esta es la excepción más que la regla en mi experiencia.

¡La compresión +1 realmente me ayudaría! En el trabajo como ingeniero de software, hago una copia de seguridad de toda mi carpeta de inicio, que tiene una gran cantidad de código fuente sin comprimir (y en lenguajes dinámicos, como ruby ​​o python, casi siempre es código fuente, incluso la mayoría de las dependencias).

En casa hago una copia de seguridad de mi / completo, nuevamente incluyendo muchas cosas que se benefician de la compresión, como binarios, archivos man, archivos de recursos, etc.

Por supuesto, podría comprimirlos todos y hacer muchas transformaciones antes de hacer una copia de seguridad, pero eso anularía gran parte de la conveniencia de ejecutar un comando muy simple y poder obtener una copia de seguridad, así como fácilmente. restaurar cosas.

Ahora, por supuesto, hay muchas clases de archivos que no se comprimen bien, pero nadie dice que se deba obligar a comprimirlos. Hay muchos enfoques para resolver esto: incluir en la lista blanca qué tipos de archivos deben comprimirse, en la lista negra qué archivos no deben comprimirse, o incluso el más simple: intente comprimir, y si el tamaño resultante no mejora, almacénelo sin comprimir (creo que ZFS utiliza este enfoque cuando la compresión en disco está habilitada).

Al final, la compresión es un ejemplo del clásico equilibrio entre espacio y tiempo: ¿quiere pagar más CPU o más almacenamiento? En mi caso, el almacenamiento domina mis costos, así que creo que sería genial si mi quad-core se calentara un poco más y luego mi factura de alojamiento de archivos fuera menor.

Finalmente, realizo una copia de seguridad de un poco más de 4 TB en un proveedor de la nube y mi velocidad de carga es débil de todos modos, por lo que una compresión adicional haría que mi proceso de copia de seguridad sea más rápido, no más lento: mi CPU puede más que mantenerse al día con mi mala conexión VDSL .

Sí, puedo estar de acuerdo con todos los demás aquí. La compresión es bastante importante y realmente no veo ningún argumento por qué restic no debería tenerla.

@mholt Estoy completamente de acuerdo contigo. Cada palabra.
En mi cadena de herramientas, la compresión viene antes que la deduplicación restic porque, por ejemplo, utilizo TFS como control de fuente y todas las fuentes ya están comprimidas en las copias de seguridad de SQL y las imágenes de la aplicación están comprimidas en archivos de configuración msi o archivos 7z. Solo necesito una forma rápida y sencilla de obtener el delta diario y enviarlo a la nube para implementar un plan seguro de recuperación ante desastres.
Creo que @ fd0 necesita concentrar su tiempo en resolver problemas que tratar de agregar otra complejidad al producto.

Solo repitiendo con una pequeña comparación que hice entre borg usando auto,zstd compresión y restic (sin compresión), primero en / , luego en /home , excluyendo cosas como imágenes de VM y imágenes de la ventana acoplable (ya que tampoco las hago en una copia de seguridad del mundo real). La máquina de prueba fue mi máquina de desarrollo de software diaria, que contiene muchos archivos binarios, algunas imágenes comprimidas y archivos de audio, pero también una buena cantidad de código fuente en texto plano, que debería comprimirse bastante bien:

/ : 1053136 archivos, 92,9 GiB

  • borg, ninguno: 17:27 min, 64,1 GiB
  • borg, zstd: 19:29 min, 40,6 GiB
  • descanso: 09:45 min, 62,4 GiB

/home : 221338 archivos, 58,3 GiB

  • borg, zstd: 09:06 min, 30,7 GiB
  • descanso: 04:36 min, 39,4 GiB
    Omití borg sin compresión aquí, ya que es más o menos lo mismo que restic en lo que respecta al espacio de almacenamiento.

En primer lugar, quiero aplaudir a Restic por ser casi exactamente el doble de rápido en ese caso de prueba. Además de que borg es más lento, podría ser interesante que la compresión solo agregue ~ 2 minutos a la duración total de la copia de seguridad (+ 11%), pero reduce significativamente los datos que se almacenarán para el caso / (-35 %). En el caso de mi directorio personal, los ahorros de almacenamiento son aproximadamente del 20%.

(La prueba se realizó en un disco externo para ese caso. Cuando se realiza una copia de seguridad en un almacenamiento remoto, el tiempo que tarda la copia de seguridad depende principalmente del ancho de banda de carga, al menos cuando la velocidad de la CPU y la E / S son mucho más altas que la red. Probé esto y borg con compresión es de hecho más rápido que restic entonces, porque la compresión da como resultado que se transfieran menos datos). Con todo, estoy a favor de que restic obtenga soporte de compresión, idealmente usando la detección automática para verificar si un fragmento se beneficia de la compresión.

@nioncode Si mis cálculos son correctos, realiza una copia de seguridad de unos 100/150 MB / s. Eso está por debajo de lo que zstd puede comprimir. Dado que la compresión es asincrónica, no debería haber ninguna ralentización. Incluso puede ser un poco más rápido ya que hay menos para escribir.

Sé que archivar máquinas virtuales puede ser un caso de uso, pero estoy tratando de evitar la necesidad de hacerlo.
Estoy tratando de automatizar toda la construcción de la máquina virtual a partir de los archivos iso y de configuración.
En caso de recuperación ante desastres, quiero poder restaurar toda la máquina virtual utilizando la copia de seguridad de los archivos de configuración, los documentos y la copia de seguridad de las bases de datos. Y estoy tratando de hacerlo sin la interacción del usuario.
De esta manera, puedo evitar la necesidad de comprimir y hacer copias de seguridad de muchos archivos basura contenidos en una máquina virtual, como archivos temporales, archivos sin comprimir como exe y dll, etc.
Lo sé, no es simple, pero puedo evitar comprimir y deduplicar los mismos GB de archivos inútiles ahorrando espacio en disco y ancho de banda.

No abarrotemos este hilo sobre quién hace las cosas y cómo. Ha sido suficiente.

La compresión es una característica que muchas personas quieren (incluido yo mismo) y puede ahorrar tanto el almacenamiento de respaldo como el tiempo de carga en caso de conectividad a Internet lenta-media, para algunas personas incluso un 30% o más.

Sin embargo, no todo el mundo lo necesita y algunas personas han adaptado su flujo de trabajo de una manera inteligente para lidiar con él, o simplemente tienen el dinero o el ancho de banda o ambos para que simplemente no les importe.

En cualquier caso, ambas partes se han pronunciado.

@ bjoe2k4 o están preocupados por las implicaciones de seguridad negativas de comprimir datos antes de

A menos que la compresión se vuelva obligatoria, las preocupaciones de seguridad de la compresión son simplemente una compensación que el usuario puede hacer. Tomaré copias de seguridad más rápidas y reduciré los costos mensuales y únicos sobre este riesgo teórico (un riesgo que probablemente no podría explotarse de todos modos, ya que mis conjuntos de datos son grandes y los cambios impredecibles, por lo que el ruido ahogaría cualquier intento de generar un error. señal de compresión).

Sin embargo, no creo que nadie esté hablando de hacer que la compresión sea obligatoria.

Mi caso de uso especial es realizar copias de seguridad de GRANDES conjuntos de volcados CSV y SQL. Estos archivos serían MUY comprimibles ... y no quiero / no puedo precomprimirlos.

Realmente me gustaría tener la función de compresión ya que pago por cada GB de almacenamiento en línea

Dado que esta discusión se está volviendo un poco más activa ahora, me gustaría compartir algunos hallazgos que tuve con una versión resticida parcheada de algunos amigos míos. Agregaron compresión a restic (más o menos rápido y sucio que yo sepa) y les notificaré sobre esta publicación para que puedan comentar sobre los detalles de implementación si alguien está interesado.
Mi caso de uso es un software bancario realmente feo que tiene su propio formato de base de datos. Tenemos que usar este software por razones reglamentarias y los datos que tenemos son varios TB de archivos bastante grandes que se pueden comprimir hasta el 90% de su tamaño original. Entonces, obviamente, la compresión nos ahorraría mucho en almacenamiento de respaldo, tiempos de respaldo y tiempos de restauración.
Mis hallazgos al comparar restic upstream, el restic parcheado con compresión y nuestra solución de respaldo actual con tar se pueden encontrar aquí: https://gist.github.com/joerg/b88bf1de0ce824894ffc38f597cfef5f

| Herramienta | Tiempo de respaldo (m: s) | Tiempo de restauración (m: s) | Espacio de respaldo (G) | Espacio de respaldo (%) | Copia de seguridad (MB / s) | Restaurar (MB / s) |
| --------------------------- | ----------------- | ------------------ | ---------------- | ---------------- | ------------- | -------------- |
| Tar | 4:42 | 5:19 | 11 | 9,6% | 404 | 357 |
| Restic S3 local Upstream | 10:04 | 30:56 | 102 | 89,5% | 189 | 61 |
| Compresión local Restic S3 | 5:43 | 19:28 | 8,6 | 7,5% | 332 | 98 |
| Restic Local Upstream | 8:33 | 26:06 | 102 | 89,5% | 222 | 73 |
| Compresa local Restic | 5:21 | 16:57 | 8,6 | 7,5% | 355 | 112 |
| Restic S3 Remoto Upstream | 17:12 | 46:06 | 102 | 89,5% | 110 | 41 |
| Compresión Remota Restic S3 | 5:27 | 21:42 | 8,6 | 7,5% | 349 | 88 |

Creo que restic ganaría enormemente con la compresión opcional de cualquier tipo porque reduce prácticamente todo.

No todos los archivos tendrán una relación de compresión interesante. Probablemente no valga la pena comprimir un archivo de vídeo, pero sin duda lo es comprimir un volcado SQL. Es por eso que los sistemas de archivos como Btrfs primero intentan comprimir los primeros 128 KB de un archivo y, si hay una relación de compresión significativa, comprimirán todo el archivo. Definitivamente no es perfecto, pero es rápido y debería funcionar para la mayoría de los casos de uso si se decide comprimir archivos individualmente.

Para aquellos que están argumentando en contra de proporcionar compresión como una opción, mi caso de uso es que hago una copia de seguridad de una mezcla de tipos de archivos en su mayoría comprimibles cuyo contenido no tengo control y no es razonable esperar que tenga que comprimir los datos en varias máquinas (que ocupan más espacio en el disco local en el caso de comprimir a un nuevo archivo o inutilizan los archivos para sus aplicaciones asociadas si se comprimen en su lugar) antes de realizar una operación de copia de seguridad.

Preferiría poder usar restic como mi herramienta de copia de seguridad de recuperación ante desastres, pero actualmente estoy usando borg (requisitos de RAM masivos y lentos, etc.) porque la compresión resultante + deduplicación que logra me ahorra muchos gigabytes de transferencia de red por operación de copia de seguridad y fácilmente en un terrabyte de espacio de almacenamiento (que pago por mes) en la nube en la totalidad de mi conjunto de respaldo. Podría conservar las copias de seguridad durante más tiempo o reducir mis costos de almacenamiento si restic soportara la compresión.

Hola @joerg , gracias por compartir tus pruebas.
¿Ha intentado hacer una copia de seguridad con restic de la salida de la tarea de compresión Tar?
Tengo curiosidad por comparar "Restic S3 Remote Compress" y "Tar" + "Restic S3 Remote Upstream".
Además, lo que dices parece no ser realmente cierto:

Creo que restic ganaría enormemente con la compresión opcional de cualquier tipo porque reduce prácticamente todo

Al ver los resultados de la prueba, parece que el tiempo de CPU que necesita restic es 2 veces más largo para la copia de seguridad local y 6 veces más largo en la restauración. No es muy bueno comparado con el alquitrán.

tar no es un algoritmo de compresión. por supuesto que es rápido.
EDITAR: oh y por cierto. si alquila un directorio, no utilizará varios subprocesos por archivo y tampoco funcionará con dos archivos o más a la vez, sino que escaneará el directorio y agregará un archivo y luego pasará al siguiente. bastante lento. pero el problema es el archivo de almacenamiento que no está diseñado para agregar varios subprocesos.

Al ver los resultados de la prueba, parece que el tiempo de CPU utilizado por restic es 2 veces más lento en la copia de seguridad local y 6 veces más lento en la restauración. No es muy bueno comparado con el alquitrán.

No estoy completamente seguro de su punto aquí. restic es más lento que Tar, claro, pero restic con compresión siempre es más rápido que restic sin, por lo que restic claramente se beneficiaría.

Tar es una comparación útil de un "mejor caso en este hardware", pero carece de la mayoría de las otras características de restic (me vienen a la mente instantáneas y deduplicación de datos). Al parecer, agregar compresión solo mejora los tiempos de respaldo, los tiempos de restauración y los costos de almacenamiento, aspectos que son importantes para un producto de respaldo.

@joerg ¿Pueden tus amigos abrir una solicitud de extracción y hacer que sus parches para restic con compresión estén disponibles al público? ¿Qué algoritmo de compresión utilizan?

@joerg @thedaveCA
Me disculpo , afirmación de

Tenga en cuenta que no estamos usando archivos tar desnudos, sino archivos tar comprimidos con gzip con una implementación zip paralela especial; de lo contrario, el archivo de terabytes de datos tomaría días en lugar de las "solo" horas que toma ahora: https: //gist.github. com / joerg / b88bf1de0ce824894ffc38f597cfef5f # tarpigz
@shibumi Les informé sobre este tema y mi publicación, así que ahora depende de ellos si quieren involucrarse en esto y en qué medida. Personalmente, espero que abran esa solicitud de extracción ...

La compresión no es válida para el cifrado. Permite a un atacante adivinar si un repositorio cifrado contiene un determinado archivo, ya que una sección (fragmento) de un archivo se comprime al mismo tamaño independientemente de la clave de cifrado utilizada. Esta es una vulnerabilidad muy conocida de los protocolos de cifrado, y es por eso que se eliminó la compresión de TLS 1.3.

No creemos un problema conocido donde no hay ninguno, ¿de acuerdo?

(Creo que este problema ya se mencionó, y probablemente ni siquiera una vez. Aún así, este problema está abierto, donde siento que por esta única razón debería cerrarse de una vez por todas).

¿Por qué envías spam al problema? :( Se ha discutido tantas veces que es casi fuera de tema. ¡¡No estarás FORZADO a habilitar la compresión !!

Además, creo que su idea de ataque requiere que el atacante sea capaz de controlar la compresión y el cifrado de los datos (¡aunque no estoy seguro!). https://en.m.wikipedia.org/wiki/CRIME

Pero en cualquier caso, incluso si es un problema de seguridad, alguien puede querer usar la compresión solo en un almacenamiento que está bajo su propio control para simplemente ahorrar espacio de almacenamiento.

Tener incluso una característica opcional que debilita el cifrado invita a una falsa sensación de seguridad. Restic afirma ser un programa de copia de seguridad _seguro_. Agregar una compresión opcional anulará esta promesa, ya que a veces no puede estar seguro, solo a tiempo completo, todo el tiempo. Y habrá informes CVE, seguro. ¿Quién quiere para su software este tipo de "popularidad"?

Pero creo que agregar una compresión de una manera que nunca se use con cifrado es una opción viable.

FWIW en 2017 hice una demostración en la que eliminé el cifrado de Restic y demostré que la compresión puede ser muy efectiva . Cien veces eficaz. La compresión IIRC se puede agregar como una especie de envoltorio al igual que el cifrado, pero no he mirado el código durante mucho tiempo, por lo que las cosas pueden ser más difíciles en estos días o más fáciles.

en realidad CRIME necesita saber la longitud del texto cifrado, lo cual es básicamente imposible en restic.
tampoco existe un programa de copia de seguridad "seguro". si los archivos de respaldo son accesibles por terceros, siempre existe la posibilidad de que alguien pueda alterar o peor aún, leer los datos.
así que decir que la compresión lo empeora, es simplemente una estupidez.

en realidad CRIME necesita saber la longitud del texto cifrado

CRIME necesita pero tú no. Imagina que eres un periodista de investigación que te ha proporcionado un conjunto de archivos ultrasecretos de tu fuente. Los respalda con encriptación y nadie sabrá que tiene estos archivos.

Ahora imagine que no fue lo suficientemente inteligente como para habilitar la compresión, y ahora todos los demás, que también tienen estos archivos, solo a juzgar por el tamaño de los fragmentos comprimidos y luego encriptados, sabrán que tiene estos archivos ultrasecretos en este archivo sin incluso necesitando conocer la clave de cifrado. Esto está muy lejos de ser seguro. La gente puede ir a la cárcel por esta "característica", ser torturada o algo peor.

no hay un programa de copia de seguridad "seguro"

Esto entonces necesita una actualización.

Fast, secure, efficient backup program

También tenga en cuenta que es seguro por defecto.

Restic almacena solo trozos empaquetados, por lo que el tamaño de los trozos no es evidente para
alguien que no tiene las llaves.

El viernes, 09 de agosto de 2019 a las 02:09:23 AM -0700, Alexey Kopytko escribió:

La compresión no es válida para el cifrado. Permite a un atacante adivinar si un repositorio cifrado contiene un determinado archivo, ya que una sección (fragmento) de un archivo se comprime al mismo tamaño independientemente de la clave de cifrado utilizada. Esta es una vulnerabilidad muy conocida de los protocolos de cifrado, por eso se eliminó la compresión de TLS 1.3.

No creemos un problema conocido donde no hay ninguno, ¿de acuerdo?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/restic/restic/issues/21#issuecomment -519844526

-
(Escriu-me xifrat si saps PGP / Escribe cifrado si conoces PGP)
Clave PGP 7CBD1DA5 - https://emailselfdefense.fsf.org/

Para quienes quieran saber más sobre estos problemas de seguridad, hay un buen artículo que lo describe http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf
Según tengo entendido, podría haber una falla si el archivo se fragmenta y luego se comprime y encripta. Pero si el archivo se comprime antes de fragmentar, es un archivo binario como cualquier otro y esos ataques de texto plano se vuelven inútiles.

Pero si el archivo se comprime antes de fragmentar, es un archivo binario como cualquier otro y esos ataques de texto plano se vuelven inútiles.

Eso es correcto. Pero eso no ayudará exactamente con la deduplicación eficiente si lo entiendo correctamente, ya que un algoritmo de compresión puede usar un vocabulario diferente para cada versión de un archivo, lo que da como resultado un resultado binario muy diferente. Que obviamente no se deduplicará. Dicho de otro modo, solo tiene sentido comprimir los fragmentos resultantes.

Restic almacena solo trozos empaquetados, por lo que el tamaño de los trozos no es evidente para alguien que no tenga las llaves

Eso es un alivio.

Mi punto sigue en pie: hay muchas formas en que uno puede agregar una debilidad oculta en un programa cuando implementa la compresión junto con el cifrado, por lo que es mejor no agregar una en absoluto. Incluso los _expertos_ de cifrado que deciden sobre TLS optaron por eliminar la compresión. Supongo que tenían un razonamiento similar.

por cierto.:

However, it is important to note that these attacks have little security impact on, say, a bulkencryption application which compresses data before encrypting

...
Además, CRIME solo funciona si tiene varias versiones diferentes de los archivos cifrados.
es decir, múltiples ejecuciones de copia de seguridad (a diferentes repositorios, donde el atacante las obtuvo todas)
y también solo funciona con una pequeña cantidad de datos.

CRIME necesita pero tú no. Imagina que eres un periodista de investigación que te ha proporcionado un conjunto de archivos ultrasecretos de tu fuente. Los respalda con encriptación y nadie sabrá que tiene estos archivos.

Ahora imagine que no fue lo suficientemente inteligente como para habilitar la compresión, y ahora todos los demás, que también tienen estos archivos, solo a juzgar por el tamaño de los fragmentos comprimidos y luego encriptados, sabrán que tiene estos archivos ultrasecretos en este archivo sin incluso necesitando conocer la clave de cifrado. Esto está muy lejos de ser seguro. La gente puede ir a la cárcel por esta "característica", ser torturada o algo peor.

eso es una tonteria. porque solo funciona con un tamaño de muestra pequeño. también puede ser posible ir a la cárcel sin compresión. especialmente en algún momento, cuando un atacante obtuvo sus archivos de respaldo, podría ser capaz de burlarlos en el futuro.
puede haber otros problemas de seguridad que aparezcan en el futuro, etc.
la discusión simplemente se convirtió en un alarmismo sin sentido.

@sanmai , no obtengo este ejemplo con

Imagine que es un periodista de investigación ... Ahora imagine que no fue lo suficientemente inteligente como para habilitar la compresión, y ahora todos los demás, que también tienen estos archivos, a juzgar por el tamaño de los fragmentos comprimidos y luego encriptados, sabrán que tiene estos archivos ultrasecretos en este archivo sin necesidad de conocer la clave de cifrado.

¿Qué se quiere decir? ¿Alguien puede adivinar que una instantánea encriptada tiene estos archivos con solo mirar el tamaño? Esto supone que los archivos están comprimidos solos o junto con otros archivos conocidos. Pero luego se puede hacer la misma suposición con una instantánea sin cifrar.

En realidad, ¿qué tal si comprime archivos con gzip antes de realizar una copia de seguridad? ¿Abre esto también una vulnerabilidad de seguridad?

Creo que este ejemplo no tiene sentido: si afirma que puede determinar si una instantánea contiene versiones comprimidas de algunos archivos (arbitrarios) que conoce, también podría determinar si contiene esos archivos sin comprimir.

No creo que la compresión pueda hacer que el cifrado sea mucho menos seguro.

La mayoría de los ataques de canal lateral de compresión involucran varios factores:
1) El atacante puede controlar la entrada
2) El atacante puede observar el tamaño de la salida.
3) Pequeños cambios en los datos de entrada dan como resultado cambios medibles en el tamaño de salida
4) El atacante puede cambiar la entrada y reintentar cientos de miles de veces

A diferencia de los sistemas basados ​​en la web, en la gran mayoría que involucran copias de seguridad restringidas, (1) y (2) rara vez se mantendrán al mismo tiempo. Además, la compresión basada en bloques (3) no está realmente garantizada, y para la mayoría de los regímenes de copia de seguridad (4) ciertamente no se cumple. Debido a que la frecuencia de las copias de seguridad suele ser una vez al día aproximadamente, se necesitarían miles de años para poder manipular los datos y monitorear el tamaño de salida comprimido para notar cualquier diferencia significativa, y eso asumiendo que no hay otros datos que cambien, lo que en la mayoría de los casos sería.

Si estaba realizando copias de seguridad en las que el tamaño de salida era visible, es posible que desee considerar la posibilidad de deshabilitar la compresión. De lo contrario, realmente no hay ataques prácticos contra él y no sería menos seguro tenerlo habilitado.

restic ya realiza la deduplicación, lo que lo expone a los mismos ataques teóricos que los canales laterales de compresión de todos modos, y nadie se ha quejado de esto que yo sepa.

El hecho es que hay cientos o miles de usuarios que se beneficiarían de una función de compresión sin inconvenientes de ningún tipo. ¿Podemos dejar este problema de hace 5 años a los desarrolladores que están trabajando en él?

para ser honesto ... prefiero el concepto de restic ... pero hice pruebas en mi caso de uso (muchos archivos CSV y volcados de SQL) y tuve que cambiar a borg.

Probé con cuatro generaciones de respaldo incremental y mis archivos obtienen una compresión de 7: 1 y junto con la deduplicación alcanzo> 20: 1. No puedo ignorar eso ya que ya dije que pago mi almacenamiento de respaldo en línea por GB.

root<strong i="7">@xxxx</strong>:~# borg list
2019-08-08_14:37                     Thu, 2019-08-08 14:37:10 [5e113a8102f2bd7e40d100343f849dc73843d145011c7214d5fa0895927eb6d1]
2019-08-08_22:28                     Thu, 2019-08-08 22:28:21 [17d815d000212a576610b2fd5688ab87cce00039bb89f63722c6a7819dec1821]
2019-08-09_02:00                     Fri, 2019-08-09 02:00:23 [217c53b07f30dfbca584c49468cfa624a2445a005890220509c97715f7007e81]
2019-08-10_02:00                     Sat, 2019-08-10 02:00:10 [5dd45b8ccf0aa382bf00d5b08e1d5d88daae014f0a1a42b3e2b0fc368623bba0]
root<strong i="8">@xxxx</strong>:~# borg info
Repository ID: xxxx
Location: ssh://xxxx
Encrypted: Yes (repokey)
Cache: /var/lib/borg/cache/xxxx
Security dir: /var/lib/borg/security/xxxx
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
All archives:               69.02 GB             11.24 GB              2.80 GB

                       Unique chunks         Total chunks
Chunk index:                    9227                41812

¿Qué se quiere decir? ¿Que alguien pueda _adivinar_ que una instantánea cifrada tiene estos archivos con solo mirar el tamaño? Esto supone que los archivos están comprimidos solos o junto con otros archivos conocidos. Pero luego se puede hacer la misma suposición con una instantánea sin cifrar.

Exactamente. Divida un archivo de texto sin formato en partes iguales, comprímalo y luego cifre. Cortar de nuevo, comprimir y cifrar. Como los tamaños de los archivos cifrados no cambian en cuanto a AES, verá que en ambos casos tiene un rango de tamaños que coinciden entre sí como una huella digital. Ellos (y con ellos me refiero principalmente a administraciones de regímenes opresivos como Irán o Rusia) pueden hacer una suposición razonable de que estos archivos están presentes aquí, lo que por lo tanto da la razón, digamos, para continuar torturando al sospechoso. No entiendo por qué se ofenden tanto con estas ideas, ¿no son fáciles de entender? Esto no es un DELITO per se, ¿verdad?

Pero como señaló antes @viric , técnicamente Restic no se ve afectado por estas vulnerabilidades, ya que los tamaños de los fragmentos no se ven sin una clave de cifrado. Sin embargo, si se agrega compresión en algún momento, es posible que Restic aún no se vea afectado ahora, pero puede verse afectado más adelante.

¿Agregar compresión expone a Restic a alguna vulnerabilidad adicional, dado que ya realiza la deduplicación?

Si su preocupación es que un atacante adivine el tamaño de los bloques comprimidos para inferir el tamaño sin comprimir, está bien, pero ¿la compresión lo empeora? ¿No tendría un atacante la misma información básica?

Si un atacante pudiera ver los tamaños comprimidos y sin comprimir de cada archivo, la identificación podría volverse más realista, pero esto no sería posible en restic.

En última instancia, la deduplicación ya lo expone a todos los ataques teóricos en los que puedo ver que la compresión tiene un impacto, además, por supuesto, la compresión puede desactivarse para mantener el estado actual de las cosas si esto se adapta mejor a su situación.

Simplemente no entiendo por qué discuten sobre hipotéticas preocupaciones de seguridad acerca de adivinar la presencia de un archivo al ver el tamaño de un fragmento cifrado ... ,,

Ustedes chicos usan ZIP o GZ? Entonces deberías estar bien.

¿Crees que las autoridades iraníes pueden adivinar mi contenido por tamaños? Entonces simplemente no use la compresión (!). Eso simplemente no significa que la compresión no debería estar disponible.

Creo que hemos cubierto todos los ángulos relevantes de agregar compresión a restic, muchas gracias por todos sus aportes.

Creo que deberíamos agregar compresión y habilitarla de forma predeterminada, pero permitir que los usuarios deshabiliten la compresión. Tenga paciencia hasta que tenga más tiempo para trabajar en ello.

Me parece que esta discusión se sale de control, así que estoy bloqueando este tema por ahora. Si desea continuar con esta discusión, diríjase al foro . ¡Gracias!

¿Fue útil esta página
0 / 5 - 0 calificaciones