sql >> Base de Datos >  >> NoSQL >> HBase

E/S Apache HBase – HFile

Introducción

Apache HBase es el administrador de almacenamiento versionado, distribuido y de código abierto de Hadoop muy adecuado para aplicaciones aleatorias. , lectura/escritura en tiempo real acceso.

¿Espera espera? acceso aleatorio de lectura/escritura en tiempo real?
¿Cómo es eso posible? ¿No es Hadoop solo un sistema de procesamiento por lotes de lectura/escritura secuencial?

Sí, estamos hablando de lo mismo, y en los siguientes párrafos, les explicaré cómo HBase logra la E/S aleatoria, cómo almacena datos y la evolución del formato HFile de HBase.

Formatos de archivo de E/S de Apache Hadoop

Hadoop viene con un formato de archivo SequenceFile[1] que puede usar para agregar sus pares clave/valor, pero debido a la capacidad de solo agregar de hdfs, el formato de archivo no puede permitir la modificación o eliminación de un valor insertado. La única operación permitida es agregar, y si desea buscar una clave específica, debe leer el archivo hasta que encuentre su clave.

Como puede ver, está obligado a seguir el patrón de lectura/escritura secuencial... pero, ¿cómo es posible construir un sistema de acceso de lectura/escritura aleatorio y de baja latencia como HBase encima de esto?

Para ayudarlo a resolver este problema, Hadoop tiene otro formato de archivo, llamado MapFile[1], una extensión de SequenceFile. MapFile, en realidad, es un directorio que contiene dos SequenceFiles:el archivo de datos “/data” y el archivo de índice “/index”. MapFile le permite agregar pares clave/valor ordenados y cada N claves (donde N es un intervalo configurable) almacena la clave y el desplazamiento en el índice. Esto permite una búsqueda bastante rápida, ya que en lugar de escanear todos los registros, escanea el índice que tiene menos entradas. Una vez que haya encontrado su bloque, puede saltar al archivo de datos reales.

MapFile es bueno porque puede buscar pares clave/valor rápidamente, pero todavía hay dos problemas:

  • ¿Cómo puedo eliminar o reemplazar una clave/valor?
  • Cuando mi entrada no está ordenada, no puedo usar MapFile.

HBase y archivo de mapa

La clave HBase consta de:la clave de fila, la familia de columnas, el calificador de columna, la marca de tiempo y un tipo.

Para resolver el problema de eliminar pares clave/valor, la idea es usar el campo "tipo" para marcar la clave como eliminada (tombstone markers). Resolver el problema de reemplazar pares clave/valor es solo una cuestión de elegir la última marca de tiempo (el valor correcto está cerca del final del archivo, agregar solo significa que la última inserción está cerca del final).

Para resolver el problema de la clave "no ordenada", mantenemos en la memoria los últimos valores-clave agregados. Cuando haya alcanzado un umbral, HBase lo vacía en un MapFile. De esta manera, termina agregando valores/clave ordenados a un MapFile.

HBase hace exactamente esto[2]:cuando agrega un valor con table.put(), su clave/valor se agrega a MemStore (bajo el capó, MemStore es un ConcurrentSkipListMap ordenado). Cuando se alcanza el umbral por tienda de memoria (hbase.hregion.memstore.flush.size) o RegionServer usa demasiada memoria para las tiendas de memoria (hbase.regionserver.global.memstore.upperLimit), los datos se vacían en el disco como un nuevo MapFile .

El resultado de cada descarga es un MapFile nuevo, y esto significa que para encontrar una clave hay que buscar en más de un archivo. Esto requiere más recursos y es potencialmente más lento.

Cada vez que se emite una obtención o un escaneo, HBase escanea cada archivo para encontrar el resultado, para evitar saltar demasiados archivos, hay un hilo que detectará cuando haya alcanzado una cierta cantidad de archivos (hbase.hstore.compaction .máx). Luego intenta fusionarlos en un proceso llamado compactación, que básicamente crea un nuevo archivo grande como resultado de la fusión de archivos.

HBase tiene dos tipos de compactación:una denominada "compactación menor" que simplemente fusiona dos o más archivos pequeños en uno, y la otra denominada "compactación principal" que recoge todos los archivos de la región, los fusiona y realiza una limpieza. En una compactación importante, se eliminan los valores/clave eliminados, este nuevo archivo no contiene los marcadores de desecho y se eliminan todos los valores/clave duplicados (operaciones de reemplazo de valores).

Hasta la versión 0.20, HBase ha utilizado el formato MapFile para almacenar los datos, pero en 0.20 se introdujo un nuevo MapFile específico de HBase (HBASE-61).

HArchivo v1

En HBase 0.20, MapFile se reemplaza por HFile:una implementación de archivo de mapa específica para HBase. La idea es bastante similar a MapFile, pero agrega más funciones que un simple archivo de clave/valor. Funciones como la compatibilidad con metadatos y el índice ahora se guardan en el mismo archivo.

Los bloques de datos contienen los valores/clave reales como MapFile. Para cada "operación de cierre de bloque", la primera clave se agrega al índice y el índice se escribe en HFile close.

El formato HFile también agrega dos tipos de bloques de "metadatos" adicionales:Meta y FileInfo. Estos dos bloques clave/valor se escriben al cerrar el archivo.

El bloque Meta está diseñado para mantener una gran cantidad de datos con su clave como una cadena, mientras que FileInfo es un mapa simple preferido para información pequeña con claves y valores que son matriz de bytes. StoreFile de Regionserver usa Meta-Blocks para almacenar un filtro Bloom y FileInfo para Max SequenceId, clave de compactación principal e información de rango de tiempo. Esta información es útil para evitar leer el archivo si no hay posibilidad de que la clave esté presente (Bloom Filter), si el archivo es demasiado antiguo (Max SequenceId) o si el archivo es demasiado nuevo (Timerange) para contener lo que estamos buscando. para.

HArchivo v2

En HBase 0.92, el formato HFile se modificó un poco (HBASE-3857) para mejorar el rendimiento cuando se almacenan grandes cantidades de datos. Uno de los principales problemas con HFile v1 es que necesita cargar todos los índices monolíticos y filtros Bloom grandes en la memoria, y para resolver este problema, v2 introduce índices multinivel y un filtro Bloom a nivel de bloque. Como resultado, HFile v2  presenta mejoras en la velocidad, la memoria y el uso de caché.

La característica principal de esta v2 son los "bloques en línea", la idea es dividir el índice y el filtro Bloom por bloque, en lugar de tener todo el índice y el filtro Bloom de todo el archivo en la memoria. De esta forma puedes tener en ram justo lo que necesitas.

Dado que el índice se mueve al nivel de bloque, entonces tiene un índice de varios niveles, lo que significa que cada bloque tiene su propio índice (índice de hoja). La última clave de cada bloque se mantiene para crear el índice/intermedio que hace que el árbol b+ de índice multinivel sea como.

El encabezado del bloque ahora contiene información:el campo "Mágico del bloque" se reemplazó por el campo "Tipo de bloque" que describe el contenido del bloque "Datos", Leaf-Index, Bloom, Metadata, Root-Index, etc. También tres Se agregaron campos (tamaño comprimido/sin comprimir y bloque anterior compensado) para permitir búsquedas rápidas hacia adelante y hacia atrás.

Codificaciones de bloques de datos

Dado que las claves están ordenadas y suelen ser muy similares, es posible diseñar una compresión mejor que la que puede hacer un algoritmo de propósito general.

HBASE-4218 intentó resolver este problema, y ​​en HBase 0.94 puede elegir entre un par de algoritmos diferentes:Prefijo y Codificación Diff.

La idea principal de la codificación de prefijos es almacenar el prefijo común solo una vez, ya que las filas están ordenadas y el comienzo suele ser el mismo.

La codificación Diff impulsa este concepto aún más. En lugar de considerar la clave como una secuencia opaca de bytes, el Codificador Diff divide cada campo clave para comprimir cada parte de una mejor manera. Siendo esto que la familia de columnas se almacena una vez. Si la longitud de la clave, la longitud del valor y el tipo son los mismos que en la fila anterior, se omite el campo. Además, para una mayor compresión, la marca de tiempo se almacena como una diferencia de la anterior.

Tenga en cuenta que esta función está desactivada de forma predeterminada, ya que la escritura y el escaneo son más lentos, pero se almacenan más datos en caché. Para habilitar esta función, puede configurar DATA_BLOCK_ENCODING =PREFIX | DIF | FAST_DIFF en la información de la tabla.

HArchivo v3

HBASE-5313 contiene una propuesta para reestructurar el diseño de HFile para mejorar la compresión:

  • Embale todas las claves al principio del bloque y todo el valor al final del bloque. De esta forma, puede usar dos algoritmos diferentes para comprimir claves y valores.
  • Comprime las marcas de tiempo usando XOR con el primer valor y usa VInt en lugar de long.

Además, se está investigando un formato en columnas o una codificación en columnas, eche un vistazo a AVRO-806 para obtener un formato de archivo en columnas de Doug Cutting.

Como puede ver, la tendencia en la evolución es ser más consciente de lo que contiene el archivo, para obtener una mejor compresión o un mejor conocimiento de la ubicación que se traduce en menos datos para escribir/leer desde el disco. ¡Menos E/S significa más velocidad!

[1] https://clouderatemp.wpengine.com/blog/2011/01/hadoop-io-sequence-map-set-array-bloommap-files/
[2] https://clouderatemp.wpengine. com/blog/2012/06/hbase-write-path/