Posts tagged with “mongodb”
Replicación maestro-esclavo en MongoDB
Esta es una entrada cortita, gracias en parte a la extrema facilidad de administrador de nuestra base de datos NoSQL favorita. En esta ocasión vamos a ver como crear una replicación dentre dos sistemas MongoDB, en arquitectura Maestro-Esclavo. Como pasa bastante habitualmente, la arquitectura Maestro-Maestro, a pesar de ser posible, no la recomiendan. Esta, al igual que en MySQL, se basa en el truco de hacer que un esclavo sea al mismo tiempo maestro.
Yo voy a mostrar la opción recomendada, Maestro-Esclavo.
Para ello, lo primero es instalar dos MongoDB en Debian Lenny.
El primero se llamará Maestro con IP 192.168.1.105 y el segundo Esclavo con IP 192.168.1.101.
Arrancamos el maestro indicando que actuará con ese Rol:
debian1:/usr/local/mongodb# bin/mongod --master Sat Jun 12 16:41:23 Mongo DB : starting : pid = 2158 port = 27017 dbpath = /data/db/ master = 1 slave = 0 64-bit Sat Jun 12 16:41:23 db version v1.4.3, pdfile version 4.5 Sat Jun 12 16:41:23 git version: 47ffbdfd53f46edeb6ff54bbb734783db7abc8ca Sat Jun 12 16:41:23 sys info: Linux domU-12-31-39-06-79-A1 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41 Sat Jun 12 16:41:23 waiting for connections on port 27017 Sat Jun 12 16:41:23 ****** Sat Jun 12 16:41:23 creating replication oplog of size: 944MB (use --oplogSize to change) Sat Jun 12 16:41:23 ****** Sat Jun 12 16:41:23 allocating new datafile /data/db/local.ns, filling with zeroes... Sat Jun 12 16:41:23 done allocating datafile /data/db/local.ns, size: 16MB, took 0.026 secs Sat Jun 12 16:41:23 allocating new datafile /data/db/local.0, filling with zeroes... Sat Jun 12 16:41:23 done allocating datafile /data/db/local.0, size: 64MB, took 0.185 secs Sat Jun 12 16:41:23 allocating new datafile /data/db/local.1, filling with zeroes...
Una vez hecho, arrancamos el Esclavo indicándole por parámetro donde está su Maestro:
debian2:/usr/local/mongodb/bin# ./mongod --slave --source 192.168.1.105:27017 Sat Jun 12 16:42:03 Mongo DB : starting : pid = 2172 port = 27017 dbpath = /data/db/ master = 0 slave = 1 64-bit Sat Jun 12 16:42:03 db version v1.4.3, pdfile version 4.5 Sat Jun 12 16:42:03 git version: 47ffbdfd53f46edeb6ff54bbb734783db7abc8ca Sat Jun 12 16:42:03 sys info: Linux domU-12-31-39-06-79-A1 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41 Sat Jun 12 16:42:03 waiting for connections on port 27017 Sat Jun 12 16:42:03 web admin interface listening on port 28017 Sat Jun 12 16:42:04 allocating new datafile /data/db/local.ns, filling with zeroes... Sat Jun 12 16:42:04 done allocating datafile /data/db/local.ns, size: 16MB, took 0.028 secs Sat Jun 12 16:42:04 allocating new datafile /data/db/local.0, filling with zeroes... Sat Jun 12 16:42:05 done allocating datafile /data/db/local.0, size: 64MB, took 0.185 secs Sat Jun 12 16:42:05 building new index on { id: 1 } for local.sources Sat Jun 12 16:42:05 Buildindex local.sources idxNo:0 { name: "_id", ns: "local.sources", key: { _id: 1 } } Sat Jun 12 16:42:05 done for 0 records 0secs Sat Jun 12 16:42:05 repl: from host:192.168.1.105:27017 Sat Jun 12 16:42:05 repl: applied 1 operations Sat Jun 12 16:42:05 repl: end sync_pullOpLog syncedTo: Sat Jun 12 16:42:00 2010 4c139cb8:1
Ya tenemos las dos bases de datos en marcha:

Creamos una nueva base de datos llamada test y añadimos una colección:
> use test switched to db test > a = { nombre : "Miguel Angel", apellido : "Nieto" } { "nombre" : "Miguel Angel", "apellido" : "Nieto" } > db.gente.save(a);
Comprobamos que se ha añadido en Maestro:

Comprobamos que se ha añadido en Esclavo:

Y lo buscamos en el Esclavo:

Más facil y rápido imposible :)
Introducción al mundo noSQL
NoSQL es la nueva palabra de moda. Una solución pensada para el almacenamiento de gran cantidad de datos para su posterior uso. Esto ya nos suena, una base de datos, pero realmente, ¿cual es la diferencia?
NoSQL es un término usado en informática para agrupar una serie de almacenes de datos no relacionales que no proporcionan garantías ACID. Normalmente no tienen esquemas fijos de tablas ni sentencias "join".
Wikipedia
La diferencia ya es clara, no es una base de datos como las que conocemos actualmente, es bastante más peculiar y tira por tierra bastantes de los conceptos y formas de trabajar a los que estamos acostumbrados. Y aunque el termino en si sea nuevo, la teoría tiene sus años, bastantes más que las bases de datos relacionales, pero ahora vuelve con fuerza para salvarnos la vida en algunos casos concretos, evitando problemas de escalabilidad o rendimiento a costa de algo de fiabilidad.
Hasta ahora el cuello de botella siempre ha sido el acceso a los datos y la forma de evitarlo la escalabilidad vertical, esto es, añadiendo más memoria, procesamiento y discos rápidos. Pero todo escalado vertical tiene un límite, y es el que pone nuestro bolsillo y la propia tecnología. Por otro lado, las bases de datos relacionales no suelen tender a escalar bien horizontalmente.
- Normalización o desnormalización
- Replicación asíncrona y por lo tanto problemática
- ¿Cómo distribuyes la carga de escrituras?
- ¿Transacciones distribuidas? Uff... no!
Es importante tener en cuenta que no es un reemplazo a las bases de datos SQL que llevamos usando desde hace años, si no que un complemento que nos ayudará en casos particulares, por lo tanto tened en mente que noSQL es en realidad no(tOnly)SQL :)
A modo introducción vamos a ver el funcionamiento de MongoDB, una de las que más me han impresionado por su facilidad de uso y rapidez.
MongoDB agrupa los datos documentos (y sub-documentos). Esto es, objetos sin ningún tipo de esquema fijo, como por ejemplo un array de PHP o una tupla de Python. Los datos se guardan en BSON (JSON binario) y permite consultas algo más complejas que algunas otras soluciones NoSQL.
BSON [bee · sahn], short for Binary JSON, is a binary-encoded serialization of JSON-like documents. Like JSON, BSON supports the embedding of documents and arrays with in other documents and arrays. BSON also contains extensions that allow representation of data types that are not part of the JSON spec. For example, BSON has a Date type and a BinData type.
Además soporta el uso de índices compuestos, simples o geo-espaciales de dos dimensiones, auto particionado de datos y replicación master-slave entre otras muchas cosas. Importante para los desarrolladores, ¡existe módulo de PHP! ;) No en vano, la gente lo empieza a llamar el MySQL de NoSQL.
Después de esta pequeña introducción vamos a jugar un poco con MongoDB :) Para ello nos bajamos el binario de http://www.mongodb.org/display/DOCS/Downloads La instalación es tan sencilla como descomprimir y lanzar el binario del servidor (mongod):
bin # ./mongod ./mongod --help for help and startup options Fri May 7 21:16:00 Mongo DB : starting : pid = 307 port = 27017 dbpath = /data/db/ master = 0 slave = 0 64-bit Fri May 7 21:16:00 db version v1.4.1, pdfile version 4.5 Fri May 7 21:16:00 git version: nogitversion Fri May 7 21:16:00 sys info: Darwin iMac-Punisher.local 10.3.0 Darwin Kernel Version 10.3.0: Fri Feb 26 11:58:09 PST 2010; root:xnu-1504.3.12~1/RELEASE_I386 i386 BOOST_LIB_VERSION=1_42 Fri May 7 21:16:00 waiting for connections on port 27017 Fri May 7 21:16:00 web admin interface listening on port 28017
A primera vista ya vemos datos interesantes. Los datos se van a guardar en la ruta /data/db, que debemos crear con antelación o indicar otra mediante parámetro, y que el puerto de escucha será 27017. Si no le indicamos nada, el demonio se lanzará en foreground y la consola se quedará "bloqueada". Podremos parar el demonio con un simple Control+C.
La consola para empezar a usar mongoDB se llama "mongo", que se encuentra en la misma ruta de binarios que el resto.
bin $ ./mongo MongoDB shell version: 1.4.1 url: test connecting to: test type "help" for help >
Vemos las bases de datos existentes y nos creamos la nuestra propia:
> show dbs admin local > use midb switched to db midb
Como veis no es necesario crearla antes de usarla, simplemente dile que la quieres usar y si no existe la creará. Ahora vamos a meter una serie de datos:
>a = { nombre : "Miguel Angel", apellidos : "Nieto Salazar", edad : "27", localidad : "Barakaldo" } { "nombre" : "Miguel Angel", "apellidos" : "Nieto Salazar", "edad" : "27", "localidad" : "Barakaldo" } >b = { nombre : "Estibaliz", apellidos : "Sanchez", Nacimiento : "Logroño", estudio : "Comercio" } { "nombre" : "Estibaliz", "apellidos" : "Sanchez", "Nacimiento" : "Logroño", "estudio" : "Comercio" } > db.coll.save(a); > db.coll.save(b);
Y como ya dije anteriormente, no existen tablas ni esquemas, añades datos según lo vas necesitando, sin necesidad de seguir un patrón o estando obligado a rellenar unos datos en concreto. Todos estos documentos se guardarán en la colección "coll" dentro de la base de datos midb. Una colección no es más que una agrupación de datos BSON que estos a su vez se pueden agrupar en namespaces. Por ejemplo blog.post y blog.comments son dos colecciones que cuelgan del mismo namespace. Esto es solamente a nivel organizativo para el usuario, internamente no afecta en nada.
Una vez que tenemos los datos introducidos, podemos hacer consultas:
> db.coll.find({edad:"27"}); { "_id" : ObjectId("4be029e11967ab80a305e1f0"), "nombre" : "Miguel Angel", "apellidos" : "Nieto Salazar", "edad" : "27", "localidad" : "Barakaldo" } > db.coll.find({Nacimiento:"Logroño"}); { "_id" : ObjectId("4be029e41967ab80a305e1f1"), "nombre" : "Estibaliz", "apellidos" : "Sanchez", "Nacimiento" : "Logroño", "estudio" : "Comercio" }
Facil, sencillo y para toda la familia. Cuando lo ves así piensas, "esto es lo lógico, el almacenamiento de datos tendría que ser así siempre" :)
También podemos almacenar datos binarios, esto es, ficheros. Puedes olvidarte de todo lo que has sufrido con los tipos BLOB en otras bases de datos. MongoDB guarda los ficheros en la base de datos haciendo uso de las especificaciones GridFS. BSON solo permite almacenar datos de hasta 4 megas, para saltarnos esta limitación GirdFS divide de forma transparente los ficheros en grupos de documentos (lo cual también nos permitira buscar por rangos de bytes).
Listamos el contenido, de momento no hay ningún fichero:
$ mongofiles list connected to: 127.0.0.1
Añadimos un fichero, en este caso un documento PDF:
$ mongofiles put /Users/punisher/Documents/High\ Performance\ MySQL\ Second\ Edition.pdf connected to: 127.0.0.1 added file: { _id: ObjId(4be46d25a409d73217ca227b), filename: "/Users/punisher/Documents/High Performance MySQL Second Edition.pdf", length: 5904835, chunkSize: 262144, uploadDate: new Date(1273261349209), md5: "082f8333d45d1e3b7bce6323d0da59f0" } done!
Listamos de nuevo:
$ mongoflist connected to: 127.0.0.1 /Users/punisher/Documents/High Performance MySQL Second Edition.pdf 5904835
Lo sacamos de la base de datos a nuestro sistema de ficheros:
$ mongofiles get "/Users/punisher/Documents/High Performance MySQL Second Edition.pdf" connected to: 127.0.0.1 done write to: /Users/punisher/Documents/High Performance MySQL Second Edition.pdf
No lo voy a negar, estoy enamorado de mongoDB y del concepto noSQL. Olvídate de las relaciones, de optimizar queries, normalizar tablas... dedicate a lo que importa, guardar y sacar datos. Una revolución para los que nos guiamos por la filosofía KISS (Keep it simple, stupid)



