在Microsoft Azure上使用CentOS虚拟机部署Mongo数据库高可用集群

来源:互联网 发布:网络电视机wifi 编辑:程序博客网 时间:2024/05/29 13:32

MongoDB应用已经非常普遍,根据DB-Engine的最新统计,MongoDB在所有NoSQL数据库中,流行程度排名第一;而在全部数据库中它的流行程度已经排名第5。

MongoDB的一大优点在于其灵活的数据模型,它允许开发者以JSON格式的文档来表示和存储数据。此外,MongoDB在企业中的普及与其高可用性也关系紧密。在这篇文章里,我们将介绍如何基于MicrosoftAzure上的CentOS虚拟机来创建Mongo数据库集群。

MongoDB的数据复制原理

MongoDB目前建议采用副本集的方式来实现高可用性,其特点如下:

1.      副本集是一组包含相同数据集合的mongod进程实例。

2.      副本集包含一个主节点(Primary)和多个副节点(Secondary)。副本集一般情况下应该包含奇数个节点,以便于竞选主节点。

3.      主节点负责接收和处理客户端的所有写操作。主节点会把所有的数据集合的改变记录在oplog中。

4.      从节点会以异步的方式复制主节点的oplog,并在自己的数据集合上重新执行这些操作,从而保证数据的严格一致。

5.      当主节点不可用,系统会从副本集中自动选择一个从节点作为主节点。

6.      客户端缺省是从主节点读取数据,但可以指定其它读策略,使得也可以从副节点读取数据,从而提高读的效率。

更多细节可以参考官方文档:http://docs.mongodb.org/manual/core/replication-introduction/

集群的部署架构

在本文中,我们采用的是一主两从的部署架构。在这种架构下,即使主节点不可用,仍然可以确保在从节点中选出新的主节点。

在Azure上,我们将为主节点和两个从节点各分配一个虚拟机,并且要保证这三台虚拟机处于同一个可用性集内,这样它们将被Azure置于不同的更新域和故障域中。此外,我们将把这三个虚拟机置于同一个云服务和虚拟网络之中,整个系统的架构如下图所示:


本文的系统配置如下:虚拟机基于CentOS 6.5,MongoDB使用2.6。

创建虚拟机及其外围环境

在创建虚拟机之前,我们需要先创建地缘组、存储账户、虚拟网络和云服务,其步骤可参见《在WindowsAzure上基于CentOS 6.3部署MySQL 5.6主从式数据库(1)》。这里不再赘述。

完成上述工作之后,在Azure的管理门户中选择CentOS6.5映像,创建第一个虚拟机:

设置好该虚拟机所在的云服务、虚拟网络和存储账户,如下图:


依次建好三个虚拟机,在每个虚拟机的“配置”页面,将虚拟机加入同一个可用性集中,这样,三个虚拟机不会位于同一个物理节点,从而可以保证高可用性。如下图所示:


添加数据磁盘

由于我们的虚拟机将用于存储数据库,我们当然希望这些数据存储能够持久,因此数据库应该置于数据磁盘中。在Azure中,每个虚拟机除了OS磁盘和临时磁盘之外,还可以添加一或多块数据磁盘。例如,1核的A1型虚拟机可以关联2块数据磁盘,每个数据磁盘的最大容量是1TB。这些数据磁盘都是存放在Azure Storage之中,且在同一个数据中心会有3份拷贝。

逐一为每个虚拟机添加空白的数据磁盘,如下图所示:


空磁盘的缓存选项设为“无”,如下图:


数据磁盘添加好后,我们需要通过PuTTY登录到虚拟机内部对磁盘进行格式化。输入fdisk命令如下:fdisk /dev/sdc


格式化完成后,再输入下述命令建立ext4文件系统:mkfs –t ext4 /dev/sdc1


输入下述命令,将新的数据磁盘挂载至某个目录下:mount /dev/sdc1  /mongodb


为了保证虚拟机重启后能够自动挂载数据磁盘,需要修改/etc/fstab配置文件,如下图所示:


注意,新磁盘分区的UUID的值可以通过下述命令读取:sudo -i blkid

对每个虚拟机重复上述步骤,确保每个虚拟机都有配置好的数据磁盘。

安装配置MongoDB

为了提高MongoDB的安装速度,我们建议先从官网上下载安装包到本机,然后从本机将安装包上传至Azure Blob存储中。下图显示了已上传至Azure存储中的安装包:


通过PuTTY登录到第一个虚拟机中,进入数据磁盘所在的目录,MongoDB将安装在这个目录下:

cd /mongodb

输入下述命令下载安装包:

wget http://[storage_account].blob.core.chinacloudapi.cn/[container]/mongodb-linux-x86_64-2.6.0.tgz


从上图可见,由于在同一个数据中心,安装包下载速度非常快,100MB+的文件1秒左右即下载完成。

下载之后,输入下述命令对安装包解压缩:

tar xvzf mongodb-linux-x86_64-2.6.0.tgz

在数据磁盘所在的目录下再建立一个目录,该目录作为MongoDB的数据存储目录:

mkdir /mongodb/data

创建配置文件mongodb.conf如下,其中dbPath的值为MongoDB的数据存储目录,bindIp的值为当前虚拟机的内部IP地址,port保持为27017:


对于其它虚拟机,重复上述步骤,分别安装和配置好MongoDB。

启动MongoDB

登录进入每个虚拟机,输入下述命令,以后台服务的形式启动mongoDB:

bin/mongod --fork --logpath /var/log/mongodb.log --config /mongodb/mongodb.conf


当所有虚拟机上的mongod进程被启动后,输入下述命令进入mongo shell环境:

bin/mongo mongo-vm1/admin


注意,这里我们使用的是虚拟机的名字来表示虚拟机的地址。在同一个云服务中,各虚拟机可以通过名字相互访问。

在mongo shell中输入rs.status(),可以查看集群的状态,由下图可见集群已经建立好:


插入数据

MongoDB的副本集中只有Primary节点能支持写入数据,因此,我们必须登录至主节点所在的虚拟机,来执行数据的插入。

首先,我们需要在mongo shell中输入下述命令创建新的数据库:use travelProduct

接下来,在mongo shell中输入下述命令,为travelProduct数据库上的products collection添加document如下:

检查数据复制

登录到某一个从节点的虚拟机,且进入mongo shell。缺省情况下,MongoDB不允许从节点读取数据,为了允许从节点读取数据,需要输入下述命令:db.setSlaveOk();

再输入下述命令,检查从节点上的数据复制情况:db.products.find();


由上图可见,前面插入的数据已经复制到从节点mongo-vm2中。

通过Node.js访问MongoDB集群

要使外部程序访问MongoDB集群,需要先将三个节点的输入端点配置好。注意:同一个云服务内不同实例的公用端口不得重复,因此三个节点的mongo端点的公用端口各不相同。






使用Node.js建立server.js和products.js两个文件。在这个项目里,我们使用的mongoose是3.8.8,使用的express是4.1.1。

server.js代码:

var mongoose = require('mongoose');

var express = require('express');

var products = require('./products.js');

 

var app = express();

app.get('/list',products.getProducts);

 

var opts = { replSet: {rs_name:'mongoset'} };

var uri ='mongodb://[ cloudservice].chinacloudapp.cn:27017/travelProduct,mongodb://[cloudservice].chinacloudapp.cn:27018, mongodb://[ cloudservice].chinacloudapp.cn:27019';

mongoose.connect(uri,opts,function(err){

    console.log('connectionstatus: ' + (err ? err.message :'ok'));   

});

 

var port = process.env.port || 1337;

app.listen(port,function() {

    var db = mongoose.connection;

    db.on('error',function(err) {

        console.error('failed to connect to mongo db: ' + err.message);   

    });

    db.once('open',function() {

        console.info('succeed to connect to mongo db');   

    });

});

 

products.js代码:

var mongoose = require('mongoose');

var Schema = mongoose.Schema;

 

var ProductSchema =new Schema({

    name: String,

    city: String,

    price: String   

});

mongoose.model('Product', ProductSchema,'products');

 

exports.getProducts=function(req,res) {

    console.log('getProductscalled');

    var model = mongoose.model('Product');

    var query = model.find();

    query.exec(function(err, products) {

        console.log('find return');

        if (!err) {

            res.send(JSON.stringify(products));

        } else {

            console.log(err);

        }

    });

}  


运行结果如上图所示。至此,我们的MongoDB高可用集群已经配置完毕,且可响应外部的请求。

0 0
原创粉丝点击