lunes, 29 de noviembre de 2010

Comparativa MongoDB con otras Bases de datos NoSQL

He encontrado en myNoSQL algunas tablas comparativas de MongoDB con respecto a otras bases de datos NoSQL, creadas por Alex Popescu.

Bases de datos orientadas a documento
La primera tabla compara tres bases de datos orientadas a documento: MongoDB, CouchDB y RavenDB (echo en falta una columna para OrientDB).

  MongoDB CouchDB RavenDB
Documentos
FormatoBSONJSONJSON
MetadataNoSistemaSistema + personalizado
VersionadoNoSíPlugin incluído
AdjuntosGridFSSíSí
Map/ReduceJavaScript + otrosJavaScriptLINQ
Carga masivamongoimportSíSí
Consulta AdhocSíNoNo
Almacenamiento
FragmentaciónSíSíSí
DurabilidadServidor simple v1.8Diseño "crash-only"Escritura previa trazabilidad y aislamiento de instantáneas para garantizar recuperación vía ESE
TransaccionesNoNoSí
ConcurrenciaActualización in-placeMVCC (Multi-Version Concurrency Control)Concurrencia optimista
ConsistenciaMaestro fuerte / Esclavo eventualNodo fuerte / Cluster eventualEventual
ReplicaciónMaestro-Maestro con funciones de resolución personalizadasMaestro-EsclavoPlugin incluído
Interfaz
ProtocoloPersonalizado sobre TCP/IPHTTP/RESTHTTP/REST
.NET APIProyectos de tercerosProyectos de tercerosIncluído
Otros
TriggersNoValidación de actualización, SeguridadSí
SeguridadBásicaBásicaNinguna
Escrito enC++ErlangC#

Lenguajes de programación
La siguiente tabla muestra el uso de lenguajes de programación en varias bases de datos NoSQL. Yo hubiera añadido también Perl, C/C++, Erlang ó Go, que son lenguajes populares que también comprende MongoDB (entre otros muchos).

  BBDD Modo durabilidad java ruby python php .net http
documento mongodb basado en réplica x x x x x x
  couchdb nodo simple x x x x x x
  ravendb nodo simple - - - - x x
clave-valor redis en memoria, serializado en disco x x x x x -
  riak basado en réplica x x x x x x
tabular cassandra basado en réplica x x x x x -
grafo neo4j nodo simple x x x x - x
  sones nodo simple - - - - x x


Fuentes
http://nosql.mypopescu.com/post/1016366403/nosql-guide-for-beginners
http://nosql.mypopescu.com/post/978742866/document-databases-compared-couchdb-mongodb-ravendb

MongoDB: Ejemplo de configuración de fragmentación

Este post es una traducción del artículo original "Return to the Mongo Mailbag", de Kristina Chodorow.


En la lista de correo mongodb-user de la semana pasada, alguien preguntó (básicamente):

"Tengo 4 servidores y quiero dos frgamentos. ¿Cómo lo configuro?"

Mucha gente está preguntando sobre cómo configurar conjuntos de réplica y fragmentación, por lo que que aquí se explicará en detalle.


The Architecture

Prerequisitos. Si no estás familiarizado con los conjuntos de réplica, echa un vistazo a mi post en mi blog. El resto de este post no tendrá mucho sentido a menos que tú sepas qué es un árbitro. Además, deberías conocer los conceptos de la fragmentación.

Cada fragmento debería ser un conjunto de réplica, por lo que necesitaremos dos conjuntos de réplica (los llamaremos "foo" y "bar"). Queremos que nuestro cluster sea correcto si una de las máquinas se cae o se separa de la manada (partición de red), así que extenderemos fuera cada conjunto entre las máquinas disponibles. Los conjuntos de réplica están codificadas por color y las máquinas son nombradas imaginativamente server1-4.

Cada conjunto de replica tiene dos hosts y un árbitro. De esta manera, si un servidor se cae, ninguna funcionalidad se pierde (y ahí no estarán dos maestros en un servidor simple).

Para configurar ésto, ejecuta:

server1

$ mkdir -p ~/dbs/foo ~/dbs/bar
$ ./mongod --dbpath ~/dbs/foo --replSet foo
$ ./mongod --dbpath ~/dbs/bar --port 27019 --replSet bar --oplogSize 1


server2

$ mkdir -p ~/dbs/foo
$ ./mongod --dbpath ~/dbs/foo --replSet foo


server3

$ mkdir -p ~/dbs/foo ~/dbs/bar
$ ./mongod --dbpath ~/dbs/foo --port 27019 --replSet foo --oplogSize 1
$ ./mongod --dbpath ~/dbs/bar --replSet bar


server4

$ mkdir -p ~/dbs/bar
$ ./mongod --dbpath ~/dbs/bar --replSet bar


Los árbitros tienen un tamaño de oplog de 1. Por defecto, el tamaño de oplog es un ~5% de tu disco duro, pero los árbitros no necesitan mantener ningún dato, por lo que esto es un gran desperdicio de espacio.

Poner juntos los conjuntos de réplica

Ahora arrancaremos los dos conjuntos de réplica. Arrancar la consola mongo y escribir:

> db = connect("server1:27017/admin")
connecting to: server1:27017
admin
> rs.initiate({"_id" : "foo", "members" : [
... {"_id" : 0, "host" : "server1:27017"},
... {"_id" : 1, "host" : "server2:27017"},
... {"_id" : 2, "host" : "server3:27019", arbiterOnly : true}]})
{
  "info" : "Config now saved locally. Should come online in about a minute.",
  "ok" : 1
}
> db = connect("server3:27017/admin")
connecting to: server3:27017
admin
> rs.initiate({"_id" : "bar", "members" : [
... {"_id" : 0, "host" : "server3:27017"},
... {"_id" : 1, "host" : "server4:27017"},
... {"_id" : 2, "host" : "server1:27019", arbiterOnly : true}]})
{
  "info" : "Config now saved locally. Should come online in about a minute.",
  "ok" : 1
}


Ahora tenemos dos conjuntos de réplica en ejecución. Creemos ahora un cluster.


Configurar la fragmentación

Una vez intentemos configurar un sistema sin puntos simples de fallo, usaremos tres servidores de configuración. Podemos tener tantos procesos mongos como queramos (se recomienda uno en cada appserver), pero empezaremos con uno.

server2

$ mkdir ~/dbs/config
$ ./mongod --dbpath ~/dbs/config --port 20000


server3

$ mkdir ~/dbs/config
$ ./mongod --dbpath ~/dbs/config --port 20000


server4

$ mkdir ~/dbs/config
$ ./mongod --dbpath ~/dbs/config --port 20000
$ ./mongos --configdb server2:20000,server3:20000,server4:20000 --port 30000


Ahora añadiremos nuestros conjuntos de réplica al cluster. Concta los mongos y ejecuta el comando addshard:

> mongos = connect("server4:30000/admin")
connecting to: server4:30000
admin
> mongos.runCommand({addshard : "foo/server1:27017"})
{ "shardAdded" : "foo", "ok" : 1 }
> mongos.runCommand({addshard : "bar/server3:27017"})
{ "shardAdded" : "bar", "ok" : 1 }


Como puedes ver, terminarás con un fragmento "foo" y un fragmento "bar". (si estás usando una versión antigua de MongoDB, tus fragmentos tendrán nombres como “shard0000″ o “shard0001″)

Ahora puedes conectar a “server4:30000″ en tu aplicación y utilizarlo con un simple y “normal” mongod. Si quieres añadir más procesos mongos, simplemente arráncalos con los mismos parámetros configdb utilizados anteriormente.

MongoDB: Conjuntos de réplica. Parte 3

Este post asume que sabes qué son los conjuntos de réplica y algo de la sintáxis básica.

En la parte 1, configuramos un conjunto de réplica desde cero, pero la vida real es más desordenado: puedes querer migrar servidores de desarrollo a producción, añadir nuevos esclavos, priorizar servidores, cambiar cosas en el momento (on the fly)... y ésto es lo que este post cubre.


Antes de empezar…

A los conjuntos de réplica no les gusta localhost. Son serviciales para secundarlos... más o menos, bastante... pero a menudo provoca discrepancias. Puedes evitar estas discrepancias usando en su lugar el nombre del servidor (hostname). En Linux, puedes buscar tu nombre de servidor ejecutando el comando:

$ hostname
wooster


De aquí en adelante, usaremos mi nombre de servidor en lugar de localhost.


Arrancar con datos

Esto es más o menos que arrancar sin datos, escepto que deberías hacer una copia de seguridad de tus datos antes de arrancar (deberías siempre hacer un backup siempre de tus datos antes de hacer travesuras con tu servidor de configuración).

Si en el pre-conjunto-réplica, arrancaste tu servidor con algo como:

$ ./mongod

...conviértelo en el primer miembro de tu conjunto de réplica, por lo que has de parar y arrancar de nuevo con la opción –replset:

$ ./mongod --replSet unicomplex/wooster:27017

Ahora, inicializa el conjunto con el único servidor:

> rs.initiate()
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}



Agregar esclavos

Deberías arrancar MongoDB siempre con esclavos, así que agreguemos alguno.

Arranca tu servidor con las opciones usuales, así como también como –replSet. Así, por ejemplo, podríamos hacer:

$ ./mongod --dbpath ~/dbs/slave1 --port 27018 --replSet unicomplex/wooster:27017

Ahora, agregamos este esclavo al conjunto de réplica. Asegurarse de que db está conectado a wooster:27017 (el servidor primario) y arrancar:

> rs.add("wooster:27018")
{"ok" : 1}


Repetir como sea necesario para agregar más esclavos.


Agregar un árbitro

Esto es muy similar a agregar un esclavo. Cuando arranques el árbitro, deberías darle la opción –oplogSize 1. De esta manera el árbitro no desperdiciará espacio.

$ ./mongod --dbpath ~/dbs/arbiter --port 27019 --replSet unicomplex/wooster:27017 --oplogSize 1

Ahora agregarlo al conjunto. Puedes especificar que este servidor es un árbitro pasando en un objeto un campo arbiterOnly a rs.add:

> rs.add({"host" : "wooster:27019", "arbiterOnly" : true})
{"ok" : 1}



Degradar un primario

Supongamos que nuestra compañía tiene disponibles los siguientes servidores:

1. Super máquina Gazillion dollar
2. Instancia EC2
3. iMac que encontramos en la calle

A través de un accidente del destino, el iMac se convierte en primario. Podemos forzarle a que se convierta en esclavo ejecutando el comando:

> imac = connect("imac.example.com/admin")
connecting to: imac.example.com/admin
admin
> imac.runCommand({"replSetStepDown" : 1})
{"ok" : 1}


Ahora el iMac será un esclavo.


Establecer prioridades

Podemos indicar que el iMac nunca sea un maestro (queremos usarlo sólo como backup). Puedes forzar ésto estableciendo su prioridad a cero. La más alta prioridad de un servidor es la que hará que se convierta en maestro si el actual maestro falla. Las únicas opciones son 0 (no puede ser maestro) o 1 (puede ser maestro), pero en el futuro serás capaz de tener una buena graduación de prioridades..

Así, cambiaremos la prioridad del iMac a 0. Para cambiar la configuración, conectemos al maestro y editemos su configuración:

> config = rs.conf()
{
"_id" : "unicomplex",
"version" : 1,
"members" : [
{
"_id" : 0,
"host" : "prod.example.com:27017"
},
{
"_id" : 1,
"host" : "ec2.example.com:27017"
},
{
"_id" : 2,
"host" : "imac.example.com:27017"
}
]
}


Ahora, tenemos que hacer dos cosas: 1) establecer la prioridad del iMac a 0, y 2) actualizar la versión de la configuración. El nuevo número de versión es siempre el anterior más uno

> config.members[2].priority = 0
0
> config.version += 1
2


Finalmente, decimos al conjunto de réplica que tenemos una nueva configuración.

> use admin
switched to db admin
> db.runCommand({"replSetReconfig" : config})
{"ok" : 1}


Todos los cambios de configuración deben ocurrir en el maestro. Éstos se propagarán de éste a los esclavos. Ahora puedes "matar" cualquier servidor y el iMac nunca se convertirá en maestro.

Esta configuración es un poco melindrosa para hacer desde la consola. En el futuro, la gente probablemente utilice una GUI para configurar sus conjuntos y trastear con la configuración del servidor.


Artículo original: http://www.snailinaturtleneck.com/blog/2010/08/03/part-3-replica-sets-in-the-wild/