美文网首页基础服务我爱编程
搭建一个MongoDB副本集系统

搭建一个MongoDB副本集系统

作者: zhou | 来源:发表于2017-08-02 18:25 被阅读166次

    在任何服务系统中,要提供系统服务高可用,必须要解决单点故障及实现故障自动转移。mongodb的副本集提供了这样的功能,副本集由多个mongodb实例组成,其中一个为主,其他为从,解决了单点故障。另外主实例无法服务时,mongodb会重新选举主实例进行故障转移。

    一、mongodb实例启动准备

    下载解压

    cd /usr/local
    wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.6.tgz
    tar -xvf mongodb-linux-x86_64-3.4.6.tgz
    mv mongodb-linux-x86_64-3.4.6  mongodb
    

    设置环境

    vim /etc/profile
    
    export MONGODB_HOME=/usr/local/mongodb
    export PATH=$MONGODB/bin:$PATH
    
    source /etc/profile
    

    由于这里搭建mongodb副本集,所以至少需要三个mongodb实例,两个数据实例,一个仲裁实例,首先创建三个数据目录

    mkdir  -p /data/mongodb1
    mkdir  -p /data/mongodb1/{log,conf}
    touch  /data/mongodb1/log/mongodb.log
    
    
    mkdir  -p /data/mongodb2
    mkdir  -p /data/mongodb2/{log,conf}
    touch  /data/mongodb2/log/mongodb.log
    
    mkdir  -p /data/mongodb3
    mkdir  -p /data/mongodb3/{log,conf}
    touch  /data/mongodb3/log/mongodb.log
    

    创建配置文件,配置文件放在/data/mongodb1/conf/目录下,文件名为mongodb.conf,配置如下:

    dbpath=/data/mongodb1
    logpath=/data/mongodb1/log/mongodb.log
    logappend=true
    noprealloc=true
    port=27011
    fork=true
    replSet=test
    

    其他两个实例配置文件内容和位置一样,修改目录和端口就可以了,其他两个实例端口分别为:27012、27013。其中,replSet参数表示副本集名,三个实例必须配置一致。

    二、启动实例

    执行下面命令启动三个实例

    mongod  -f  /data/mongodb1/conf/mongodb.conf
    mongod  -f  /data/mongodb2/conf/mongodb.conf
    mongod  -f  /data/mongodb3/conf/mongodb.conf
    

    三个实例启动成功后,不代表副本集已经搭建成功了,还需要进行副本集初始化。

    三、初始化副本集

    连接任何一个实例进行初始化

    mongo --port 27011
    
    use admin
    config={
        _id:'test',
        members:[
            {_id:1, host:'localhost:27011',priority:2},
            {_id:2, host:'localhost:27012',priority:1},
            {_id:3, host:'localhost:27013',arbiterOnly:true}
        ]
    }
    
    rs.initiate(config)
    

    上面执行成功后,可以使用rs.status()查看副本集当前状态。

    上面配置文件中,_id:'test'表示副本集名称,与前面mongodb.conf配置文件中的replSet参数配置的名称要一致。

    priority:2表示优先级,优先级越高,副本集初始化时会选举为主。arbiterOnly:true表示该实例为仲裁节点,不存储数据,只参与投票。

    四、创建管理员用户和读写用户

    连接到主实例,创建用户

    mongo --port 27011 
    
    use admin
    
    db.createUser({
        user:'dba',
        pwd:'dba',
        roles:[{role:"userAdminAnyDatabase", db:"admin"}, {role:"readWriteAnyDatabase", db:"admin"}]
    })
    
    db.createUser({
        user:'rd',
        pwd:'rd',
        roles:[{role:'readWrite', db:'test'}]
    })
    
    

    创建好后,可以使用show users查看所有创建的用户信息

    五、为副本集增加权限认证

    副本集采用keyfile文件来实现权限认证,并且副本集中的所有成员使用的keyfile必须一样。

    # 生成keyfile文件
    openssl rand -base64 90 > /data/mongodb1/conf/keyfile
    
    cp /data/mongodb1/conf/keyfile  /data/mongodb2/conf/keyfile
    cp /data/mongodb1/conf/keyfile  /data/mongodb3/conf/keyfile
    

    另外需要注意,keyfile文件权限必须是X00,也就是说,不能给group和other成员分配任何权限,否则实例无法启动。

    chmod 400 /data/mongodb1/conf/keyfile
    chmod 400 /data/mongodb2/conf/keyfile
    chmod 400 /data/mongodb3/conf/keyfile
    

    生成好keyfile之后,将keyfile写入mongodb.conf配置文件中,在mongodb.conf配置文件中增加如下配置:

    keyFile=/data/mongodb1/conf/keyfile
    

    其他实例做同样修改,重启所有实例。
    在配置文件中开启了keyFile,就不需要开启auth认证,因为开启keyFile,就默认开启了auth。

    六、验证

    连接主实例

    mongo --port 27011
    
    查看当前数据库

    发现没有权限执行,使用db.auth('dba', 'dba')进行权限认证,再次执行就可以查看了。

    认证后查看

    创建一个数据库test,然后写入一些数据。

    写入数据

    退出客户端重新连接,不认证无法进行数据库读写操作。

    重新连接

    下面使用前面创建的rd读写用户来认证,发现认证失败。这是因为,rd用户是在admin库下面创建,所以必须要到admin库下面认证,mongodb下的用户是随着库走的。

    下面连接到从实例上面,虽然用户已经认证可以了,但无法查看数据。

    从实例操作

    这是因为mongodb默认是从主节点读写数据的,副本节点上不允许读(更不能写入),但可以设置副本节点可以读,使用db.getMongo().setSlaveOk()命令就可以了。

    设置从可读

    七、PHP实现

    首先连接主实例,在test库下面创建一个读写用户

    # 登录管理员权限
    use admin
    db.auth('dba', 'dba')
    
    # 切换到test库下创建用户
    use test
    db.createUser({
        user:'test',
        pwd:'test',
        roles:[{role:'readWrite', db:'test'}]
    })
    
    创建新用户

    php代码如下:

    <?php
    
    $m = new MongoClient(
        "mongodb://test:test@192.168.99.100:27012,192.168.99.100:27011/test", 
        array(
            'connectTimeoutMS' => 100, 
            'readPreference' =>  MongoClient::RP_PRIMARY_PREFERRED,
        )
    );
    
    $db = $m->test; 
    $collection = $db->person;
    
    $collection->insert(array(
        'name' => 'li',
        'age'  => 22,
    ));
    
    $cursor = $collection->find();
    
    foreach ($cursor as $document) {
        var_dump($document);
    }
    

    执行结果

    执行结果

    最后,副本集的故障转移可以自行验证下。

    相关文章

      网友评论

        本文标题:搭建一个MongoDB副本集系统

        本文链接:https://www.haomeiwen.com/subject/cicylxtx.html