Caché de bloques HBase

Bloquear caché

HBase proporciona dos implementaciones de BlockCache diferentes para almacenar en caché los datos leídos desde HDFS: el LruBlockCache predeterminado en el montón y BucketCache (generalmente fuera del montón). Esta sección analiza las ventajas y desventajas de cada implementación, cómo elegir las opciones adecuadas y cada opción de configuración. 

Selección de caché

LruBlockCache es la implementación original, completamente en el montón de Java. BucketCache es opcional y se usa principalmente para mantener los datos de caché en bloque fuera del montón, aunque BucketCache también puede ser un caché respaldado por archivos. 

Cuando habilita BucketCache, habilitará un sistema de caché de dos niveles. Una vez describimos las capas como "L1" y "L2", pero el término hbase-2.0.0 ha quedado obsoleto. La caché "L1" se refiere a una instancia de LruBlockCache y "L2" se refiere a BucketCache fuera del montón. Por el contrario, cuando BucketCache está habilitado, todos los bloques de DATOS se almacenan en la capa BucketCache y los metabloques (bloques INDEX y BLOOM) están en el montón de LruBlockCache. CombinedBlockCache completa la gestión de estos dos niveles y la estrategia de controlar el movimiento de bloques entre ellos.

Configuración de caché general

Además de la implementación de la caché en sí, puede establecer algunas opciones de configuración generales para controlar cómo se ejecuta la caché. Consulte CacheConfig . Después de configurar cualquiera de estas opciones, reinicie o reinicie el clúster para que la configuración surta efecto. Consulte el registro para ver si hay errores o comportamientos inesperados. 

Diseño de LruBlockCache

LruBlockCache es un caché LRU que contiene tres prioridades a nivel de bloque para permitir la resistencia al escaneo y ColumnFamilies en la memoria: 

  • Prioridad de acceso único: cuando un bloque se carga por primera vez desde HDFS, generalmente tiene esta prioridad y será parte del primer grupo que se considerará durante el desalojo. La ventaja es que los bloques de escaneo tienen más probabilidades de ser desalojados que los bloques que se usan más.
  • Prioridad de acceso múltiple: si se vuelve a acceder a un bloque del grupo de prioridad anterior, se actualizará a esta prioridad. Por tanto, forma parte del segundo grupo considerado durante el desalojo.
  • Prioridad de acceso a memoria: Si la serie del bloque está configurada como "en memoria", pasará a formar parte de esta prioridad independientemente del número de accesos. La tabla de directorio está configurada así. Este grupo es el último grupo considerado en el proceso de expulsión. Para marcar la familia de columnas como en la memoria, llame a:
    HColumnDescriptor.setInMemory(true);

Si crea una tabla desde java, o establece IN_MEMORY ⇒ verdadero cuando crea o cambia la tabla en el shell, por ejemplo:

hbase(main):003:0> create  't', {NAME => 'f', IN_MEMORY => 'true'}

Uso de LruBlockCache

Todas las tablas de usuario tienen la caché de bloques habilitada de forma predeterminada, lo que significa que cualquier operación de lectura cargará la caché de LRU. Esto puede ser beneficioso para una gran cantidad de casos de uso, pero generalmente requiere más ajustes para lograr un mejor rendimiento. Un concepto importante es el tamaño del conjunto de trabajo o WSS, es decir: "la cantidad de memoria necesaria para calcular la respuesta a la pregunta". Para un sitio web, estos serán los datos necesarios para responder la consulta en poco tiempo.

El método para calcular cuánta memoria tiene HBase en la caché es:

number of region servers * heap size * hfile.block.cache.size * 0.99

El valor predeterminado de la caché de bloques es 0.4, lo que significa el 40% del montón disponible. El último valor (99%) es el factor de carga aceptable predeterminado en la caché de LRU después de que comience el desalojo. La razón por la que se incluye en esta ecuación es que no es realista decir que se puede usar el 100% de la memoria disponible, porque impedirá que el proceso cargue el nuevo bloque. Aquí hay unos ejemplos:

  • El tamaño de pila de un servidor regional se establece en 1 GB, y el tamaño de caché de bloque predeterminado tendrá una caché de bloque de 405 MB disponible.
  • El tamaño de pila de 20 servidores regionales se establece en 8 GB, y el tamaño de caché de bloque predeterminado tendrá 63,3 cachés de bloque.
  • 100 servidores regionales con un tamaño de pila de 24 GB y un tamaño de caché de bloque de 0,5 tendrán una caché de bloque de aproximadamente 1,16 TB.

Sus datos no son los únicos residentes de la caché de bloques. Aquí hay otras preguntas que quizás deba considerar:

Tablas de directorio Las tablas hbase: meta están forzadas en la caché de bloques y tienen prioridad de memoria, lo que significa que son más difíciles de desalojar. (Según el número de regiones, la tabla meta hbase: puede ocupar varios MB).

Actualmente, la forma recomendada de medir el tamaño del índice HFile y el filtro de floración es ver la interfaz de usuario web del servidor regional y verificar las métricas relevantes. Para las claves, puede utilizar la herramienta de línea de comandos HFile para completar el muestreo y encontrar la métrica de tamaño de clave promedio. A partir de HBase 0.98.3, puede ver información detallada sobre las estadísticas y métricas de BlockCache en la sección especial Block Cache de la interfaz de usuario. 

Cuando WSS no es adecuado para la memoria, generalmente no es bueno usar el almacenamiento en caché de bloques. Por ejemplo, existe una situación en la que hay 40 GB disponibles en el caché de bloque de todos los servidores regionales, pero es necesario procesar 1 TB de datos. Una razón es que el abandono causado por el desalojo desencadenará innecesariamente más recolecciones de basura. Aquí hay dos casos de uso:

  • Modo de lectura completamente aleatorio: en este caso, casi nunca se accede a la misma fila dos veces en un corto período de tiempo, por lo que la tasa de aciertos del bloque de caché es cercana a cero. La configuración de un caché de bloques en una tabla de este tipo desperdiciará memoria y ciclos de CPU y, además, generará más basura para ser extraída por la JVM.
  • Tabla de mapeo: en un trabajo típico de MapReduce, cada fila solo se puede leer una vez, por lo que no es necesario colocarlas en la caché de bloques. El objeto Scan se puede cerrar con el método setCaching (configúrelo en falso). Si necesita acceso de lectura aleatorio rápido, aún puede mantener la caché de bloques abierta en esta tabla. Un ejemplo es el número de filas que proporcionan tráfico en tiempo real en una tabla estadística. El almacenamiento en caché de cada bloque de la tabla provocará una gran pérdida y definitivamente expulsará los datos actualmente en uso.

Solo caché de bloques META (bloques de datos en fscache)

Una configuración interesante es que solo almacenamos en caché el bloque META y leemos el bloque DATA en cada acceso. Si el bloque de DATOS es adecuado para fscache, esta alternativa puede tener sentido cuando el acceso es completamente aleatorio en un conjunto de datos muy grande. Para habilitar esta configuración, cambie su tabla y cada conjunto de familias de columnas: BLOCKCACHE ⇒'false '. Solo "inhabilitas" BlockCache para esta familia de columnas. Nunca puede deshabilitar el almacenamiento en caché de bloques META. Dado que HBASE-4683 siempre almacena en caché índices y bloques de floración, almacenaremos en caché los bloques META incluso si BlockCache está deshabilitado.

Caché de bloques fuera del montón

Cómo habilitar BucketCache

La implementación habitual de BucketCache es configurar dos capas de caché a través de una clase de administración: la caché de pila implementada por LruBlockCache y la segunda caché implementada por BucketCache. La clase de gestión tiene como valor predeterminado CombinedBlockCache. El enlace anterior describe la "estrategia" de almacenamiento en caché implementada por CombinedBlockCache. En resumen, la forma en que funciona es mantener los metabloques (ÍNDICE y BLOOM) en la capa LruBlockCache en el montón y guardar los bloques de DATOS en la capa BucketCache. 

En comparación con LruBlockCache en el montón nativo, la versión Pre-hbase-2.0.0 siempre es más lenta cuando se obtienen datos de BucketCache antes de hbase-2.0.0. Sin embargo, con el tiempo, la latencia tiende a ser menos errática, porque hay menos recolección de basura cuando se usa BucketCache, porque administra la asignación de BlockCache en lugar de GC. Si BucketCache se implementa en modo fuera de pila, el GC no administra la memoria en absoluto. Esta es la razón por la que usará BucketCache antes de la 2.0.0, por lo que su latencia es menos inestable, a fin de reducir GC y la fragmentación del montón, de modo que pueda usar más memoria de manera segura. En versiones anteriores a 2.0.0, BucketCache se puede configurar para recibir víctimas expulsadas por LruBlockCache. Todos los bloques de índice y de datos se almacenan en caché primero en L1. Cuando el desalojo ocurre en L1, los bloques (o víctimas) se moverán a L2. Configure cacheDataInL1 a (HColumnDescriptor.setCacheDataInL1 (true) o shell, configure CACHE_DATA_IN_L1 en true: para crear o modificar la familia de columnas, como: hbase (main): 003: 0> create't ', {NAME =>' t ' , CONFIGURACIÓN => {CACHE_DATA_IN_L1 => 'verdadero'}}

La versión hbase-2.0.0 + HBASE-11425 cambia la ruta de lectura de HBase para que pueda mantener los datos leídos del montón y evitar copiar los datos almacenados en caché en el montón de Java. En hbase-2.0.0, el retraso fuera del montón está cerca del tiempo de retraso de la caché del montón y no se activará GC. A partir de HBase 2.0.0, los conceptos de L1 y L2 han quedado obsoletos. Cuando se abre BucketCache, el bloque DATA siempre ingresará al BucketCache, y el bloque INDEX / BLOOM ingresará al montón LRUBlockCache. Se ha eliminado la compatibilidad con cacheDataInL1.

La caché de bloques de BucketCache se puede implementar en modo de archivo fuera de pila, archivo o archivo mmaped. 

Puede configurarlo a través de la configuración de hbase.bucketcache.ioengine. Configurarlo en offheap hace que BucketCache coloque su asignación fuera del montón, y la configuración de ioengine del archivo: PATH_TO_FILE le indicará a BucketCache que use el almacenamiento en caché de archivos (especialmente útil cuando adjunta algunas E / S rápidas a cajas como SSD). A partir de 2.0.0, varios archivos pueden admitir BucketCache. Esto es muy útil cuando los requisitos de tamaño de la caché son altos. Para múltiples archivos de respaldo, configure ioengine en archivos: PATH_TO_FILE1, PATH_TO_FILE2, PATH_TO_FILE3. BucketCache también se puede configurar para usar archivos mmapped. Configure ioengine para mmap: PATH_TO_FILE.

Podemos implementar configuraciones jerárquicas cuando omitimos la estrategia CombinedBlockCache y usamos BucketCache como una caché L2 estricta para trabajar en L1 LruBlockCache. Para tales configuraciones, establezca hbase.bucketcache.combinedcache.enabled en false. En este modo, cuando se desaloja de L1, el bloqueo pasará a L2. Cuando un bloque se almacena en caché, primero se almacenará en caché en L1. Cuando buscamos el bloque de caché, primero miramos L1, y si no podemos encontrarlo, buscamos L2. A este formato de implementación lo llamamos Raw L1 + L2. Nota: Este modo L1 + L2 se elimina de 2.0.0. Cuando se usa BucketCache, será estrictamente una caché de DATOS, y LruBlockCache almacenará en caché los bloques INDEX / META.

Otras configuraciones de BucketCache incluyen: especificar dónde guardar el caché al reiniciar, cuántos subprocesos usar para escribir el caché, etc.

Para verificar si está habilitado, busque la línea de registro que describe la configuración de la caché, que detallará cómo se implementa BucketCache. Consulte también UI. Presentará el almacenamiento en caché en niveles y su configuración en detalle.

Configuración de ejemplo de BucketCache

Este ejemplo proporciona una configuración para un BucketCache fuera de pila de 4 GB con una caché de pila de 1 GB. 

Realice la configuración en RegionServer.

Establezca hbase.bucketcache.ioengine y hbase.bucketcache.size> 0 para habilitar CombinedBlockCache. Supongamos que RegionServer se ha configurado para ejecutarse con un montón de 5G: es decir, HBASE_HEAPSIZE = 5g.

  1. Primero, edite el hbase-env.sh del RegionServer y configure HBASE_OFFHEAPSIZE en un valor mayor que el tamaño requerido fuera del montón, en este caso 4 GB (representado como 4G). Lo configuramos en 5G. Para nuestro caché fuera del montón, esto será 4G, para cualquier otro uso de memoria fuera del montón (además de BlockCache, hay usuarios de otro almacenamiento fuera del montón, como DFSClient en RegionServer que puede usar el almacenamiento fuera del montón).
    HBASE_OFFHEAPSIZE=5G
  2. A continuación, agregue la siguiente configuración a hbase-site.xml de RegionServer.
    <property>
      <name>hbase.bucketcache.ioengine</name>
      <value>offheap</value> </property>
    <property> 
      <name>hfile.block.cache.size</name> 
      <value>0.2</value> </property>
    <property>
      <name>hbase.bucketcache.size</name>
      <value>4196</value> </property>
  3. Reinicie o reinicie el clúster y verifique los registros para ver si hay algún problema.

En lo anterior, configuramos BucketCache en 4G. Configuramos LruBlockCache en el montón al 20% (0.2) (0.2 * 5G = 1G) del tamaño del montón de RegionServer. En otras palabras, configure L1 LruBlockCache como de costumbre (como si no hubiera caché L2). 

HBase-10641 presenta la función de configurar varios tamaños de depósitos para HBase 0.98 y BucketCache posterior. Para configurar varios tamaños de área de almacenamiento, configurar el nuevo hfile.block.cache atributo. Tamaños (en lugar de hfile.block.cache. Tamaño ) como una lista separada por comas de tamaños de bloque (ordenados de menor a mayor), y sin espacios. El objetivo es optimizar el tamaño del depósito de almacenamiento en función de sus patrones de acceso a los datos. El siguiente ejemplo configura depósitos de almacenamiento con tamaños de 4096 y 8192.

<property>
  <name>hfile.block.cache.sizes</name>
  <value>4096,8192</value> 
</property>

Uso de memoria directa en HBase

La memoria directa máxima predeterminada varía según la JVM. Tradicionalmente es 64M o algo relacionado con el tamaño de pila asignado (-Xmx) o sin límite (JDK7). El servidor HBase usa memoria directa, especialmente para lectura de cortocircuito, y el DFSClient alojado asignará búferes de memoria directa. El número de DFSClient utilizado no es fácil de cuantificar; es el número de archivos HFiles abiertos * hbase.dfs.client.read.shortcircuit.buffer.size, donde hbase.dfs.client.read.shortcircuit.buffer.size se establece en 128k. Si utiliza el almacenamiento en caché fuera del montón, utilizará la memoria directa. RPCServer usa el grupo ByteBuffer. A partir de 2.0.0, estos búferes son ByteBuffers fuera del montón. Inicie su JVM, asegúrese de que la configuración -XX: MaxDirectMemorySize en conf / hbase-env.sh, considere la caché de bloques fuera del montón (hbase.bucketcache.size), el uso de DFSClient y el tamaño máximo de ByteBufferPool en el lado de RPC . Debe ser mayor que la suma del tamaño de BlockCache fuera del montón y el tamaño máximo de ByteBufferPool. La asignación de 1-2 GB adicionales para el tamaño máximo de memoria directa funcionó en la prueba. La memoria directa es parte del montón de procesos de Java y está separada del montón de objetos asignado por -Xmx. MaxDirectMemorySizeEl valor asignado no debe exceder la RAM física y puede ser menor que la RAM total disponible debido a otros requisitos de memoria y limitaciones del sistema. 

Puede ver la pestaña "Métricas del servidor: Memoria" en la interfaz de usuario para ver cuánta memoria y memoria directa / fuera del montón está configurada para usar por el RegionServer y la hora cada vez que se usa. También se puede obtener a través de JMX. En particular java.nio.type=BufferPool,name=direct, la memoria directa utilizada actualmente por el servidor se puede encontrar en el bean. Terracotta tiene un buen historial de uso de memoria no dinámica en Java. Esto es para su producto BigMemory, pero muchas preguntas han mencionado cualquier intento de almacenamiento externo, compruébalo.

hbase.bucketcache.percentage.in .combinedcache

Esta es una configuración anterior a HBase 1.0 porque es desordenada. Este es un número de punto flotante, establecerá un valor entre 0.0 y 1.0, y su valor predeterminado es 0.9. Si la implementación usa CombinedBlockCache, tamaño LruBlockCache L1 se calcula como:  , tamaño BucketCache: . Si size-of-bucket-cache se especifica como Megabytes, entonces configura el valor de hbase.bucketcache.size; si hbase.bucketcache.size está entre 0 y 1.0, entonces  *  .(1 - hbase.bucketcache.percentage.in.combinedcache) * size-of-bucketcachehbase.bucketcache.percentage.in.combinedcache * size-of-bucket-cachehbase.bucketcache.size-XX:MaxDirectMemorySize

En 1.0, debería ser más directo. El tamaño de Onheap LruBlockCache se establece en una pequeña parte del montón de Java utilizando la configuración hfile.block.cache.size (no óptima), y BucketCache se establece en el valor anterior en megabytes absolutos.

Comprimir BlockCache

HBASE-11331 introduce la descompresión perezosa de BlockCache, que se llama más simplemente BlockCache comprimido. Cuando el BlockCache comprimido está habilitado, los datos y los bloques de datos codificados se almacenarán en caché en BlockCache en formato de disco en lugar de descomprimirse y descifrarse antes del almacenamiento en caché. 

Para los RegionServers que transportan más datos y no son adecuados para el almacenamiento en caché, habilitar esta función a través de la compresión SNAPPY puede aumentar el rendimiento en un 50%, aumentar la latencia promedio en un 30%, aumentar la recolección de basura en un 80% y aumentar la carga general de CPU en un 2%. Para obtener más detalles sobre cómo medir e implementar el rendimiento, consulte HBASE-11331. Para los RegionServers que contienen datos adecuados para el almacenamiento en caché, o si su carga de trabajo es sensible a la CPU adicional o la carga de recolección de basura, puede recibir menos ingresos.

BlockCache comprimido está deshabilitado de forma predeterminada. Para habilitarlo, configure hbase.block.data.cachecompressed en verdadero en hbase-site.xml de todos los RegionServers.

Índice HFiles

Un HFILE es el formato de archivo utilizado por HBase para almacenar datos en HDFS. Contiene un índice multicapa, que permite a HBase encontrar datos sin tener que leer todo el archivo. El tamaño de estos índices es un factor del tamaño del bloque (64 KB por defecto), el tamaño de la clave y la cantidad de datos almacenados. Para conjuntos de datos grandes, no es raro que la cantidad de cada servidor regional sea de aproximadamente 1 GB, pero no todos los datos se almacenarán en caché porque LRU desalojará los índices no utilizados.

botón

El valor almacenado es solo la mitad de la imagen, porque cada valor se almacena con su clave (clave de fila, calificador de familia y marca de tiempo).

Filtro de floración

Al igual que el índice HFile, estas estructuras de datos (cuando están habilitadas) se almacenan en el LRU.

Supongo que te gusta

Origin blog.csdn.net/godlovedaniel/article/details/113514158
Recomendado
Clasificación