Translate

Mostrando las entradas con la etiqueta Apache Cassandra. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Apache Cassandra. Mostrar todas las entradas

sábado, 17 de julio de 2021

Crear una base de datos cassandra con Docker


Antes de empezar tenes que tener docker andando. 

Esto es muy fácil, en dockerhub hay una imagen de cassandra : https://hub.docker.com/_/cassandra

Bueno, en consola ponemos : 

$ docker run --name some-cassandra --network some-network -d cassandra:tag

Donde some-cassandra es el nombre de la base, network es el modo de red que va utilizar y tag es la versión. Yo puse algo así: 

docker run --name demo4-cassandra --network host -d cassandra:4.0

Y listo, cassandra funcionando. 

Ahora tenemos que crear el keyspace, vamos a entrar en el container con el comando: 

docker exec -it some-cassandra bash

Que es similar a lo que ya vimos antes, yo utilice este : 

docker exec -it demo4-cassandra bash

y dentro del container vamos donde esta cassandra : 

cd /opt/cassandra/bin

cqlsh

Y ejecutamos el comando para crear el keyspace : 

cqlsh> CREATE KEYSPACE IF NOT EXISTS demo WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 1 };

cqlsh> use demo;


Y listo!! 

viernes, 10 de abril de 2020

Complimentary O’Reilly Cassandra Book


Me llego este mail de un libro que estuve leyendo y esta muy bueno, de cassandra :


Hello Emanuel, 

Thanks for your recent interest in Apache Cassandra™, I’m here to help with any content resources to make you successful.

The newest edition of O’Reilly’s “Cassandra, The Definitive Guide” by Jeff Carpenter and Eben Hewitt is just out, here is a complimentary PDF.

Our community forum is also a good place to ask or answer questions.

Again, our mission is to help you be successful with Cassandra. I hope these are useful!

Best Regards,
Angela Young
angela.young@datastax.com | datastax.com

miércoles, 27 de noviembre de 2019

DataStax publica un libro gratuito de Apache Cassandra

Me llego el siguiente mail de DataStax, sobre un libro de Cassandra:

constellation
Fortune 500 companies have fallen in love with Apache Cassandra for its scalability and high availability. But what’s the difference between Cassandra’s distributed database technology and relational databases? And where do you even begin with Cassandra? In this new e-book, foremost NoSQL experts answer those questions and more.

martes, 1 de octubre de 2019

Diagramas de Chebotko


Con frecuencia es útil presentar diseños de modelos de datos lógicos y físicos visualmente. Para lograr esto en Cassandra, podemos utilizar Diagrama de Chebotko, que presenta un diseño de esquema de base de datos como una combinación de esquemas de tabla individuales y transiciones de flujo de trabajo de aplicaciones basadas en consultas. Algunas de las ventajas de los Diagramas de Chebotko, en comparación con los scripts de definición de esquemas de CQL regulares, incluyen una legibilidad general mejorada, una inteligibilidad superior para modelos de datos complejos y una mejor expresividad con esquemas de tabla y sus consultas de aplicaciones compatibles. Los diagramas de nivel físico contienen información suficiente para generar un script CQL que instancia un esquema de base de datos y puede servir como documentos de referencia para desarrolladores y arquitectos que diseñan y mantienen una solución basada en datos.

Dentro de la comunidad de Cassandra han propuesto anotaciones para capturar modelos de datos en forma de diagrama. Y se popularizo el diagrama creado  por Artem Chebotko que proporciona una forma simple e informativa de visualizar las relaciones entre consultas y tablas en nuestros diseños.

Cada tabla se muestra con su título y una lista de columnas. Las columnas de clave principal se identifican mediante símbolos como K para columnas de clave de partición y C ↑ o C ↓ para representar columnas de agrupamiento. Las líneas se muestran entrando en tablas o entre tablas para indicar las consultas que cada tabla está diseñada para admitir.
   

Modelado de datos en Cassandra

Nosotros en casandra podemos guradar algun id y verlo como una foreign key pero este concepto no existe en realidad, el motor de base de datos no realiza ningun checkeo.

En el diseño de bases de datos relacionales, a menudo se nos enseña la importancia de la normalización. Esto no es una ventaja cuando se trabaja con Cassandra porque funciona mejor cuando el modelo de datos está desnormalizado. A menudo ocurre que las empresas también terminan desnormalizando datos en bases de datos relacionales.

Hay dos razones comunes para esto:

Uno es el rendimiento. Las empresas simplemente no pueden obtener el rendimiento que necesitan cuando tienen que hacer tantas uniones en datos, por lo que desnormalizar puede ser una solución para la performance.  Esto termina funcionando, pero va en contra de la forma en que se pretende diseñar las bases de datos relacionales por lo tanto no tiene sentido usar base de datos relacionales.

Una segunda razón es conservar un historial. El ejemplo común aquí es con las facturas. Ya tiene tablas de clientes y productos, y pensaría que podría hacer una factura que referencie esas tablas. Pero esto nunca debe hacerse en la práctica. La información del cliente o del precio podría cambiar, y luego perdería la integridad del documento tal como estaba en la fecha de la factura, lo que podría violar auditorías, informes o leyes, y causar otros problemas.

En el mundo relacional, la desnormalización viola las formas normales de Codd y tratamos de evitarla. Pero en Cassandra, la desnormalización es, bueno, perfectamente normal.

En cassandra existen una tecnicas para modelar nuestros datos :
Query-first design o diseño orientado a consultas: En cassandra podemos comenzar modelando de los datos desde las consultas, la información se debe organizar según las consultas que necesitamos. De esta manera vamos a tener un monton de datos repetidos pero esto no es significativo, dado que con cassandra el hardware es relativamente barato y la escritura muy rapida.

En las base de datos relacionales muchas veces es transparente como se organiza la base a como se guardan los datos en disco. En cambio en cassandra cada tabla es guardada en un archivo diferente en el disco. Por lo tanto es importante mantener columnas relacionadas en la misma tabla. Un objetivo de cassandra es minimizar el numero de particiones donde hay que buscar con el objetivo de satisfacer una query. Pensemos que buscar los datos en una partición puede ser sumamente más performate que buscarlo en nodos separados.

En las base de datos relacionales es muy facil cambiar el orden en una consulta con la instrucción ORDER BY. Y no se puede especificar el orden con los que se guardan los datos y por defecto los datos son recuperados según fueron grabados. En cassandra esto cambia un poco dado que esta es una decisión de diseño. El order es fijo y esta determinado por las clustering columns. Es decir el select permite utilizar el order by pero solo en las clustering columns.

sábado, 21 de septiembre de 2019

Charla sobre Apache Cassandra


El día martes 24 de Septiembre Hexacta dictará a través de la plataforma de streaming provista por la Universidad Tecnológica Nacional Facultad Regional Paraná una charla sobre Apache Cassandra. Los esperamos!
Formulario de inscripción: https://bit.ly/2m3ZLsE

jueves, 1 de agosto de 2019

SASI : Una nueva implementación del índice secundario en Cassandra


La versión Cassandra 3.4 incluía una implementación alternativa de índices secundarios conocida como SSTable Attached Secondary Index (SASI). SASI fue desarrollado por Apple y lanzado como una implementación de código abierto de la API del índice secundario de Cassandra. Como su nombre lo indica, los índices SASI se calculan y almacenan como parte de cada archivo SSTable, a diferencia de la implementación original de Cassandra, que almacena los índices en tablas separadas, "ocultas".

La implementación SASI existe junto con los índices secundarios tradicionales, y puede crear un índice SASI con el comando CQL CREATE CUSTOM INDEX:

CREATE CUSTOM INDEX user_last_name_sasi_idx ON user (last_name)
USING 'org.apache.cassandra.index.sasi.SASIIndex';

Los índices SASI ofrecen funcionalidad más allá de la implementación de índice secundario tradicional, como la capacidad de realizar búsquedas de desigualdad (mayor o menor que) en columnas indexadas. También puede utilizar la nueva palabra clave "LIKE" para realizar búsquedas de texto en columnas indexadas. Por ejemplo, podría usar la siguiente consulta para encontrar usuarios cuyo apellido comience con "N":

SELECT * FROM user WHERE last_name LIKE 'N%';

Si bien los índices SASI se desempeñan mejor que los índices tradicionales al eliminar la necesidad de leer de tablas adicionales, aún requieren lecturas de un mayor número de nodos que un diseño desnormalizado.

jueves, 18 de julio de 2019

Indices secundarios en Cassandra


Si intentamos filtrar una tabla por una columna que no es parte de la clave primaria, no tendremos éxito, veamos un ejemplo :

cqlsh:my_keyspace> SELECT * FROM user WHERE last_name = 'Goette';

InvalidRequest: code=2200 [Invalid query] message="No supported
secondary index found for the non primary key columns restrictions"

El mensaje de error es claro, nosotros necesitamos crear un indice secundario, para la columna last_name. Los indices secundarios no son parte de la clave primaria y nos permiten filtrar por estos campos.

cqlsh:my_keyspace> CREATE INDEX ON user ( last_name );

Nosotros podemos darle un nombre al indice con la sintaxis :

CREATE INDEX <name> ON... ;

Si no especificamos el nombre, automáticamente utiliza el nombre :
 <table name>_<column name>_idx

Ahora vamos a hacer el mismo select :

cqlsh:my_keyspace> SELECT * FROM user WHERE last_name = 'Nguyen';

first_name | last_name
 ------------+-----------
Bill            | Nguyen

(1 rows)

Se pueden crear indices para tipos simples y colecciones, los mapas se pueden indexar por clave, por valor o por ambos.

Por último podemos remover un indice con drop index, por ejemplo :

cqlsh:my_keyspace> DROP INDEX user_last_name_idx;

Los indices secundarios no son recomendados para los siguientes casos:

  • Columnas muy grandes
  • Columnas con valores poco diferentes como por ejemplo titulo, los valores serán (señor, señorita, …) 
  • Columnas que son actualizadas con mucha frecuencia. 



martes, 16 de julio de 2019

Definir nuestros propios datos en Cassandra

Muchas veces debemos guardar datos compuestos, como direcciones, identificación, telefono, etc. Una forma es guardarlo todo en una columna de texto, pero luego vamos a tener que parcear, los resultados. Sería mejor si pudiéramos definir una estructura en la que almacenar por ejemplo las direcciones para mantener la integridad de los diferentes componentes.

Afortunadamente, Cassandra nos da una manera de definir nuestros propios tipos. Luego podemos crear columnas de estos tipos definidos por el usuario. Vamos a crear nuestro propio tipo de dirección, insertando algunos saltos de línea en nuestro comando para facilitar la lectura:

qlsh:my_keyspace> CREATE TYPE address (
... street text,
... city text,
... state text,
... zip_code int);

Podríamos haber escrito CREATE TYPE my_keyspace.address. Si ejecuta el comando DESCRIBE KEYSPACE my_keyspace, verá que el tipo de dirección es parte de la definición del espacio de claves.

Ahora que hemos definido nuestro tipo de dirección, intentaremos usarlo en nuestra tabla de usuarios, pero inmediatamente nos encontramos con un problema:

cqlsh:my_keyspace> ALTER TABLE user ADD addresses map<text, address>;

InvalidRequest: code=2200 [Invalid query] message="Non-frozen
collections are not allowed inside collections: map<text,
address>"

¿Que esta pasando aqui? Resulta que un tipo de datos definido por el usuario se considera una colección, ya que su implementación es similar a un conjunto, lista o mapa.

Las versiones de Cassandra anteriores a 2.2 no son totalmente compatibles con el anidamiento de colecciones. Específicamente, la capacidad de acceder a los atributos individuales de una colección anidada aún no se admite, ya que la colección anidada se serializa como un solo objeto por la implementación.

La congelación es un concepto que la comunidad Cassandra ha introducido como un mecanismo de compatibilidad hacia adelante. Por ahora, puede anidar una colección dentro de otra colección marcándola como congelada.

En el futuro, cuando las colecciones anidadas sean totalmente compatibles, habrá un mecanismo para "descongelar" las colecciones anidadas, permitiendo el acceso a los atributos individuales.
También puede usar una colección como clave principal si está congelada.

Ahora que hemos tomado un breve desvío para hablar sobre la congelación y las tablas anidadas, volvamos a modificar nuestra tabla, esta vez marcando la dirección como congelada:

cqlsh:my_keyspace> ALTER TABLE user ADD addresses map<text, frozen<address>>;

Ahora agreguemos una dirección de casa para Mary:

cqlsh:my_keyspace> UPDATE user SET addresses = addresses + {'home': { street: '7712 E. Broadway', city: 'Tucson', state: 'AZ', zip_code: 85715} } WHERE first_name = 'Mary';


Collections en Apache Cassandra


Como casandra no permite joins es muy dificil mantener relaciones como lo hariamos en una base SQL normal, por ejemplo si queremos mantener datos de un usuario y sus emails, una forma de hacerlo sería crear columnas adicionales, como email2, email3, etc.

Si bien este es un enfoque que funcionará, no escala muy bien y puede causar muchos cambios. Es mucho más simple tratar con las direcciones de correo electrónico como grupo o "colección". Cassandra hereda los tipos de Java por lo tanto tenemos Listas, conjuntos y mapas.  Echemos un vistazo a cada uno de ellos:

set : El tipo de datos de conjunto almacena una colección de elementos. Los elementos no están ordenados, pero cqlsh devuelve los elementos en orden ordenado. Por ejemplo, los valores de texto se devuelven en orden alfabético. Los conjuntos pueden contener los tipos simples que revisamos en el post anterior, así como los tipos definidos por el usuario e incluso otras colecciones. Una de las ventajas de usar set es la capacidad de insertar elementos adicionales sin tener que leer el contenido primero.

Veamos un ejemplo de agregar un set de emails a la tabla usuario :

cqlsh:my_keyspace> ALTER TABLE user ADD emails set<text>;

Luego agregaremos una dirección de correo electrónico para Mary y verificaremos que se haya agregado con éxito:

cqlsh:my_keyspace> UPDATE user SET emails = {'mary@example.com' } WHERE first_name = 'Mary';

cqlsh:my_keyspace> SELECT emails FROM user WHERE first_name ='Mary';

emails
----------------------
{'mary@example.com'}

(1 rows)

Tenga en cuenta que al agregar esa primera dirección de correo electrónico, reemplazamos el contenido anterior del conjunto, que en este caso era nulo. Podemos agregar otra dirección de correo electrónico más tarde sin reemplazar todo el conjunto mediante concatenación:

cqlsh:my_keyspace> UPDATE user SET emails = emails + { 'mary.mcdonald.AZ@gmail.com' } WHERE first_name = 'Mary';

cqlsh:my_keyspace> SELECT emails FROM user WHERE first_name = 'Mary';

emails
---------------------------------------------------
{'mary.mcdonald.AZ@gmail.com', 'mary@example.com'}

(1 rows)

list : El tipo de datos de lista contiene una lista ordenada de elementos. Por defecto, los valores se almacenan en orden de inserción (es decir por un indice). Modifiquemos nuestra tabla de usuarios para agregar una lista de números de teléfono:

cqlsh:my_keyspace> ALTER TABLE user ADD phone_numbers list<text>;

Luego agregaremos un número de teléfono para Mary y verificaremos que se haya agregado correctamente:

cqlsh:my_keyspace> UPDATE user SET phone_numbers = ['1-800-999-9999' ] WHERE first_name = 'Mary';

cqlsh:my_keyspace> SELECT phone_numbers FROM user WHEREfirst_name = 'Mary';

phone_numbers
--------------------
['1-800-999-9999']

(1 rows)

Agreguemos un segundo número añadiéndolo:

cqlsh:my_keyspace> UPDATE user SET phone_numbers = phone_numbers + [ '480-111-1111' ] WHERE first_name = 'Mary';

cqlsh:my_keyspace> SELECT phone_numbers FROM user WHERE first_name = 'Mary';

phone_numbers
------------------------------------
['1-800-999-9999', '480-111-1111']

(1 rows)

El segundo número que agregamos ahora aparece al final de la lista.

Podemos reemplazar un elemento individual en la lista cuando lo referenciamos por su índice:

cqlsh:my_keyspace> UPDATE user SET phone_numbers[1] = '480-111-1111' WHERE first_name = 'Mary';

Al igual que con los conjuntos, también podemos usar el operador de resta para eliminar elementos que coincidan con un valor específico:

cqlsh:my_keyspace> UPDATE user SET phone_numbers =phone_numbers - [ '480-111-1111' ] WHERE first_name = 'Mary';

Finalmente, podemos eliminar un elemento específico directamente usando su índice:

cqlsh:my_keyspace> DELETE phone_numbers[0] from user WHERE first_name = 'Mary';

map : El tipo de datos mapa contiene una colección de pares clave/valor. Las claves y los valores pueden ser de cualquier tipo excepto contador. Probemos esto utilizando un mapa para almacenar información sobre los inicios de sesión de los usuarios. Crearemos una columna para rastrear el tiempo de inicio de sesión en segundos, con un timeuuid como clave:

cqlsh:my_keyspace> ALTER TABLE user ADD login_sessions map<timeuuid, int>;

Luego agregaremos un par de sesiones de inicio de sesión para Mary y veremos los resultados:

cqlsh:my_keyspace> UPDATE user SET login_sessions = { now(): 13, now(): 18} WHERE first_name = 'Mary';

cqlsh:my_keyspace> SELECT login_sessions FROM user WHERE first_name = 'Mary';

login_sessions
-----------------------------------------------
{6061b850-14f8-11e5-899a-a9fac1d00bce: 13,
6061b851-14f8-11e5-899a-a9fac1d00bce: 18}

(1 rows)

También podemos hacer referencia a un elemento individual en el mapa usando su clave.

Los tipos de colección son muy útiles en los casos en que necesitamos almacenar un número variable de elementos dentro de una sola columna.


domingo, 23 de junio de 2019

Tipos en Cassandra


Veamos los distintos tipos que tenemos disponibles para nuestros valores. Como hemos visto en nuestra exploración hasta ahora, cada columna de nuestra tabla es de un tipo específico.

CQL admite un conjunto flexible de tipos de datos, incluidos tipos de caracteres y numéricos simples, colecciones y tipos definidos por el usuario. Describiremos estos tipos de datos y proporcionaremos algunos ejemplos de cómo podrían usarse para aprender a tomar la decisión correcta para los diferentes modelos de datos.

int: 32-bit entero con signo como java.
bigint: 64-bit entero grande con signo equivalente a long de Java
smallint: 16-bit entero con signo equivalente a short de Java
tinyint: 8-bit entero con signo
varint: A variable precision signed integer (equivalent to java.math.BigInteger )
float: 32-bit IEEE-754 equivalente a float de java
double: 64-bit IEEE-754 equivalente a double de Java
decimal: equivalente a java.math.BigDecimal

Si bien los tipos enumerados son comunes en muchos lenguajes, no hay un equivalente directo en CQL. Una práctica común es almacenar valores enumerados como cadenas. Por ejemplo, usando el método Enum.name() para convertir un valor enumerado en una Cadena para escribir en Cassandra como texto, y el método Enum.valueOf() para volver a convertir el texto al valor enumerado.

CQL proporciona dos tipos de datos para representar texto, uno de los cuales ya hemos utilizado bastante :

text , varchar : cadena de caracteres UTF-8
ascii : una cadena de ascii

UTF-8 es el estándar de texto más reciente y más utilizado y es compatible con la internacionalización, por lo que recomendamos utilizar texto sobre ascii al crear tablas para nuevos datos. El tipo de ascii es más útil si está tratando con datos heredados que están en formato ASCII.

Cassandra nos provee tipos para representar el tiempo :

timestamp : Si bien señalamos anteriormente que cada columna tiene una marca de tiempo que indica cuándo se modificó por última vez, también puede usar una marca de tiempo como el valor de una columna en sí. El tiempo se puede codificar como un entero con signo de 64 bits, pero normalmente es mucho más útil ingresar una marca de tiempo utilizando uno de los varios formatos de fecha ISO 8601 compatibles.

date, time : hasta Cassandra 2.1 solo tenían el tipo timestamp para representar los tiempos, que incluía tanto una fecha como una hora del día. La versión 2.2 introdujo los tipos de fecha y hora que permitieron que estos se representaran de forma independiente; es decir, una fecha sin una hora y una hora del día sin referencia a una fecha específica. Al igual que con ltimestamp, estos tipos admiten formatos ISO 8601.
Aunque hay nuevos tipos de java.time disponibles en Java 8, el tipo de fecha se asigna a un tipo personalizado en Cassandra para preservar la compatibilidad con JDK más antiguos. El tipo de tiempo se asigna a una Java long que representa el número de nanosegundos desde la medianoche.

Veamos el tipo de datos para las claves:

uuid : El identificador único universal (UUID) de RA es un valor de 128 bits en el que los bits se ajustan a uno de varios tipos, de los cuales los más utilizados comúnmente se conocen como Tipo 1 y Tipo 4. El tipo de uuid CQL es un UUID de Tipo 4, que se basa enteramente en números aleatorios. Los UUID se representan normalmente como secuencias separadas por guiones de dígitos hexadecimales. El tipo uuid se usa a menudo como una clave sustituta, ya sea por sí misma o en combinación con otros valores. Debido a que los UUID son de una longitud finita, no están absolutamente garantizados para ser únicos. Sin embargo, la mayoría de los sistemas operativos y lenguajes de programación proporcionan utilidades para generar ID que proporcionan una singularidad adecuada, y cqlsh también lo hace. Puede obtener un valor UUID de Tipo 4 a través de la función uuid () y usar este valor en INSERT o UPDATE.

timeuuid : Este es un UUID de Tipo 1, que se basa en la dirección MAC de la computadora, la hora del sistema y un número de secuencia utilizado para evitar duplicados. Este tipo se usa frecuentemente como una marca de tiempo libre de conflictos. cqlsh proporciona varias funciones convenientes para interactuar con el tipo de timeuuid: now (), dateOf () y unixTimestampOf (). La disponibilidad de estas funciones de conveniencia es una de las razones por las que timeuuid tiende a usarse con más frecuencia que uuid.

Para terminar veamos otros tipos que no se donde agruparlos :

boolean : Este es un simple valor verdadero / falso. El cqlsh no distingue entre mayúsculas y minúsculas en la aceptación de estos valores, pero da como resultado True o False.

blob : Un objeto grande binario (blob) es un término informático coloquial para una matriz arbitraria de bytes. El tipo de blob CQL es útil para almacenar medios u otros tipos de archivos binarios. Cassandra no valida ni examina los bytes en un blob. CQL representa los datos como dígitos hexadecimales, por ejemplo, 0x00000ab83cf0. Si desea codificar datos textuales arbitrarios en el blob, puede usar la función textAsBlob() para especificar valores para la entrada.

inet : Este tipo representa las direcciones de Internet IPv4 o IPv6. cqlsh acepta cualquier formato legal para definir direcciones IPv4, incluidas representaciones con puntos o sin puntos que contengan valores decimales, octales o hexadecimales. Sin embargo, los valores se representan utilizando el formato decimal punteado en la salida cqlsh, por ejemplo, 192.0.2.235.
Las direcciones IPv6 se representan como ocho grupos de cuatro dígitos hexadecimales, separados por dos puntos, por ejemplo, 2001: 0db8: 85a3: 0000: 0000: 8a2e: 0370: 7334. La especificación de IPv6 permite el colapso de valores hexadecimales cero consecutivos, por lo que el valor anterior se representa de la siguiente manera cuando se lee con SELECT: 2001: db8: 85a3: a :: 8a2e: 370: 7334.

counter : El tipo de datos de contador proporciona un entero con signo de 64 bits, cuyo valor no se puede establecer directamente, sino que solo se puede incrementar o disminuir. Los contadores se utilizan con frecuencia para el seguimiento de estadísticas, como el número de páginas vistas, tweets, mensajes de registro, etc. El tipo de contador tiene algunas restricciones especiales. No se puede utilizar como parte de una clave principal. Si se usa un contador, todas las columnas que no sean columnas de clave primaria deben ser contadores.

En proximos post hablaremos de tipos de datos compuestos como las colecciones y en la capacidad de crear nuestros propios tipos de datos.


domingo, 16 de junio de 2019

Tiempo de vida en las columnas en Apache Cassandra


Una característica muy poderosa que tiene apache Cassandra es la capacidad de expirar datos que no necesita por mucho tiempo. Esta característica es muy flexible y trabaja a nivel individual de cada valor de una columna. El tiempo de vida (TTL) es el tiempo que Cassandra persiste un campo y se indica a nivel de columna.

El TTL por defecto es null y esto significa que el dato escrito no espira. Con la funcion TTL() podemos ver el tiempo de vida de un campo determinado :

cqlsh:my_keyspace> SELECT first_name, last_name, TTL(last_name) FROM user WHERE first_name = 'Mary';

first_name | last_name | ttl(last_name)
-------------+-------------+----------------
Mary          | Boateng   | null

(1 rows)

Ahora vamos a modificar esto:

cqlsh:my_keyspace> UPDATE user USING TTL 3600 SET last_name ='McDonald' WHERE first_name = 'Mary' ;

cqlsh:my_keyspace> SELECT first_name, last_name, TTL(last_name) FROM user WHERE first_name = 'Mary';

first_name | last_name | ttl(last_name)
-------------+-------------+---------------
Mary         | McDonald |  3588

(1 rows)

En este caso modificamos el TTL con update pero también podemos utilizar insert con el comando USING TTL.

El TTL es por columnas, no tenemos un mecanismo para settear el TTL a nivel de fila directamente.  Y esto es setteado cuando proveemos un valor a una columna. Si queremos settear el TTL a nivel de fila, debemos proveer un valor para la primary key en el update o insert.

domingo, 9 de junio de 2019

Columnas en Apache Cassandra


Una columna es la unidad más básica de la estructura de datos en el modelo de datos de Cassandra. Hasta ahora hemos visto que una columna contiene un nombre y un valor. Restringimos cada uno de los valores para que sean de un tipo particular cuando definimos la columna. Vamos profundizar en los diversos tipos que están disponibles para cada columna, pero primero echemos un vistazo a algunos otros atributos de una columna que aún no hemos discutido: marcas de tiempo y tiempo de vida. Estos atributos son clave para entender cómo Cassandra usa el tiempo para mantener los datos actualizados.

Marcas de tiempo: Cada vez que escribe datos en Cassandra, se genera una marca de tiempo para cada valor de columna que se actualiza. Internamente, Cassandra usa estas marcas de tiempo para resolver cualquier cambio conflictivo que se realice en el mismo valor. Generalmente, la última marca de tiempo gana.

Veamos las marcas de tiempo que se generaron para nuestras escrituras anteriores agregando la función writetime() a nuestro comando SELECT. Haremos esto en la columna de apellido e incluiremos un par de otros valores para el contexto:

cqlsh:my_keyspace> SELECT first_name, last_name, writetime(last_name) FROM user;

  first_name | last_name | writetime(last_name)
   ------------+-------------+----------------------
          Mary | Rodriguez | 1434591198790252
             Bill | Nguyen     | 1434591198798235
(2 rows)

Podríamos esperar que si solicitamos la marca de tiempo en first_name obtendríamos un resultado similar. Sin embargo, resulta que Cassandra no nos permite solicitar la marca de tiempo en las columnas de clave principal:

cqlsh:my_keyspace> SELECT WRITETIME(first_name) FROM user;
InvalidRequest: code=2200 [Invalid query] message="Cannot use selection function writeTime on PRIMARY KEY part first_name"

Cassandra también nos permite especificar una marca de tiempo cuando modificamos. Usaremos la opción USING TIMESTAMP para establecer manualmente una marca de tiempo (tenga en cuenta que la marca de tiempo debe ser posterior a la de nuestro comando SELECT, o se ignorará la ACTUALIZACIÓN):

cqlsh:my_keyspace> UPDATE user USING TIMESTAMP 1434373756626000 SET last_name = 'Boateng' WHERE first_name = 'Mary' ;

cqlsh:my_keyspace> SELECT first_name, last_name, WRITETIME(last_name) FROM user WHERE first_name = 'Mary';

first_name | last_name | writetime(last_name)
------------+-------------+---------------------
       Mary | Boateng     | 1434373756626000

(1 rows)

Esta declaración tiene el efecto de agregar la columna de apellido a la fila identificada por la clave principal "Mary", y establecer la marca de tiempo al valor que proporcionamos.


jueves, 6 de junio de 2019

Tablas en Cassandra



Una tabla es un contenedor para una colección ordenada de filas, cada una de las cuales es una colección ordenada de columnas. El orden está determinado por las columnas, que se identifican como claves. Pronto veremos cómo Cassandra usa claves adicionales más allá de la clave principal.

Cuando escribe datos en una tabla en Cassandra, especifica valores para una o más columnas. Esa colección de valores se llama una fila. Al menos uno de los valores que especifique debe ser una clave principal que sirva como identificador único para esa fila.

Leemos usando el comando SELECT en cqlsh:

cqlsh:my_keyspace> SELECT * FROM user WHERE first_name='Bill';

first_name | last_name
 ------------+-----------
           Bill | Nguyen
(1 rows)

Notarás en la última fila que el shell nos dice que se devolvió una fila. Resulta ser la fila identificada por el primer nombre "Bill". Esta es la clave principal que identifica esta fila.

No necesitamos incluir un valor para cada columna cuando agregamos una nueva fila a la tabla. Probemos esto con nuestra tabla de usuarios usando el comando ALTER TABLE y luego veamos los resultados usando el comando DESCRIBE TABLE:

cqlsh:my_keyspace> ALTER TABLE user ADD title text;
cqlsh:my_keyspace> DESCRIBE TABLE user;

CREATE TABLE my_keyspace.user (
     first_name text PRIMARY KEY,
     last_name text,
     title text
) ...

Vemos que se ha añadido la columna de título. Tenga en cuenta que hemos acortado la salida para omitir las diversas configuraciones de la tabla.

Ahora, escribamos un par de filas, llenemos diferentes columnas para cada una y veamos los resultados:

cqlsh:my_keyspace> INSERT INTO user (first_name, last_name, title)
VALUES ('Bill', 'Nguyen', 'Mr.');

cqlsh:my_keyspace> INSERT INTO user (first_name, last_name) VALUES
('Mary', 'Rodriguez');

cqlsh:my_keyspace> SELECT * FROM user;

       first_name | last_name | title
         ------------+-----------+-------
               Mary | Rodriguez | null
                  Bill |     Nguyen | Mr.
(2 rows)

Ahora que hemos aprendido más sobre la estructura de una tabla y hemos realizado algunos modelos de datos, profundicemos en las columnas.

domingo, 2 de junio de 2019

Clusters y Keyspaces en Cassandra

Clusters: la base de datos Cassandra está diseñada específicamente para ser distribuida en varias máquinas que operan juntas y que aparecen como una sola instancia para el usuario final. Así que la estructura más externa en Cassandra son los clusters, a veces llamado el anillo, porque Cassandra asigna datos a los nodos en el grupo organizándolos en un anillo.

Keyspaces: Un clúster es un contenedor para keyspaces. Un keyspace es un contenedor más externo para datos en Cassandra, que se corresponde estrechamente con una base de datos relacional. De la misma manera que una base de datos es un contenedor para tablas en el modelo relacional, un keyspace es un contenedor para tablas en el modelo de datos de Cassandra. Al igual que una base de datos relacional, un keyspace tiene un nombre y un conjunto de atributos que definen el comportamiento de todo el keyspace.


Modelo de datos en Cassandra

El almacén de datos más simple con el que querrías trabajar podría ser una matriz o una lista. Se vería como la siguiente figura:



Si se persiste en esta lista, podría consultarla más adelante, pero tendría que examinar cada valor para saber qué representaba, o almacenar siempre cada valor en el mismo lugar de la lista y luego mantener externamente la documentación sobre qué  se encuentra en que celda. Eso significa que podría tener que proporcionar valores de marcador de posición vacíos (nulos) para mantener el tamaño predeterminado de la matriz en caso de que no tuviera un valor para un atributo opcional (como un número de fax o un número de apartamento). Una matriz es una estructura de datos claramente útil, pero no semánticamente rica.

Así que nos gustaría agregar una segunda dimensión a esta lista: nombres para que coincidan con los valores. Daremos nombres a cada celda, y ahora tenemos una estructura de mapa, como se muestra en la siguiente figura:



Esto es una mejora porque podemos saber los nombres de nuestros valores. Entonces, si decidimos que nuestro mapa contendría la información del usuario, podríamos tener nombres de columna como primer nombre, último nombre, teléfono, correo electrónico, etc. Esta es una estructura algo más rica para trabajar.

Pero la estructura que hemos construido hasta ahora solo funciona si tenemos una instancia de una entidad determinada, como una sola persona, usuario, hotel o tweet. No nos da mucho si queremos almacenar varias entidades con la misma estructura, que es ciertamente lo que queremos hacer. No hay nada para unificar una colección de pares de nombre / valor, y no hay manera de repetir los mismos nombres de columna. Así que necesitamos algo que agrupará algunos de los valores de columna en un grupo claramente direccionable. Necesitamos una clave para hacer referencia a un grupo de columnas que deben tratarse juntas como un conjunto. Necesitamos filas. Luego, si obtenemos una sola fila, podemos obtener todos los pares de nombre / valor para una sola entidad a la vez, o simplemente obtener los valores de los nombres que nos interesan. Podríamos llamar a estas columnas de pares de nombre / valor. Podríamos llamar a cada entidad separada que contiene un conjunto de filas de columnas.

Y el identificador único para cada fila podría llamarse clave de fila o clave principal.
La siguinte figura muestra el contenido de una fila simple: una clave principal, que es en sí misma una o más columnas, y columnas adicionales.


Cassandra define una tabla como una división lógica que asocia datos similares. Por ejemplo, podríamos tener una tabla de usuario, una tabla de hotel, una tabla de libreta de direcciones, etc. De esta manera, una tabla de Cassandra es análoga a una tabla en el mundo relacional.

Ahora no necesitamos almacenar un valor para cada columna cada vez que almacenamos una nueva entidad. Quizás no sepamos los valores de cada columna para una entidad dada. Por ejemplo, algunas personas tienen un segundo número de teléfono y otras no, y en lugar de almacenar el valor nulo para aquellos valores que no conocemos, lo que desperdiciaría espacio, simplemente no almacenaremos esa columna para esa fila. Así que ahora tenemos una estructura de matriz multidimensional dispersa que se parece a la siñguiente figura :


Al diseñar una tabla en una base de datos relacional tradicional, normalmente se trata de "entidades" o del conjunto de atributos que describen un nombre particular (hotel, usuario, producto, etc.). No se piensa mucho en el tamaño de las filas en sí, porque el tamaño de la fila no es negociable una vez que haya decidido qué sustantivo representa su tabla. Sin embargo, cuando trabajas con Cassandra, realmente tienes que tomar una decisión sobre el tamaño de tus filas: pueden ser anchas o delgadas, dependiendo del número de columnas que contenga la fila.

Una fila ancha significa una fila que tiene muchos y muchos (quizás decenas de miles o incluso millones) de columnas. Normalmente, hay un número menor de filas que van junto con tantas columnas. A la inversa, podría tener algo más cercano a un modelo relacional, donde define un número menor de columnas y usa muchas filas diferentes, es decir, el modelo delgado.

En Cassandra, tenemos estas estructuras de datos básicas :
  • La columna, que es un par de nombre / valor
  • La fila, que es un contenedor para columnas referenciadas por una clave primaria
  • La tabla, que es un contenedor para filas.
  • El keyspace, que es un contenedor para tablas.
  • El clúster, que es un contenedor para espacios de claves que abarca uno o más nodos
Así que ese es el enfoque de abajo hacia arriba para mirar el modelo de datos de Cassandra. Ahora que conocemos la terminología básica, examinemos cada estructura con más detalle en proximos posts.

domingo, 26 de mayo de 2019

Que son los System Keyspaces en Cassandra?

Cassandra tiene su propio almacenamiento para realizar un seguimiento de los metadatos sobre el clúster y el nodo local. Esto es similar a la forma en que Microsoft SQL Server mantiene las metabases de datos master y tempdb. El master se usa para mantener información sobre el espacio en disco, el uso de este, la configuración del sistema y las notas generales de instalación del servidor; el tempdb se utiliza como un espacio de trabajo para almacenar resultados intermedios y realizar tareas generales. La base de datos Oracle siempre tiene un tablespace llamado SYSTEM, usado para propósitos similares. Los System Keyspaces de Cassandra se utilizan de forma muy similar a estos.

Si vamos a cqlsh y echamos un vistazo rápido a las tablas System Keyspaces en Cassandra, si hacemos :

cqlsh> DESCRIBE TABLES;

Al observar estas tablas, vemos que muchas de ellas están relacionadas con los conceptos que se analizado en post anteriores :

  • La información sobre la estructura del clúster comunicada a través de gossip se almacena en system.local y system.peers. Estas tablas contienen información sobre el nodo local y otros nodos en el clúster, incluidas direcciones IP, ubicaciones por centro de datos y rack, CQL y versiones de protocolo.
  • system.range_xfers y system.available_ranges rastrean los rangos de token administrados por cada nodo y cualquier rango que necesite asignación.
  • Los system_schema.keyspaces, system_schema.tables y system_schema.columns almacenan las definiciones de los espacios de claves, tablas e índices definidos para el clúster.
  • La construcción de vistas materializadas se rastrea en las tablas system.materialized_views_builds_in_progress y system.built_materialized_views, lo que da como resultado las vistas disponibles en system_schema.materialized_views.
  • Extensiones proporcionadas por el usuario, como system_schema.types para tipos definidos por el usuario, system_schema.triggers para activadores configurados por tabla, system_schema. funciones para funciones definidas por el usuario, y system_schema.aggregates para agregados definidos por el usuario.
  • La tabla system.paxos almacena el estado de las transacciones en curso, mientras que la tabla system.batchlog almacena el estado de los lotes atómicos.


Volvamos a cqlsh para echar un vistazo rápido a los atributos System Keyspaces de Cassandra:

cqlsh> USE system;
cqlsh:system> DESCRIBE KEYSPACE;
CREATE KEYSPACE system WITH replication = {'class': 'LocalStrategy'} AND durable_writes = true;
...

Al observar la primera declaración en la salida, vemos que el espacio System Keyspaces está usando la estrategia de replicación LocalStrategy, lo que significa que esta información está destinada para uso interno y no se replica en otros nodos.

Clases que componen Apache Cassandra Parte 2


Y llego la continuación del post "Clases que componen Apache Cassandra" 

El Protocolo nativo CQL es el protocolo binario utilizado por los clientes para comunicarse con Cassandra. El paquete org.apache.cassandra.transport contiene las clases que implementan este protocolo, incluido el Servidor. Este servidor de transporte nativo administra las conexiones de clientes y enruta las solicitudes entrantes, delegando el trabajo de realizar consultas al StorageProxy.
Hay varias otras clases que manejan las características clave de Cassandra. Aquí hay algunos para investigar si estás interesado:















Clases que componen Apache Cassandra


Hay un conjunto de clases que forman los mecanismos básicos de control interno de Cassandra. Ya nos hemos encontrado con algunos de ellos en post anteriores, incluidos Hinted HandOffManager, CompactionManager y StageManager. Aquí presentamos una breve descripción de algunas otras clases para que pueda familiarizarse con algunas de las más importantes. Muchos de ellos exponen los MBeans a través de Java Management Extension (JMX) para informar el estado y las métricas y, en algunos casos, permitir la configuración y el control de sus actividades.

La interfaz org.apache.cassandra.service.CassandraDaemon representa el ciclo de vida del servicio Cassandra ejecutándose en un solo nodo. Incluye las operaciones típicas de ciclo de vida que se podrían esperar: iniciar, detener, activar, desactivar y destruir.

También puede crear una instancia de Cassandra en memoria mediante programación utilizando la clase org.apache.cassandra.service.EmbeddedCassandraService. Crear una instancia embebida puede ser útil para los programas de prueba unitaria que usan Cassandra.

La funcionalidad de almacenamiento de datos principal de Cassandra se conoce comúnmente como el motor de almacenamiento, que consiste principalmente en clases en el paquete org.apache.cassandra.db. El punto de entrada principal es la clase ColumnFamilyStore, que administra todos los aspectos del almacenamiento de tablas, incluidos los registros de confirmación, memtables, SSTables e índices.

Cassandra encasula el motor de almacenamiento en servicio representado por la
clase org.apache.cassandra.service.StorageService. El servicio de almacenamiento contiene el token del nodo, que es un marcador que indica el rango de datos de los que es responsable el nodo.
El servidor se inicia con una llamada al método initServer de esta clase, en el que el servidor registra los controladores SEDA, realiza algunas determinaciones sobre su estado (por ejemplo, si fue un programa de arranque o no, y cuál es su particionador), y registra un MBean con el servidor JMX.

El propósito de org.apache.cassandra.net.MessagingService es crear listeners de socket para el intercambio de mensajes; los mensajes entrantes y salientes de este nodo llegan a través de este servicio. El método MessagingService.listen crea un hilo. Cada conexión entrante luego se sumerge en el grupo de subprocesos ExecutorService usando org.apache.cassandra.net.IncomingTcpConnection (una clase que extiende Thread) para deserializar el mensaje. El mensaje se valida y luego se enruta al controlador apropiado.

Debido a que MessagingService también hace un uso intensivo de las etapas y el grupo que mantiene está envuelto con un MBean, puede descubrir mucho sobre cómo está funcionando este servicio (si las lecturas se están respaldando y demás) a través de JMX.

La transmisión por secuencias es la forma optimizada de Cassandra de enviar secciones de archivos SSTable de un nodo a otro a través de una conexión TCP persistente; todas las demás comunicaciones entre nodos se producen a través de mensajes serializados. org.apache.cassandra.streaming.StreamManager maneja estos mensajes de transmisión, incluida la administración de la conexión, la compresión de mensajes, el seguimiento de progreso y las estadísticas.

Nos quedan unas cuantas clases que seguiremos viendo en una parte 2.



domingo, 19 de mayo de 2019

Arquitectura dirigida por eventos (SEDA) en Apache Cassandra


El diseño de Cassandra fue influenciado por Staged Event-Driven Architecture (SEDA). SEDA es una arquitectura general para servicios de Internet altamente concurrentes, propuesta originalmente en un documento de 2001 llamado "SEDA: An Architecture for Well-Conditioned, Scalable
Internet Services" de Matt Welsh, David Culler y Eric Brewer. Puede leer el documento original de SEDA en http://www.eecs.harvard.edu/~mdw/proj/seda.

En una aplicación típica, una sola unidad de trabajo se realiza a menudo dentro de los límites de un solo hilo. Una operación de escritura, por ejemplo, comenzará y terminará dentro del mismo hilo. Cassandra, sin embargo, es diferente: su modelo de concurrencia se basa en SEDA, por lo que una sola operación puede comenzar con un hilo, que luego pasa el trabajo a otro hilo, que puede pasarlo a otros hilos. Pero no corresponde al hilo actual entregar el trabajo a otro hilo. En su lugar, el trabajo se subdivide en lo que se denomina etapas, y el grupo de subprocesos (en realidad, un servicio java.util.concurrent.Executor) asociado con la etapa determina la ejecución.

Una etapa es una unidad básica de trabajo, y una sola operación puede realizar una transición interna de estado de una etapa a la siguiente. Debido a que cada etapa puede ser manejada por un grupo de subprocesos diferente, Cassandra experimenta una mejora masiva del rendimiento. Este diseño también significa que Cassandra puede administrar mejor sus propios recursos internamente porque diferentes operaciones pueden requerir Entrada y Salida de disco, o pueden estar vinculadas al CPU, o pueden ser operaciones de red, y así sucesivamente, para que los grupos puedan administrar su trabajo de acuerdo a la disponibilidad de estos recursos.

Una etapa consiste en una cola de eventos entrantes, un controlador de eventos y un grupo de subprocesos asociado. Las etapas son administradas por un controlador que determina la programación y la asignación de subprocesos; Cassandra implementa este tipo de modelo de concurrencia utilizando el grupo de subprocesos java.util.concurrent.ExecutorService. Para ver específicamente cómo funciona esto, echa un vistazo a la clase org.apache.cassandra.concurrent.StageManager. Las siguientes operaciones se representan como etapas en Cassandra, incluidos muchos de los conceptos que hemos analizado en post anteriores :


Algunas operaciones adicionales también se implementan como etapas, como las operaciones en memtables que incluyen el vaciado de datos a SSTables y la liberación de memoria. Las etapas implementan la interfaz IVerbHandler para admitir la funcionalidad de un verbo dado. Debido a que la idea de mutación se representa como una etapa, puede desempeñar un papel en las operaciones de inserción y eliminación.

Dejo link : https://en.wikipedia.org/wiki/Staged_event-driven_architecture