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

Download IT Guides!

 
Spring Data's mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It makes it easy to use data access technologies, relational and non-relational databases, map-reduce frameworks, and cloud-based data services. In this eBook, we provide a compilation of Spring Data examples that will help you kick-start your own projects. We cover a wide range of topics, from setting up the environment and creating a basic project, to handling the various modules (e.g. JPA, MongoDB, Redis etc.).
 
 
Selenium is a portable software testing framework for web applications. Selenium provides a record/playback tool for authoring tests without learning a test scripting language (Selenium IDE). It also provides a test domain-specific language (Selenese) to write tests in a number of popular programming languages, including Java, C#, Groovy, Perl, PHP, Python and Ruby.In this ebook, we provide a compilation of Selenium programming examples that will help you kick-start your own projects. We cover a wide range of topics, from Installation and JUnit integration, to Interview Questions and Standalone Server functionality.
 
 
IntelliJ IDEA is a Java integrated development environment (IDE) for developing computer software. It is developed by JetBrains, and is available as an Apache 2 Licensed community edition, and in a proprietary commercial edition. Both can be used for commercial development. The IDE provides for integration with build/packaging tools like grunt, bower, gradle, and SBT. It supports version control systems like GIT, Mercurial, Perforce, and SVN. Databases like Microsoft SQL Server, ORACLE, PostgreSQL, and MySQL can be accessed directly from the IDE.
 
 
java.nio (NIO stands for non-blocking I/O) is a collection of Java programming language APIs that offer features for intensive I/O operations. It was introduced with the J2SE 1.4 release of Java by Sun Microsystems to complement an existing standard I/O. The APIs of NIO were designed to provide access to the low-level I/O operations of modern operating systems. Although the APIs are themselves relatively high-level, the intent is to facilitate an implementation that can directly use the most efficient operations of the underlying platform.
 

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 :


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.

 

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,

match ParseDateTime inputString with
| 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.

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

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!

 
The Spring Framework is an open-source application framework and inversion of control container for the Java platform. The framework's core features can be used by any Java application, but there are extensions for building web applications on top of the Java EE platform. Although the framework does not impose any specific programming model, it has become popular in the Java community as an alternative to, replacement for, or even addition to the Enterprise JavaBeans (EJB) model. In this 200 page ebook, we provide a compilation of Spring Framework tutorials that will help you kick-start your own programming projects. We cover a wide range of topics, from basic usage and best practices, to specific projects like Boot and Batch. With our straightforward tutorials, you will be able to get your own projects up and running in minimum time.
 
 
Elasticsearch is a search engine based on Lucene. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. Elasticsearch is developed in Java and is released as open source under the terms of the Apache License. Elasticsearch is the most popular enterprise search engine followed by Apache Solr, also based on Lucene. Elasticsearch can be used to search all kinds of documents. It provides scalable search, has near real-time search, and supports multitenancy. Elasticsearch is distributed, which means that indices can be divided into shards and each shard can have zero or more replicas. Each node hosts one or more shards, and acts as a coordinator to delegate operations to the correct shard(s). Rebalancing and routing are done automatically.
 
 
Docker is the world's leading software containerization platform. Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run: code, runtime, system tools, system libraries anything that can be installed on a server. This guarantees that the software will always run the same, regardless of its environment. Docker provides an additional layer of abstraction and automation of operating-system-level virtualization on Linux. Docker uses the resource isolation features of the Linux kernel such as cgroups and kernel namespaces, and a union-capable file system such as OverlayFS and others to allow independent "containers" to run within a single Linux instance, avoiding the overhead of starting and maintaining virtual machines.
 
 
JMeter is an application that offers several possibilities to configure and execute load, performance and stress tests using different technologies and protocols. It allows simulating different type of requests against all kind of databases, FTP, HTTP, HTTPS or other kind of servers. Originally JMeter was designed to test web applications, but its functionality has expanded and nowadays allows testing against almost any kind of program and can be used to perform functional tests in your applications.Thisis a standalone, reference guide to provide a framework on how to work with JMeter and help you quickly kick-start your JMeter applications!
 

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/

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.
Estos objetivos llevaron a un diseño que tomó un par de notas de la API de GraphX en Spark. Por ejemplo, en HBase-Spark hay un objeto llamado HBaseContext. Esta clase tiene un constructor que toma la información de configuración de HBase y luego, una vez construida, le permite hacer un montón de operaciones en ella. Por ejemplo:
  • 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.
La arquitectura básica aún se mantiene, ya que la parte central del código está diseñada para obtener un objeto de conexión HBase en cada Ejecutor Spark.

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.