NoSQL Apache Cassandra

Post on 08-Nov-2014

372 views 0 download

Tags:

description

Breve introducción a Cassandra

Transcript of NoSQL Apache Cassandra

Bases de datos NoSQLParte II: Apache Cassandra

Roberto Amor Marcos

Bases de Datos Avanzadas

20 de abril de 2012

ContenidosObjetivos

¿Por qué Cassandra?

Visión general

Modelo de Datos

Arquitectura

Características

CQL

Conexión y acceso desde lenguajes de alto nivel

Aplicación de ejemplo sobre Cassandra

Objetivos

Conocer en profundidad Apache Cassandra.

Conocer y entender la terminología propia de Cassandra.

Conocer las distintas formas de acceder al contenido de la Base de Datos.

Conocer el lenguaje de consulta CQL.

Conocer cuáles son las formas de estructurar la información en Cassandra.

¿Por qué Cassandra?

Es un sistema fácil de entender pues es del tipo de Base de Datos NoSQL más cercano al modelo relacional.

Es de los pocos que ha superado la fase de versiones desarrollo 0.x y es actualizado, corregido y mejorado cada poco tiempo.

Última versión 1.0.9 del 6 de abril de 2012.

Dispone de un lenguaje de consultas muy similar a SQL: CQL (Cassandra Query Language).

Está escrito en Java.

La Fundación Apache está detrás de su desarrollo y mantenimiento.

¿Por qué Cassandra?

Es utilizado en aplicaciones comerciales muy importantes.

Twitter, Netflix, Digg, Cisco Webex, Spotify. Se usó en Facebook.

Su popularidad está en aumento y cada vez es más utilizado.

Existen distribuciones compiladas para todos los sistemas operativos, ofreciendo además, paneles de administración amigables.

Dispone de partners que dan soporte comercial de calidad.

Gran comunidad.

Visión general

Sistema key-value store que almacena column families.

Creado por Avanash Lakshaman y Prashany Malik para ser integrado en el motor de búsqueda de Facebook.

Concretamente para buscar mensajes en la bandeja de entrada.

Influido por Google BigTable (modelo de datos) y Amazon Dynamo (estructura).

Proceso de liberación:

Julio 2008: publicado como proyecto open source en Google Code.

Marzo 2009: pasa a formar parte de los proyectos Apache Incubator.

Febrero 2010: se convierte en proyecto top-level de la Apache Software Foundation.

pentaho_user
Resaltado
pentaho_user
Resaltado

Es actualmente el modelo de más éxito y el más utilizado. Actualmente sigue creciendo en número de usuarios.

En el momento de su presentación era capaz de ofrecer servicio concurrente a 100 millones de usuarios.

Especialmente diseñado para ejecutarse sobre grandes clusters, siendo muy sencilla su instalación multimáquina.

http://www.screenr.com/5G6 : how to set up a 4 node Cassandra cluster in under 2 minutes.

Visión general

pentaho_user
Resaltado

Conceptos básicos:

Cluster: las máquinas (nodos) de una instancia de Cassandra. Los clusters pueden contener múltiples keyspaces.

Keyspace: es la agrupación de ColumnFamilies. Normalmente hay un keyspace por aplicación.

ColumnFamilies: contenedor de múltiples columns. Es equivalente a la tabla en el modelo relacional. Cada entrada (row) se identifica y accede a ella mediante un row-KEY.

Column: unidad básica de almacenamiento. Consistente en una estructura de tres valores: name, value y timestamp.

SuperColumns: se consideran columns que almacenan subcolumnas. Son opcionales y no son muy utilizadas.

Modelo de Datos

De la columna al cluster

Columns

struct Column {1: binary name,2: binary value,3: i64 timestamp

}

Unidad básica de almacenamiento. Es una tripla.

{“name”: “Username”,“value”: “john23”,“timestamp”: 123456789

}

Modelo de Datos

De la columna al cluster

Columns

Los tres valores anteriores son proporcionados por el cliente de alto nivel, incluido el timestamp.

Por ello, es necesario tener sincronizado el reloj del sistema con el reloj del cluster.

El timestamp es utilizado para la resolución de conflictos (Eventual Consistency).

El timestamp puede ser cualquier cosa pero la convención marca que sea el valor en microsegundos desde 1970.

El tamaño máximo que puede albergar una columna es 2GB.

Modelo de Datos

De la columna al cluster

Rows

Agregacio!n de columnas con un nombre para referenciarlo (row-KEY).

El row sería el equivalente a la fila del modelo relacional y el row KEY el equivalente a la clave primaria del modelo relacional.

Es usado para ordenar los ficheros de forma física.

Se pueden almacenar hasta 2 mil millones de columnas en cada row.

Modelo de Datos

De la columna al cluster

Column Family

Agregacio!n rows.Cada ColumnFamily es guardado en un fichero separado y es ordenado por la KEY.

La forma de ordenar tanto de los rows como de las columnas se puede editar desde los ficheros de configuración.

ASCIIUTF-8LongUUID (léxico o de tiempo)FechaCombinaciones de ellos mediante el patrón CompositeType

Modelo de Datos

De la columna al cluster

Column Family

Modelo de Datos

De la columna al cluster

Keyspace

Es equiparable al schema del modelo relacional.

Cluster

Abarca desde el modelo físico al modelo lógico.

Incluso existe la posibilidad de interconectar clusters separados física y lógicamente.

Toda la información de un row debe encontrarse en una misma máquina o nodo del cluster.

Las IPs de los nodos se añaden en un fichero de configuración alojado en cada nodo. Todo lo demás es transparente para el usuario.

Modelo de Datos

El modelo estructural de un solo vistazo

Modelo de Datos

Cassandra reúne la tecnología de sistemas distribuidos de Dynamo y el modelo de datos de BigTable.

De Dynamo: Eventualmente Consistente. Sistema de nodos en anillo.

De BigTable: modelo de datos basado en Familias de Columnas.

Cassandra implementa la ‘parte AP’ del modelo CAP (i.e. Availability y Partitioning tolerance).

Arquitectura

Capas de la arquitectura de Cassandra:

Arquitectura

Core Layer Middle Layer Top Layer

Messaging serviceGossip Failure dectectionCluster statePartitionerReplication

Commit logMemtableSSTableIndexesCompaction

TombstonesHintedHandoffRead repairBootstrapMonitoringAdmin tools

Escritura

2 modos de escritura:

Quorum write: bloqueo hasta que la escritura tenga efecto.

Async write: se envía la petición a cualquier nodo. El nodo se encarga de hacer llegar los datos hasta el nodo apropiado.

Si un nodo está caído, otro nodo lo sustituirá hasta que el nodo original vuelva a estar disponible, escribiendo después en él. Por defecto cada 15 minutos se mueven datos entre nodos.

Arquitectura

Escritura

Camino de datos

Arquitectura

write DiskCommit

Log

nodes

memtables

t

when:out of space

too many keys

on disk: {dataFile (SSTable), indexFile (SSTable Index)}

Escritura

Propiedades de la escritura:

No hay lecturas.

No hay búsquedas.

Rápida.

Atómica respecto a las ColumnFamilies.

Siempre se puede escribir (disponibilidad de nodos).

Arquitectura

Lectura

Camino de datos:

1. Cualquier nodo puede responder (resolución de conflictos si fuera necesario con consistencia eventual).

2. El Partitioner actúa sobre cómo devolver los datos.

3. Espera de los datos desde memtable o desde SSTable.

Arquitectura

Lectura

Propiedades de la lectura:

Posibilidad de lecturas en paralelo de múltiples SSTable.

Mucho más lento que la escritura.

El retardo en las búsquedas se puede mitigar con más RAM.

Lecturas escalables hasta miles de millones de rows."

Arquitectura

Borrado

Se hace mediante una marca de borrado (tombstone) en el memtable.

Durante la fase de escritura del memtable al disco se descartan las entradas marcadas con el tombstone.

Arquitectura

VS MySQL con 50GB de datos

MySQL

~300ms write

~350ms read

Arquitectura

Cassandra

~0.12ms write

~15ms read

Búsquedas sobre +50TB de datos en cluster de 150 nodos.

Keyspace consistente en dos ColumnFamilies.

Query A: buscar mensajes por término de búsqueda.

Min: 7.78ms

Median: 18.27ms

Max: 44.41ms

Arquitectura

Búsquedas sobre +50TB de datos en cluster de 150 nodos.

Keyspace consistente en dos ColumnFamilies.

Query B: interacción de mensajería privada. Dado el nombre de un usuario, devolver todos los mensajes mantenidos con ese usuario.

Min: 7.69ms

Median: 15.69ms

Max: 26.13ms

Arquitectura

Tolerante a fallos:

Datos replicados automáticamente entre nodos.

Replicación a través de múltiples centros de datos.

Nodos automáticamente reemplazados.

Descentralizado: cada nodo es idéntico a los demás en estructura. No hay cuellos de botella.

Eventualmente consistente

Alta disponibilidad

Altamente escalable

Con soporte profesional

Probado

Características

Desde la versión 0.8, Cassandra proporciona un lenguaje de consulta y manipulación de los datos similar a SQL.

Actualmente (marzo 2012) se encuentra en su versión 2.0.

Se puede actuar con él tanto desde prompt como desde clientes de alto nivel.

CQL

SELECT * FROM MyColumnFamily;

UPDATE MyColumnFamily SET 'SomeColumn' = 'SomeValue' WHERE KEY = B70DE1D0-9908-4AE3-BE34-5573E5B09F14;

CQL

Tipo de dato Descripciónascii string de caracteres en US-ASCII

bigint long de 64-bits con signo

blob tipo LOB hexadecimal

boolean frue o false

counter contador distribuido de 64-bits

decimal número decimal de precisión variable

double número en punto flotante de 64-bits. sigue la norma IEEE-754

float número en punto flotante de 32-bits. sigue la norma IEEE-754

int entero con signo de 32-bits

text string en UTF-8

timestamp marca de tiempo de 8 bytes

uuid UUID del tipo 1 o tipo 4

varchar string en UTF-8

variant entero de precisión arbitraria

Tipos de datos en CQL

CQLEl tipo de dato UUID

Identificador Universalmente Único (Universally Unique Identifier).

Identificador estándar universal usado en computación distribuida.

Definido en el RFC-4122

Consiste en número hexadecimal de 16bytes (128-bits) dividido en grupos de la forma 8-4-4-4-12

550e8400-e29b-41d4-a716-446655440000

Hay 3 x 1038 identificadores posibles: 340,282,366,920,938,463,463,374,607,431,768,211,456

CQLEl tipo de dato UUID

Existen 5 tipos o versiones:

Version 1 MAC address

Version 2 DCE Security

Version 3 MD5 hash

Version 4 Random

Version 5 SHA-1 hash

CQLEl tipo de dato UUID

¿Probabilidad de repetición?

Con n = 2122 (122 random bits)

n probabilidad

68,719,476,736 = 236 0.0000000000000004 (4 × 10−16)

2,199,023,255,552 = 241 0.0000000000004 (4 × 10−13)

70,368,744,177,664 = 246 0.0000000004 (4 × 10−10)

CQLInstrucciones soportadas (en orden alfabético)ALTER COLUMNFAMILYBATCHCREATE COLUMNFAMILYCREATE INDEXCREATE KEYSPACEDELETEDROP COLUMNFAMILYDROP INDEXDROP KEYSPACEINSERTSELECTTRUNCATEUPDATEUSE

CQLALTER COLUMNFAMILY

ALTER COLUMNFAMILY <name> ALTER <column_name> TYPE <data_type> | ADD <column_name> <data_type> | DROP <column_name> ;

ALTER COLUMNFAMILY users ALTER email TYPE varchar;

ALTER COLUMNFAMILY users ADD gender varchar;

ALTER COLUMNFAMILY users DROP gender;

Manipular la metainformación de columna en una familia de columnas.

CQLBATCH

BEGIN BATCH

[ USING <write_option> [ AND <write_option> [...] ] ];

<dml_statement> <dml_statement> [...]

APPLY BATCH;

where <write_option> is:

USING CONSISTENCY <consistency_level> TTL <seconds> TIMESTAMP <integer>

Crea un bloque en el que las instrucciones contenidas en él se insertan el la BD con el mismo valor de timestamp.

CQLBATCH

Crea un bloque en el que las instrucciones contenidas en él se insertan el la BD con el mismo valor de timestamp.

BEGIN BATCH USING CONSISTENCY QUORUM AND TTL 8640000 INSERT INTO users (KEY, password, name) VALUES ('user2', 'ch@ngem3b', 'second user') UPDATE users SET password = 'ps22dhds' WHERE KEY = 'user2' INSERT INTO users (KEY, password) VALUES ('user3', 'ch@ngem3c') DELETE name FROM users WHERE key = 'user2' INSERT INTO users (KEY, password, name) VALUES ('user4', 'ch@ngem3c', 'Andrew')APPLY BATCH;

CQLCREATE COLUMNFAMILY

CREATE COLUMNFAMILY <cf_name> ( <key_column_name> <data_type> PRIMARY KEY [, <column_name> <data_type> [, ...] ] ) [ WITH <storage_parameter> = <value> [AND <storage_parameter> = <value> [...] ] ];

CREATE COLUMNFAMILY user_events (user text PRIMARY KEY) WITH comparator=timestamp AND default_validation=int;

CREATE COLUMNFAMILY users ( KEY uuid PRIMARY KEY, username text, email text ) WITH comment='user information' AND read_repair_chance = 1.0;

Crea una nueva Familia de Columnas

CQLCREATE INDEX

CREATE INDEX [<index_name>] ON <cf_name> (<column_name>);

CREATE COLUMNFAMILY users ( KEY uuid PRIMARY KEY, firstname text, lastname text, email text, address text, zip int, state text);

CREATE INDEX user_state ON users (state);

CREATE INDEX ON users (zip);

Crea un nuevo índice secundario

CQLCREATE KEYSPACE

CREATE KEYSPACE <ks_name> WITH strategy_class = <value> [ AND strategy_options:<option> = <value> [...] ];

CREATE KEYSPACE MyKeyspace WITH strategy_class = 'SimpleStrategy' AND strategy_options:replication_factor = 1;

Crea un nuevo Keyspace

CQLDELETE

DELETE [<column_name> [, ...]] FROM <column_family>[USING CONSISTENCY <consistency_level> [AND TIMESTAMP <integer>]]WHERE <row_specification>;

where <row_specification> is:

KEY | <key_alias> = <key_value> KEY | <key_alias> IN (<key_value> [,...])

DELETE email, phone FROM users USING CONSISTENCY QUORUM AND TIMESTAMP 1318452291034 WHERE user_name = 'jsmith';

DELETE FROM users WHERE KEY IN ('dhutchinson', 'jsmith');

Borra una o varias columnas de un row o rows

CQLDROP COLUMNFAMILY

DROP COLUMNFAMILY <name>;

DROP COLUMNFAMILY users;

Elimina una Familia de Columnas

CQLDROP INDEX

DROP INDEX <index_name>;

DROP INDEX users;DROP INDEX users_zip_idx;

Elimina un índice secundario

Si el índice se creó sin nombre, sigue el siguiente patrón:

<column_family_name><column_name>_idx

CQLDROP KEYSPACE

DROP KEYSPACE <name>;

DROP KEYSPACE demo;

Elimina un Keyspace

CQLINSERT

INSERT INTO <column_family> (<key_name>, <column_name> [, ...]) VALUES (<key_value>, <column_value> [, ...]) [USING <write_option> [AND <write_option> [...] ] ];

where <write_option> is:

USING CONSISTENCY <consistency_level> TTL <seconds> TIMESTAMP <integer>

INSERT INTO users (KEY, user_name) VALUES ('cfd66ccc-d857-4e90-b1e5-df98a3d40cd6', 'jbellis') USING CONSISTENCY LOCAL_QUORUM AND TTL 86400;

Inserta o actualiza una o varias columnas identificadas por su KEY y su Familia de Columnas

CQLSELECT

SELECT <column_specification> FROM [<keyspace>.]<column_family>[USING CONSISTENCY <consistency_level>][WHERE <row_specification> [AND <row_specification> [...]][LIMIT <integer>]

where <column_specification> is:

<column_name> [, ...] | [FIRST <integer>] [REVERSED] { <start_of_range> .. <end_of_range> | * } | COUNT(*)

and where <row_specification> is:

KEY | <key_alias> { = | < | > | <= | >= } <key_value> KEY | <key_alias> IN (<key_value> [,...])

Devuelve las rows y columnas de la Familia de Columnas solicitada

CQLSELECT

SELECT name, title FROM employees WHERE KEY IN (199, 200, 207);

SELECT FIRST 3 REVERSED 'time199'..'time100' FROM events;

SELECT COUNT(*) FROM users;

Devuelve las rows y columnas de la Familia de Columnas solicitada

A diferencia que en el SELECT de SQL, en CQL no se garantiza que las columnas solicitadas existan y no dará error si esto ocurre. Simplemente se devolverá el conjunto vacío de resultados.

CQLTRUNCATE

TRUNCATE <column_family>;

TRUNCATE user_emails;

Elimina todos los datos de una Familia de Columnas

CQLUPDATE

UPDATE <column_family> [ USING <write_option> [ AND <write_option> [...] ] ]; SET <column_name> = <column_value> [, ...] | <counter_column_name> = <counter_column_name> {+ | -} <integer> WHERE <row_specification>;

where <write_option> is:

USING CONSISTENCY <consistency_level> TTL <seconds> TIMESTAMP <integer>

and where <row_specification> is:

KEY | <key_alias> = <key_value> KEY | <key_alias> IN (<key_value> [,...])

Actualiza una o varias columnas del row y la Familia de Columnas especificados

CQLUPDATE

UPDATE users USING CONSISTENCY QUORUM SET 'state' = 'TX' WHERE KEY IN (88b8fd18-b1ed-4e96-bf79-4280797cba80, 06a8913c-c0d6-477c-937d-6c1b69a95d43, bc108776-7cb5-477f-917d-869c12dfffa8);

UPDATE users USING CONSISTENCY QUORUM SET 'name' = 'John Smith', 'email' = 'foo@bar.com' WHERE user_uuid = 88b8fd18-b1ed-4e96-bf79-4280797cba80;

UPDATE page_views USING CONSISTENCY QUORUM AND TIMESTAMP=1318452291034 SET 'index.html' = 'index.html' + 1 WHERE KEY = 'www.cosasquecontar.com';

Actualiza una o varias columnas del row y la Familia de Columnas especificados

CQLUSE

USE <keyspace_name>;

USE demo;

Conecta la sesión actual con el Keyspace especificado

Conexión y acceso desde lenguajes de alto nivel

Se ofrecen dos formas de acceder al cluster de Cassandra.

Mediante el terminal usando la línea de comandos prompt.

Mediante lenguajes de alto nivel mediante librerías CLI.

Conexión y acceso desde lenguajes de alto nivel

Acceso desde el prompt

cassandra-cli. >./bin/cassandra-cli

cqlsh. >./bin/cassandra-cliIntérprete de CQL. Precisa de Python para funcionar.

Conexión y acceso desde lenguajes de alto nivel

Lenguajes de alto nivel soportados:

Python

Java (Incluido Driver)

Scala

Node.js (Incluido Driver)

Clojure

.NET

Ruby (Incluido Driver)

PHP (Incluido PDO Driver)

Perl

C++

Haskel

La mayor parte son Frameworks de terceros.

Aplicación de ejemplo sobre Cassandra

Modelo a desarrollar

Aplicación de ejemplo sobre Cassandra

KEYSPACE ejemplo;

Estructura de BD Cassandra

Se crea el Keyspace que contendrá la aplicación

Aplicación de ejemplo sobre Cassandra

Estructura de BD Cassandra

ColumnFamily Usuario;ColumnFamily Tweet;

Por cada clase del modelo UML se crea una Familia de Columas

Por norma general, cada relación que genere una lista de objetos (i.e. relaciones 0..n, 1..n, n..m) se crea una Familia de Columnas donde se

alojarán referencias a cada objeto de la lista. Será indexado por la KEY del objeto principal.

ColumnFamily Following;ColumnFamily Followers;ColumnFamily UserTweets;

Aplicación de ejemplo sobre Cassandra

Estructura de BD Cassandra

ColumnFamily Usuario;ColumnFamily Tweet;

Por cada clase del modelo UML se crea una Familia de Columas

Cuando una clase UML tiene como destino claro realizar búsquedas (por ejemplo, una clase PalabrasClave donde no hay más de un atributo)

no hace falta crear una segunda familia de columnas.

ColumnFamily Following;ColumnFamily Followers;ColumnFamily UserTweets;

Aplicación de ejemplo sobre Cassandra

Estructura de BD Cassandra

La creación de índices secundarios no es recomendable salvo que sea estrictamente necesario para realizar búsquedas.

Las KEY no hay que definirlas.

Aplicación de ejemplo sobre Cassandra

Estructura de BD Cassandra

Usuario = { 'roviyo': { 'password': '12345', 'email': 'roviyo@hotmail.com' }, 'pleys : { 'password': 'abc123', 'email': 'pleys@gmail.com' }, ...}

ColumnFamily Usuario;

Aplicación de ejemplo sobre Cassandra

Estructura de BD Cassandra

Tweet = { '7561a442-24e2-11df-8924-001ff3591711': { 'owner': 'roviyo', 'body': 'hola mundo, esto es un tweet', },}

ColumnFamily Tweet;

Aplicación de ejemplo sobre Cassandra

Estructura de BD CassandraFollowing = { 'roviyo': { # follow KEY: timestamp en que fue añadida a la lista 'pleys': '1267413962580791', 'joan': '1267413990076949', 'bob23' : '1267414008133277', ... }, ...}

Followers = { 'roviyo': { # follow KEY: timestamp en que fue añadida a la lista 'larry': '1267413962580791', 'curly': '1267413990076949' }, ...}

UserTweets = { 'roviyo': { # tweet KEY: timestamp en que fue añadido a la lista '7561a442-24e2-11df-8924-001ff3591711': '1267413962580791', '7561a442-24e2-11df-8924-001ff3110091': '1267413990076949' }, ...}

Realizar el diagrama UML y el diseño del schema Cassandra en JSON del siguiente problema.

Se precisa de un pequeño blog de noticias.

El blog puede contener a varios autores.

Cada autor tiene un nombre, un nombre de usuario, una cuenta de twitter y una descripción.

Las noticias tienen un título, un cuerpo y una fecha de publicación.

Son publicadas por un autor.

Pueden contener o no, una lista de tags.

Los visitantes del blog pueden comentar las noticias. Cada comentario contiene un nombre (escrito por el visitante al enviar el comentario) y un cuerpo.

Ejercicio