torodb @barcelonajug 2015
TRANSCRIPT
ToroDBLa primera base de datos desarrollada en España
Compatible con MongoDB y escrita en Java
Gonzalo Ortiz <[email protected]>Álvaro Hernández <[email protected]>
ToroDB @NoSQLonSQL
Acerca de *8Kdata*
● Investigación y Desarrollo en bases de datos
● Consultoría, Formación y Desarrollo PostgreSQL
● Fundadores de PostgreSQL España, el 3er PUG mayor del mundo (más de 410 a fecha de hoy)
● Gonzalo: Desarrollador Principal de ToroDB
● Álvaro: CTO de 8Kdata. Twitter: @ahachete
www.8kdata.com
ToroDB @NoSQLonSQL
ToroDB en una diapositiva
● BBDD NoSQL orientada a documentos
● La 1ª bbdd desarrollada en España
● Software libre (AGPL)
● Compatible con el protocolo de Mongo
● Usa PostgreSQL para almacenamiento
ToroDB @NoSQLonSQL
¿Por qué no usar RDBMs para construir NoSQLs?Perspectiva técnica
● El modelo de Documento atrae a muchos. Pero todas las NoSQL han reinventado la rueda, partiendo de 0
● DRY: ¿por qué no usar RDBMs? Han demostrado que son durables, confiables, potentes y flexibles
● ¿Por qué no usar PostgreSQL?
ToroDB @NoSQLonSQL
● El mercado NoSQL es aún una fracción del tamaño del mercado relacional
● Las empresas sufren para introducir nuevos “stacks”: certificaciones, contratos de soporte, expertise técnico...
● ¿Por qué no ofrecer el modelo de documento pero sobre las IT actuales?
¿Por qué no usar RDBMs para construir NoSQLs?Perspectiva de negocio
ToroDB @NoSQLonSQL
¿Cómo se almacenan los datos?
● Los datos se almacenan en blobs tablas
● Los documentos se dividen por niveles de jerarquía en subdocumentos que no tienen niveles anidados. Cada subdocumento se almacena separado
● Los subdocumentos se clasifican por “tipo”. Cada tipo se mapea a una tabla
ToroDB @NoSQLonSQL
● La tabla structure almacena el “schema” del subdocumento
● Las claves del documento se mapean a columnas con su nombre original
● Las tablas de datos se crean dinámicamente para encajar en el tipo exacto de cada subdocumento
¿Cómo se almacenan los datos?
ToroDB @NoSQLonSQL
{ "name": "ToroDB", "data": { "a": 42, "b": "hello world!" }, "nested": { "j": 42, "deeper": { "a": 21, "b": "hello" } }}
¿Cómo se almacenan los datos?
ToroDB @NoSQLonSQL
El documento se divide en los siguientes subdocumentos:
{ "name": "ToroDB", "data": {}, "nested": {} }
{ "a": 42, "b": "hello world!"}
{ "j": 42, "deeper": {}}
{ "a": 21, "b": "hello"}
¿Cómo se almacenan los datos?
ToroDB @NoSQLonSQL
select * from demo.t_3┌─────┬───────┬────────────────────────────┬────────┐│ did │ index │ _id │ name │├─────┼───────┼────────────────────────────┼────────┤│ 0 │ ¤ │ \x5451a07de7032d23a908576d │ ToroDB │└─────┴───────┴────────────────────────────┴────────┘select * from demo.t_1┌─────┬───────┬────┬──────────────┐│ did │ index │ a │ b │├─────┼───────┼────┼──────────────┤│ 0 │ ¤ │ 42 │ hello world! ││ 0 │ 1 │ 21 │ hello │└─────┴───────┴────┴──────────────┘select * from demo.t_2┌─────┬───────┬────┐│ did │ index │ j │├─────┼───────┼────┤│ 0 │ ¤ │ 42 │└─────┴───────┴────┘
¿Cómo se almacenan los datos?
ToroDB @NoSQLonSQL
select * from demo.structures┌─────┬────────────────────────────────────────────────────────────────────────────┐│ sid │ _structure │├─────┼────────────────────────────────────────────────────────────────────────────┤│ 0 │ {"t": 3, "data": {"t": 1}, "nested": {"t": 2, "deeper": {"i": 1, "t": 1}}} │└─────┴────────────────────────────────────────────────────────────────────────────┘
select * from demo.root;┌─────┬─────┐│ did │ sid │├─────┼─────┤│ 0 │ 0 │└─────┴─────┘
¿Cómo se almacenan los datos?
ToroDB @NoSQLonSQL
Almacenamiento e I/O en ToroDB
sólo necesita 29% - 68%del almacenamiento que requiere Mongo 2.6
ToroDB @NoSQLonSQL
Oplog de MongoDB y tailable cursors
El oplog es una colección capped y de sistema, que contiene comandos DML idempotentes
Los tailable cursors son queries “abiertas”, donde los datos son enviados en streaming según llegan a la bbdd
Ambos muy usados (replicación, Meteor)
ToroDB @NoSQLonSQL
Es posible implementarlo gracias a logical decoding de PostgreSQL 9.4
Implementar el master de replicación es simplemente logical decoding convertido de vuelta a documento y en JSON
Los tailable cursors es logical decoding más aplicar la query para filtrar
Oplog de MongoDB y tailable cursors
ToroDB @NoSQLonSQL
El software
ToroDB está escrito en Java, compatible (y diseñado) para JVM6 (y superior)
Se ha probado únicamente en la JVM de Oracle, pero se busca probarlo en Azul
Actualmente se distribuye como un JAR ejecutable, pero se ofrecerá también como EAR para desplegar en J2EE
ToroDB @NoSQLonSQL
Apoyado en los hombros de gigantes
● PostgreSQL● Netty● HikariCP● Guava, Guice, findbugs● jOOQ
Son excelentes herramientas / frameworks que ofrecen millones de líneas de código probadas y fiables, en las que apoyarse
ToroDB @NoSQLonSQL
Código fuente muy modular
● Aplicación: consiste en 20+ módulos
● Muchos son reutilizables por sí mismos
● Varias capas de abstracción:➔ D2R (Document 2 Relational)➔ KVDocument (abstracción de KV docs)➔ Base de datos (relacional)
ToroDB @NoSQLonSQL
Otro módulo más de ToroDB
● MongoWP es nuestra implementación del protocolo de red de MongoDB
● Basado en Netty, excelente framework NIO de alto rendimiento y asíncrono
● MongoWP ofrece un interfaz de callback para cualquier implementación de middleware Mongo (ToroDB, proxy...)
ToroDB @NoSQLonSQL
Requisitos de ejecución
● Las peticiones de un usuario deben ejecutarse de manera ordenada (FIFO)
●Las peticiones pesadas de un usuario no deberían bloquear a los demás
●Las peticiones pueden ser síncronas o asíncronas
●La huella de memoria es finita.
ToroDB @NoSQLonSQL
Arquitectura del ejecutor
Colas de usuarios
Cola de sistema
Colas de control general
Con
exio
nes
ToroDB @NoSQLonSQL
Escritura en ToroDB
● Cada usuario tiene una cola de ejecución (orden de ejecución FIFO)
●Las peticiones pesadas de un usuario detienen únicamente a sus peticiones
● Existe una cola de ejecución de órdenes del sistema (tratar con metainformación)
● Existe una cola inicial no limitada por tamaño sino por estado de la memoria
ToroDB @NoSQLonSQL
ToroDB: Developer Preview
● ToroDB fue lanzado públicamente en octubre de 2014, con soporte para CRUD y gran parte del API de consultas
● github.com/torodb
● Política RERO. Se agradecen comentarios, críticas, parches...
● AGPLv3
ToroDB @NoSQLonSQL
ToroDB: Developer Preview
● Clonar el repo, construir con Maven
● O descargar el JAR:http://maven.torodb.com/jar/com/torodb/torodb/0.20/torodb.jar
● Utilización:java -jar torodb-0.20.jar –helpjava -jar torodb-0.20.jar -d dbname -u dbuser -P 27017
Y conectar... ¡con la consola Mongo! :)
ToroDB @NoSQLonSQL
ToroDB: Roadmap
● La versión actual es para sólo un nodo
● Versión 1.0:
➔ Estimado Q4 2015➔ Calidad producción➔ Soporte de replicación de MongoDB➔ Alta compatibilidad con el API Mongo
ToroDB @NoSQLonSQL
ToroDB: prioridades del desarrollo
#1 Ofrecer la experiencia de MongoDB sobre infraestructuras IT ya existentes, como app servers y RDBMSs
#2 Ir más allá de lo que Mongo ofrece, como ACID y concurrencia
#3 Excelente rendimiento
ToroDB @NoSQLonSQL
Mejorando MongoDB
MongoDB trajo el modelo de documento, HA fácil y sharding, y lo popularizó
Pero también varios problemas. ¿Y si fuera posible mejorarlo / solucionarlos?
¿No podemos aprovechar el modelo relacional y las RDBMs para ofrecer mejores características que MongoDB?
ToroDB @NoSQLonSQL
La falacia del “schema-less”
{“name”: “Álvaro”,“surname”: “Hernández”,“height”: 200,“hobbies”: [
“PostgreSQL”, “triathlon”]
}
ToroDB @NoSQLonSQL
{“name”: “Álvaro”,“surname”: “Hernández”,“height”: 200,“hobbies”: [
“PostgreSQL”, “triathlon”]
}metadata → ¿no es esto... schema?
La falacia del “schema-less”
ToroDB @NoSQLonSQL
metadata → ¿no es esto... schema?
{“name”: (string) “Álvaro”,“surname”: (string) “Hernández”,“height”: (number) 200,“hobbies”: {
“0”: (string) “PostgreSQL” , “1”: (string) “triathlon”
}}
La falacia del “schema-less”: BSON
ToroDB @NoSQLonSQL
● No existe tal “schema-less”
● Es más bien “attached-schema”
● Y esto tiene una sobrecarga, mucha duplicación del espacio ocupado por la metainformación
La falacia del “schema-less”
ToroDB @NoSQLonSQL
Duplicidades en Schema-attached
{ “a”: 1, “b”: 2 }{ “a”: 3 }{ “a”: 4, “c”: 5 }{ “a”: 6, “b”: 7 }{ “b”: 8 }{ “a”: 9, “b”: 10 }{ “a”: 11, “b”: 12, “j”: 13 }{ “a”: 14, “c”: 15 }
Contando “tipos de documentos” en millones de documentos: como máximo, miles de tipos
ToroDB @NoSQLonSQL
ToroDB: query “según la estructura”
● ToroDB a todos los efectos está particionando por tipo
● Las estructuras (que son los schemas de los documentos y las “claves de particionado”) se cachean en memoria
● Las consultas sólo escanean un subconjunto de los datos. Queries “negativas” se sirven desde memoria
ToroDB @NoSQLonSQL
Cheap single-node durability
● Sin journaling, MongoDB no es durable ni tolerante a caídas
● MongoDB requiere“j: true” para durabilidad real de un nodo. Pero ¿quién garantiza su uso consistente? ¿Quién lo usa por defecto?
● j:true crea tormentas de I/O
ToroDB @NoSQLonSQL
http://docs.mongodb.org/manual/reference/write-concern/#read-isolation-behavior
“MongoDB will allow clients to read the results of a write operation before the write operation returns.”
“If the mongod terminates before the journal commits, even if a write returns successfully, queries may have read data that will not exist after the mongod restarts.”
“Other database systems refer to these isolation semantics as read uncommitted.”
Lecturas “limpias”
ToroDB @NoSQLonSQL
Por lo tanto, MongoDB sufre dirty reads. O tal vez llamémoslo “tainted reads”
¿Y ni siquiera con $snapshot? No:
“The snapshot() does not guarantee that the data returned by the query will reflect a single moment in time nor does it provide isolation from insert or delete operations.”
http://docs.mongodb.org/manual/faq/developers/#faq-developers-isolate-cursors
Lecturas “limpias”
ToroDB @NoSQLonSQL
https://aphyr.com/posts/322-call-me-maybe-mongodb-stale-reads
Lecturas “limpias”:“Call me maybe”
ToroDB @NoSQLonSQL
ToroDB: mejorando MongoDB
● Durabilidad de un nodoPostgreSQL es 100% durable. Siempre. Y muy barato (no hay tormentas de I/O)
● Lecturas “limpias”En ToroDB los cursores se ejecutan en modeo REPEATABLE READ y READ ONLY
globalCursorDataSource.setTransactionIsolation("TRANSACTION_REPEATABLE_READ");
globalCursorDataSource.setReadOnly(true);
ToroDB @NoSQLonSQL
Operaciones atómicas
● En MongoDB no hay soporte para ops atómicas (insert/update/delete)
● Ni siquiera con $isolated:“Prevents a write operation that affects multiple documents from yielding to other reads or writes […] You can ensure that no client sees the changes until the operation completes or errors out. The $isolated isolation operator does not provide “all-or-nothing” atomicity for write operations.”http://docs.mongodb.org/manual/reference/operator/update/isolated/
ToroDB @NoSQLonSQL
Alta concurrencia
● MMAPv1 sigue siendo collection-locked
● WiredTiger es document-locked. No usar en producción hasta 3.2 ó 3.4
● Pero aún hay locks exclusivos. Las RDBMs tienen MVCC (algunas, como Pg) que implica lectores no bloquean sólo escritores a otros escritores a veces
ToroDB @NoSQLonSQL
● Operaciones en batch atómicas:Por defecto, las operaciones en batch son atómicas. Usa el flag ContinueOnError para que no sea así
● Máxima concurrencia:PostgreSQL usa MVCC. Los lectores y escritores no se bloquean
ToroDB: mejorando MongoDB
ToroDB @NoSQLonSQL
ToroDB: direcciones de investigación
● Usar almacenamiento por columnas (CitusDB)
● Usar Postgres-XL como backend. Esto requeriría cambiar la caché de ToroDB a distribuida (ehcache, Hazelcast)
● Usar pg_shard para el sharding
ToroDB @NoSQLonSQL
Big Data hablando Mongo:Vertical ToroDB
¿Y si usáramos cstore para almacenar los datos verticalmente?
ToroDB @NoSQLonSQL
1.17% - 20.26% del espacio requerido,comparado con Mongo 2.6
Big Data hablando Mongo:Vertical ToroDB