Translate
viernes, 19 de abril de 2019
Transferencia indirecta en Cassandra
Veamos el siguiente escenario: una solicitud de escritura se envía a Cassandra, pero un nodo de réplica al que pertenece la escritura, no está disponible debido un problema de la red, falla de hardware o alguna otra razón. Con el fin de garantizar la disponibilidad general del anillo en tal situación, Cassandra implementa una función llamada transferencia indirecta. Se puede pensar en una sugerencia como una pequeña nota Post-it que contiene la información de la solicitud de escritura. Si el nodo de réplica al que pertenece la escritura ha fallado, el coordinador creará una sugerencia, que es un pequeño recordatorio que dice: "Tengo la información de escritura destinada al nodo 4. Voy a recordar esta escritura hasta que el nodo 4 vuelva a estar en línea; cuando lo haga, le enviaré la solicitud de escritura". Es decir, una vez que detecte a través de gossip que el nodo 4 está nuevamente en línea, el nodo 6 entregará al nodo 4 la orden de escritura. Cassandra tiene una sugerencia diferente para cada partición que se va a escribir.
Esto permite que Cassandra esté siempre disponible para escrituras, y generalmente permite que un clúster sostenga la misma carga de escritura incluso cuando algunos de los nodos están inactivos. También reduce el tiempo en que un nodo fallido será inconsistente después de que vuelva a estar en línea.
En general, las sugerencias no cuentan como escrituras para propósitos de nivel de consistencia. La excepción es el nivel de consistencia ANY, que se agregó en 0.6. Este nivel de consistencia significa que un traspaso indirecto solo será suficiente para el éxito de una operación de escritura. Es decir, incluso si solo se pudo grabar una pista, la escritura todavía cuenta como exitosa. Tenga en cuenta que la escritura se considera duradera, pero es posible que los datos no se puedan leer hasta que la sugerencia se envíe a la réplica de destino.
Existe un problema práctico con las transferencia indirecta (y, en este caso, los enfoques de entrega garantizados): si un nodo está fuera de línea durante algún tiempo, los consejos pueden acumularse considerablemente en otros nodos. Luego, cuando los otros nodos notan que el nodo fallado ha vuelto a estar en línea, tienden a inundar ese nodo con solicitudes, justo en el momento en que es más vulnerable (cuando está luchando para volver a trabajar después de una falla). Para resolver este problema, Cassandra limita el almacenamiento de sugerencias a una ventana de tiempo configurable. También es posible deshabilitar el traspaso insinuado por completo.
Como su nombre lo sugiere, org.apache.cassandra.db.HintedHandOffManager es la clase
que gestiona las transferencias indirectas internamente.
Aunque la Transferencia indirecta ayuda a aumentar la disponibilidad de Cassandra, no reemplaza completamente la necesidad de reparación manual para garantizar la consistencia.
jueves, 18 de abril de 2019
Libros de java code geeks
domingo, 14 de abril de 2019
Caching en Apache Cassandra
Como vemos en la imagen anterior, Cassandra proporciona tres formas de almacenamiento en caché:
- La key cache almacena un mapa de claves de partición, lo que facilita un acceso de lectura más rápido a los archivos SSTables almacenados en el disco. La key cache se almacena en el heap de JVM.
- La row cache almacena filas enteras y puede acelerar enormemente el acceso de lectura para las filas a las que se accede con frecuencia, pero el costo de memoria es mayor. La row cache se almacena en la memoria fuera del heap.
- La counter cache se agregó en la versión 2.1 para mejorar el rendimiento del contador al reducir la contención de bloqueo para los contadores de acceso más frecuente.
De forma predeterminada, key cache y counter cache estan habilitados, mientras que la row cache está desactivada, ya que requiere más memoria. Cassandra guarda sus cachés en el disco periódicamente para ser más rápida en un reinicio de los nodos.
sábado, 13 de abril de 2019
Resultado de la encuesta 2019 de StackOverflow
StackOverflow desde hace algunos años hace unas encuestas que son muy buenas y nos permiten ver como esta el mercado del software.
En ocasión, no vi algo muy novedoso solo me llamo la atención es el lenguaje más amado :
Dejo link: https://insights.stackoverflow.com/survey/2019
En ocasión, no vi algo muy novedoso solo me llamo la atención es el lenguaje más amado :
Claramente le voy a tener que dar una oportunidad a Rush.
Dejo link: https://insights.stackoverflow.com/survey/2019
jueves, 11 de abril de 2019
BigData Europe
Necesitas una imagen de docker con un proyecto para procesar datos, bueno Big Data Europe es para vos...
Dejo link: https://github.com/big-data-europe
miércoles, 10 de abril de 2019
Python Developers Survey 2018 Results
Jetbrain como todos los años hace su encuestas y así tenemos los resultados:
https://www.jetbrains.com/research/python-developers-survey-2018/
La verdad no hubo muchas cosas que me llamaron la atención python es un lenguje que esta instalado ya en la sociedad.
Si puedo hacer una revisión a una cuestion sobre la relación de python con bigdata. Al parecer la gente de python utiliza spark para analizar sus datos.
https://www.jetbrains.com/research/python-developers-survey-2018/
La verdad no hubo muchas cosas que me llamaron la atención python es un lenguje que esta instalado ya en la sociedad.
Si puedo hacer una revisión a una cuestion sobre la relación de python con bigdata. Al parecer la gente de python utiliza spark para analizar sus datos.
domingo, 7 de abril de 2019
Memtables, SSTables y Commit Logs en Apache Cassandra
Veamos como es la estructura interna y archivos de apache cassandra. Cassandra guarda datos en memoria y en disco, uno que provee alta performance y el otro durabilidad. Cassandra tiene 3 estrucuras de guardado, memtables, sstables y commit logs.
Cuando realiza una operación de escritura, se escribe inmediatamente en commit logs. Commit logs es un mecanismo de recuperación ante errores. Permite volver a cassandra al estado anterior del error.
Una escritura no se considerará exitosa hasta que se escriba en el commit logs, para garantizar que si una operación de escritura no llega al almacén en memoria, aún será posible recuperar la datos. Si cierra la base de datos o se bloquea inesperadamente, el registro de confirmación puede garantizar que no se pierdan los datos. Esto se debe a que la próxima vez que inicie el nodo, el commit logs se volverá a reproducir. De hecho, esa es la única vez que se lee el registro de confirmación; los clientes nunca leen.
Después de que se escriba en el commit logs, el valor se escribe en una estructura de datos residente en la memoria llamada memtable. Cada memtable contiene datos para una tabla específica. En las primeras implementaciones de Cassandra, las memtables se almacenaban en el heap de JVM, pero las mejoras a partir de la versión 2.1 han trasladado la mayoría de los datos memtables a la memoria nativa. Esto hace que Cassandra sea menos susceptible a las fluctuaciones en el rendimiento debido a la recolección de basura de Java.
Cuando el número de objetos almacenados en la memtable alcanza un umbral, el contenido de la memtable se vacía en el disco en un archivo llamado SSTable. Entonces se crea una nueva memtable. Este lavado es una operación sin bloqueo; pueden existir múltiples memtables para una sola tabla, una actual y el resto a la espera de que se vacíe. Por lo general, no deberían tener que esperar mucho tiempo, ya que el nodo debería limpiarlos muy rápidamente a menos que esté sobrecargado.
Cada commit logs mantiene un indicador de bit interno para indicar si necesita vaciarse. Cuando se recibe una operación de escritura por primera vez, se escribe en el commit logs y su marca de bit se establece en 1. Solo hay una marca de bit por tabla, porque solo se escribe un commit logs en todo el servidor. Todas las escrituras en todas las tablas entrarán en el mismo commit logs, por lo que el indicador de bit indica si un commit logs en particular contiene algo que no se haya vaciado para una tabla en particular. Una vez que el memtable se ha colocado correctamente en el disco, el indicador de bit del commit logs correspondiente se establece en 0, lo que indica que el commit logs ya no tiene que mantener esos datos por motivos de durabilidad. Al igual que los archivos de registro normales, los commit logs tienen un umbral de transferencia configurable, y una vez que se alcanza este umbral de tamaño de archivo, el registro se reiniciará, llevando consigo los indicadores de bits sucios existentes.
El SSTable es un concepto tomado de Bigtable de Google. Una vez que un memtable se vacía en el disco como un SSTable, es inmutable y no puede ser cambiado por la aplicación. Luego las SSTables son compactadas, esta compactación cambia su representación en el disco y realiza el paso de "fusión" de una combinación en nuevos archivos y elimina los archivos antiguos en caso de éxito.
Desde la versión 1.0, Cassandra ha admitido la compresión de SSTables para maximizar el uso del almacenamiento disponible. Esta compresión es configurable por tabla. Cada SSTable también tiene un filtro Bloom asociado, que se utiliza como un mejorador de rendimiento adicional.
Todas las escrituras son secuenciales, esta es la razón principal por que las escrituras funcionan tan bien en Cassandra. No se requieren lecturas ni búsquedas de ningún tipo para escribir un valor a Cassandra porque todas las escrituras son operaciones de adición. Esto hace que una limitación clave en el rendimiento sea la velocidad de su disco. La compactación está destinada a amortizar la reorganización de datos, pero utiliza I/O secuencial para hacerlo. Así que el beneficio de rendimiento se obtiene mediante la división; la operación de escritura es solo un apéndice inmediato, y luego la compactación ayuda a organizar para un mejor rendimiento de lectura en el futuro.
En las lecturas, Cassandra leerá tanto SSTables como memtables para encontrar valores de datos, ya que la memtable puede contener valores que aún no se han vaciado en el disco. Los memtables son implementados por la clase org.apache.cassandra.db.Memtable.
Consultas y el coordinador de nodos en Apache Cassandra
Vamos a discutir como Cassandra coordina los nodos ante una consulta o escritura de un cliente.
Un cliente puede conectarse con cualquier nodo del anillo para realizar consultas o escrituras. Este nodo se denomina coordinator node o nodo coordinador. El coordinador identifica que nodos son replicas del dato que debe ser guardado o leido y luego procesa la consulta o escritura.
Para escribir, el coordinador contancta a todas las replicas que debe contactar según el consistency level o nivel de consistencia y el factor de replicación y considera la escritura exitosa cuando el numero de replicaciónes escritas son compatibles con el numero determinado en el nivel de consistencia.
Para la lectura, el coordinador contacta las replicas que son necesarias para aplicar con el nivel de consistencia, y retorna el dato al cliente.
Estos son los “caminos felices”, pero no todo es color de rosas y luego debemos discutir que sucede cuando no tenemos el numero de replicaciones para aplicar al nivel de consistencia.
sábado, 6 de abril de 2019
Consistency Levels en Apache Cassandra
El teorema de CAP de Brewer nos indica que en el que la consistencia, la disponibilidad y la tolerancia de partición se intercambian entre sí es deci no puede haber base que cumpla los 3 pero se pueden intercambiar. Cassandra proporciona niveles de consistencia ajustables que le permiten realizar estas compensaciones en un nivel de grano fino.
Se puede especificar un nivel de consistencia en cada consulta de lectura o escritura que indica cuánta consistencia necesita. Un nivel de consistencia más alto significa que más nodos deben responder a una consulta de lectura o escritura, lo que le da más seguridad de que los valores presentes en cada réplica son los mismos.
Para las consultas de lectura, el nivel de consistencia especifica cuántos nodos de réplica deben responder a una solicitud de lectura antes de devolver los datos. Para las operaciones de escritura, el nivel de consistencia especifica cuántos nodos de réplica deben responder para que la escritura se informe como exitosa al cliente. Debido a que Cassandra finalmente es consistente, las actualizaciones a otros nodos de réplica pueden continuar en segundo plano.
Los niveles de consistencia disponibles incluyen UNO, DOS y TRES, cada uno de los cuales especifica un número absoluto de nodos de réplica que deben responder a una solicitud. El nivel de consistencia QUORUM requiere una respuesta de la mayoría de los nodos de réplica (a veces expresados como "factor de replicación / 2 + 1"). El nivel de consistencia de ALL requiere una respuesta de todas las réplicas. Examinaremos estos niveles de consistencia y otros más detalladamente en el Capítulo 9.
Tanto para las lecturas como para las escrituras, los niveles de consistencia de ANY, ONE, TWO y THREE se consideran débiles, mientras que QUORUM y ALL se consideran fuertes. La coherencia se puede ajustar en Cassandra porque los clientes pueden especificar el nivel de consistencia deseado tanto en las lecturas como en las escrituras. Hay una ecuación que se usa popularmente para representar la manera de lograr una consistencia fuerte en Cassandra: R + W> N = consistencia fuerte. En esta ecuación, R, W y N son el recuento de réplicas de lectura, el recuento de réplicas de escritura y el factor de replicación, respectivamente; todas las lecturas de los clientes verán la escritura más reciente en este escenario, y tendrá una consistencia sólida.
Si eres nuevo en Cassandra, el factor de replicación a veces se puede confundir con el nivel de consistencia. El factor de replicación se establece por espacio de teclas. El nivel de consistencia es especificado por consulta, por el cliente.
El factor de replicación indica cuántos nodos desea utilizar para almacenar un valor durante cada operación de escritura. El nivel de consistencia especifica cuántos nodos ha decidido el cliente debe responder
Para sentirse seguro de una operación de lectura o escritura exitosa. La confusión surge porque el nivel de consistencia se basa en el factor de replicación, no en el número de nodos en el sistema.
Tipos que pueden ser referencia a nulos en F# 5
La introducción de tipos que pueden ser referencia a nulos en en C # representa el mayor cambio en la forma en que los desarrolladores de .NET escriben código desde async / await. Una vez que esté en funcionamiento, se tendrán que actualizar innumerables bibliotecas con anotaciones que admiten nulos para que esta característica funcione correctamente. Y para garantizar la interoperabilidad, F # deberá tambien modificarse.
F# actualmente soporta varias versiones de nulabilidad. Primero hay tipos normales de referencia en .NET. Hoy en día no hay manera de informar inequívocamente al compilador si una variable de tipo de referencia específica es nullable o no, por lo que se desaconseja su uso en F #.
La alternativa preferida es la Option<T>. También conocido como un tipo de "tal vez", esta es una forma segura para expresar el concepto de nulabilidad. Cuando se usa con el código F # idiomático, solo puede leer el valor después de verificar si no es nulo (no es "ninguno" en el lenguaje F #). Esto generalmente se hace a través de la comparación de patrones. Por ejemplo,
F# actualmente soporta varias versiones de nulabilidad. Primero hay tipos normales de referencia en .NET. Hoy en día no hay manera de informar inequívocamente al compilador si una variable de tipo de referencia específica es nullable o no, por lo que se desaconseja su uso en F #.
La alternativa preferida es la Option<T>. También conocido como un tipo de "tal vez", esta es una forma segura para expresar el concepto de nulabilidad. Cuando se usa con el código F # idiomático, solo puede leer el valor después de verificar si no es nulo (no es "ninguno" en el lenguaje F #). Esto generalmente se hace a través de la comparación de patrones. Por ejemplo,
match ParseDateTime inputString with
| Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
| None -> printfn "Failed to parse the input."
| Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
| None -> printfn "Failed to parse the input."
Option<T> es un tipo de referencia. Esto puede llevar a una gran cantidad de uso de memoria innecesaria, por lo que se creó una alternativa basada en estructura llamada ValueOption<T> en F # 4.5. Sin embargo, a ValueOption<T> le faltan algunas características que no estarán completas hasta que se lance F # 4.6.
Otro tipo de null F # con el que los desarrolladores deben tratar es Nullable<T>. Esto es similar a ValueOption<T>, pero está restringido a solo tipos de valor.
Las clases también se pueden marcar como nullables. Si el tipo tiene el atributo AllowNullLiteral, entonces todas las variables de ese tipo se consideran nullables. Esto puede ser problemático cuando desea que algunas variables de ese tipo sean nullables, pero no otras.
Las clases también se pueden marcar como nullables. Si el tipo tiene el atributo AllowNullLiteral, entonces todas las variables de ese tipo se consideran nullables. Esto puede ser problemático cuando desea que algunas variables de ese tipo sean nullables, pero no otras.
Un problema fundamental de diseño con F # tal como se encuentra actualmente es que todas estas formas diferentes de nulabilidad son incompatibles. No solo se necesitan conversiones entre los diferentes tipos de nulos, sino que también existen diferencias importantes en la forma en que funcionan. Por ejemplo, una Option<T> es recursiva, lo que le permite tener una Option<Option<Int32>> mientras que Nullable<T> no lo es. Esto puede llevar a problemas inesperados cuando se mezclan.
Otra forma en que esta incompatibilidad entra en juego es el atributo CLIMutable. Normalmente, los tipos de registro son inmutables, pero eso los hace incompatibles con los ORM. Este atributo soluciona ese problema, pero introduce uno nuevo. Ahora que el registro es mutable, los nulos se pueden deslizar después de crear el objeto, rompiendo la suposición de que los registros no contienen nulos.
El plan actual es indicar variables anulables con un ? sufijo como vemos en C#. Y al igual que C# 8, recibirá advertencias si intenta invocar un método o una propiedad en una variable que puede contener nulos sin verificar primero si es nulo. Del mismo modo, la asignación de un valor nulo a una variable no anulable es solo una advertencia, por lo que el código heredado continúa compilando.
Esta funcionalidad se considera como opt-in. Los nuevos proyectos lo tendrán activado de forma predeterminada, mientras que los proyectos existentes lo desactivarán de forma predeterminada.
Los ejemplos a continuación fueron proporcionados por la propuesta de Tipos de Referencia de Nullable y están sujetos a cambios.
// Declared type at let-binding
let notAValue : string? = null
// Declared type at let-binding
let isAValue : string? = "hello world"
let isNotAValue2 : string = null // gives a nullability warning
let getLength (x: string?) = x.Length // gives a nullability warning since x is a nullable string
// Parameter to a function
let len (str: string?) =
match str with
| null -> -1
| NonNull s -> s.Length // binds a non-null result
// Parameter to a function
let len (str: string?) =
let s = nullArgCheck "str" str // Returns a non-null string
s.Length // binds a non-null result
// Declared type at let-binding
let maybeAValue : string? = hopefullyGetAString()
// Array type signature
let f (arr: string?[]) = ()
// Generic code, note 'T must be constrained to be a reference type
let findOrNull (index: int) (list: 'T list) : 'T? when 'T : not struct =
match List.tryItem index list with
| Some item -> item
| None -> null
let notAValue : string? = null
// Declared type at let-binding
let isAValue : string? = "hello world"
let isNotAValue2 : string = null // gives a nullability warning
let getLength (x: string?) = x.Length // gives a nullability warning since x is a nullable string
// Parameter to a function
let len (str: string?) =
match str with
| null -> -1
| NonNull s -> s.Length // binds a non-null result
// Parameter to a function
let len (str: string?) =
let s = nullArgCheck "str" str // Returns a non-null string
s.Length // binds a non-null result
// Declared type at let-binding
let maybeAValue : string? = hopefullyGetAString()
// Array type signature
let f (arr: string?[]) = ()
// Generic code, note 'T must be constrained to be a reference type
let findOrNull (index: int) (list: 'T list) : 'T? when 'T : not struct =
match List.tryItem index list with
| Some item -> item
| None -> null
Como puede ver, la nueva sintaxis se adapta bien a los patrones F # existentes, incluso admite la coincidencia de patrones de manera similar a la Option<T>.
También hay un conjunto de funciones de ayuda para agregar en el código general y la coincidencia de patrones.
isNull: determina si el valor dado es nulo.
nonNull: afirma que el valor no es nulo. Provoca una NullReferenceException cuando el valor es nulo, de lo contrario, devuelve el valor.
withNull: convierte el valor en un tipo que admite nulo como un valor normal.
(| NonNull |): cuando se usa en un patrón, se afirma que el valor que se compara no es nulo.
(| Null | NotNull |): Un patrón activo que determina si el valor dado es nulo.
Las firmas de funciones completas están disponibles en la propuesta.
jueves, 4 de abril de 2019
Nuevos libros de Java Code Geeks
Download IT Guides!
|
|
|
|
martes, 2 de abril de 2019
Estrategias de replicación en Cassandra
Antes de ponernos a hablar de la replicación veamos, para que replicar?
- prevenir pérdida de datos
- acercar los datos.
- segregación de tipos de tareas
Un nodo sirve como una réplica para diferentes rangos de datos. Si un nodo se cae, otras réplicas pueden responder a las consultas para ese rango de datos. Cassandra replica datos a través de nodos de manera transparente para el usuario, y el factor de replicación es el número de nodos en su grupo que recibirá copias (réplicas) de los mismos datos. Si su factor de replicación es 3, entonces tres nodos en el anillo tendrán copias de cada fila.
La primera réplica siempre será el nodo que reclama el rango en el que cae el token, pero el resto de las réplicas se colocan de acuerdo con la estrategia de replicación (a veces también se conoce como la estrategia de colocación de réplicas).
Para determinar la ubicación de la réplica, Cassandra implementa el patrón Strategy, que se describe en la clase abstracta común org.apache.cassandra.locator.AbstractReplicationStrategy, que permite diferentes implementaciones de un algoritmo (diferentes estrategias para lograr el mismo trabajo). Cada implementación de algoritmo está encapsulada dentro de una sola clase que extiende la estrategia de integración de elementos abstractos
Cassandra proporciona dos implementaciones principales de esta interfaz (extensiones de la clase abstracta): SimpleStrategy y NetworkTopologyStrategy.
SimpleStrategy coloca réplicas en nodos consecutivos alrededor del anillo, comenzando con el nodo indicado por el particionador.
La NetworkTopologyStrategy le permite especificar un factor de replicación diferente para cada centro de datos. Dentro de un centro de datos, asigna réplicas a diferentes racks para maximizar la disponibilidad.
La estrategia se establece de forma independiente para cada espacio de claves y es una opción requerida para crear un espacio de claves.
domingo, 31 de marzo de 2019
Por qué Cristal es un lenguaje de programación importante?
Por qué opino que Cristal es un lenguaje de programación importante? Es una buena pregunta. Cristal implementa un lenguaje de tipado dinámico como Ruby como un lenguaje de tipado estático mediante la inferencia de tipos.
Parece una tontería pero permite obtener código de tipado estático, lo cual nos trae con sigo una herramienta fundamental para la búsqueda de errores que es el chequeo por tipo. Sin tener que sacrificar casi nada de nuestro lenguaje de tipado dinámico.
Digo casi nada porque por ejemplo no podemos cambiar el tipo de una variable, por ejemplo :
var a = 2
a = "hola"
no compilaría, pero la pregunta del millón es ¿ eso es útil ?
Es decir a alguien realmente le interesa cambiar de tipo una variable, yo creo que no. No escribo código de tipado dinámico pero imagino, que no existe un interés de reutilizar las variables. Por lo tanto festejo que no se pueda hacer esto en Cristal.
Por ultimo, ¿que piensan, otros lenguajes le seguirán los pasos a Cristal?
Dejo link: https://crystal-lang.org/
Parece una tontería pero permite obtener código de tipado estático, lo cual nos trae con sigo una herramienta fundamental para la búsqueda de errores que es el chequeo por tipo. Sin tener que sacrificar casi nada de nuestro lenguaje de tipado dinámico.
Digo casi nada porque por ejemplo no podemos cambiar el tipo de una variable, por ejemplo :
var a = 2
a = "hola"
no compilaría, pero la pregunta del millón es ¿ eso es útil ?
Es decir a alguien realmente le interesa cambiar de tipo una variable, yo creo que no. No escribo código de tipado dinámico pero imagino, que no existe un interés de reutilizar las variables. Por lo tanto festejo que no se pueda hacer esto en Cristal.
Por ultimo, ¿que piensan, otros lenguajes le seguirán los pasos a Cristal?
Dejo link: https://crystal-lang.org/
Apache Spark llega a Apache HBase con HBase-Spark
HBase-Spark fue commiteado por primera vez a Github en julio de 2014. HBase-Spark salió de una simple solicitud de clientes para tener un nivel de interacción entre HBase y Spark similar al ya disponible entre HBase y MapReduce. Aquí hay un breve resumen de la funcionalidad que brinda dicha librería:
Acceso completo a HBase:
- Posibilidad de hacer una carga masiva.
- Posibilidad de realizar operaciones masivas como put, get o delete
- Posibilidad de ser una fuente de datos para motores SQL.
El enfoque que se le dio a la librería tiene los siguientes objetivos:
- Hacer las conexiones HBase sin problemas.
- Hacer la integración de Kerberos sin problemas.
- Crear RDDs a través de acciones de escaneo o desde un RDD existente que se usando comandos Get.
- Tomar cualquier RDD y permita que se realice cualquier combinación de operaciones HBase.
- Proporcione métodos simples para operaciones comunes mientras permite operaciones avanzadas desconocidas sin restricciones a través de la API.
- Soporte Scala y Java.
- Soporta Spark y Spark Streaming con una API similar.
- Crear RDD / DStream desde una Scaneo.
- Poner / Eliminar el contenido de un RDD / DStream en HBase
- Crear un RDD / DStream a partir de los contenidos de un RDD / DStream
- Tomar el contenido de un RDD / DStream y realizar cualquier operación si se le entregó una HConnection en el proceso de trabajo.
Veamos unos ejemplos por ejemplo como podemos hacer un bulk delete :
val hbaseContext = new HBaseContext(sc, config)
rdd.hbaseBulkDelete(hbaseContext,
TableName.valueOf(tableName),
putRecord => new Delete(putRecord),
4)
Aquí hay un ejemplo de una función de partición de mapa donde podemos obtener un objeto de conexión a medida que iteramos sobre nuestros valores:
val getRdd = rdd.hbaseMapPartitions(hbaseContext, (it, conn) => {
val table = conn.getTable(TableName.valueOf("t1"))
var res = mutable.MutableList[String]()
...
})
MapPartitions funciona como map es decir toma un rdd y lo transforma en otro rdd.
Veamos un ejemplo completo donde guardamos los objetos con ids 1, 2, 3, 4, 5 :
// Nothing to see here just creating a SparkContext like you normally would
val sparkConf = new SparkConf().setAppName("HBaseBulkPutExample " + tableName + " " + columnFamily)
val sc = new SparkContext(sparkConf)
//This is making a RDD of
//(RowKey, columnFamily, columnQualifier, value)
val rdd = sc.parallelize(Array(
(Bytes.toBytes("1"), Array((Bytes.toBytes(columnFamily), Bytes.toBytes("1"), Bytes.toBytes("1")))),
(Bytes.toBytes("2"), Array((Bytes.toBytes(columnFamily), Bytes.toBytes("1"), Bytes.toBytes("2")))),
(Bytes.toBytes("3"), Array((Bytes.toBytes(columnFamily), Bytes.toBytes("1"), Bytes.toBytes("3")))),
(Bytes.toBytes("4"), Array((Bytes.toBytes(columnFamily), Bytes.toBytes("1"), Bytes.toBytes("4")))),
(Bytes.toBytes("5"), Array((Bytes.toBytes(columnFamily), Bytes.toBytes("1"), Bytes.toBytes("5"))))
)
)
//Create the HBase config like you normally would then
//Pass the HBase configs and SparkContext to the HBaseContext
val conf = HBaseConfiguration.create();
conf.addResource(new Path("/etc/hbase/conf/core-site.xml"));
conf.addResource(new Path("/etc/hbase/conf/hbase-site.xml"));
val hbaseContext = new HBaseContext(sc, conf);
//Now give the rdd, table name, and a function that will convert a RDD record to a put, and finally
// A flag if you want the puts to be batched
hbaseContext.bulkPut[(Array[Byte], Array[(Array[Byte], Array[Byte], Array[Byte])])](rdd,
tableName,
//This function is really important because it allows our source RDD to have data of any type
// Also because puts are not serializable
(putRecord) > {
val put = new Put(putRecord._1)
putRecord._2.foreach((putValue) > put.add(putValue._1, putValue._2, putValue._3))
put
},
true);
Ahora, cada partición de ese RDD se ejecutará en paralelo (en diferentes subprocesos en un número de trabajadores de Spark en el clúster), algo así como lo que habría ocurrido si hiciéramos Puts en una tarea MapReduce.
Una cosa a tener en cuenta es que se aplican las mismas reglas cuando se trabaja con HBase de MapReduce o Spark en términos de rendimiento de Get y Put. Si tiene Puts que no están particionados, lo más probable es que se envíe un lote de Put a cada RegionServer, lo que dará como resultado menos registros por RegionServers por lote. La imagen a continuación ilustra cómo se vería esto con seis RegionServers:
Ahora veamos el mismo diagrama si utilizamos Spark para particionar primero antes de hablar con HBase.
miércoles, 27 de marzo de 2019
Suscribirse a:
Entradas (Atom)