创建mongodb副本集操作实例

时间:2023-04-06 20:16:08

一:概念

相关概念及图片引用自这里

mongodb副本集: 副本集是一组服务器,其中一个是主服务器,用于处理客户请求;还有多个备份服务器,用于保存主服务器的数据副本。如果主服务器崩溃了,备份服务器自动将其中一个成员升级为新的主服务器。 由此可见副本集对于应对灾难性事件是多么的合适。以前的mongo主从模式其实就是一个单副本的应用,没有很好的扩展性和容错性。而mongodb副本集具有多个副本保证了高性能,数据的一致性,容错性,就算一个副本挂掉了还有很多副本存在,并且解决了上面第一个问题“主节点挂掉了,整个集群内会自动切换”。

创建mongodb副本集操作实例

由图可以看到客户端连接到整个副本集,不关心具体哪一台机器是否挂掉。主服务器负责整个副本集的读写,副本集定期同步数据备份,一但主节点挂掉,副本节点就会选举一个新的主服务器,这一切对于应用服务器不需要关心。我们看一下主服务器挂掉后的架构:

创建mongodb副本集操作实例

副本集中的副本节点在主节点挂掉后通过心跳机制检测到后,就会在集群内发起主节点的选举机制,自动选举一位新的主服务器。

其他关于选举等详细概念可以看这里

官方推荐的副本集机器数量为至少3个,那我们也按照这个数量配置测试。

因此先准备3台虚拟机用于测试:

系统均为:Linux Debian ,分别为:

创建mongodb副本集操作实例

已分配好的可登录用户分别是:root,user1

二:安装mongodb

以下记录在安装mongodb过程中遇到的问题:

1.在ip为84的虚拟机上,root用户没有开放远程登录权限,用root账号登录时报错:Access denied (网上查到是因为sshd的设置不允许root用户用密码远程登录的原因)

解决办法:user1用户登录后

  su        // 切换到管理员账号

  输入 nano /etc/ssh/sshd_config 回车              //nano是用记事本打开,也可以使用 vi 打开
  找到 # Authentication: LoginGraceTime 120 PermitRootLogin without passwd StrictModes yes
  把“PermitRootLogin without passwd”改成“PermitRootLogin yes”
  按“ctrl+o”保存再退出,退出后记得要重启一下才生效!

  reboot   //重启

2. root用户目录下安装mongodb

  root 登录

  cd /root    //在root目录下安装

  mkdir mongodb

  拖动 mongodb-linux-x86_64-3.0.1.tgz 到mongodb目录

  解压缩到当前目录:tar zxvf mongodb-linux-x86_64-3.0.1.tgz

3. 配置mongodb启动的配置文件 mongodb.conf

    创建mongodb副本集操作实例

解释一下参数名称:

  • dbpath: db数据文件存放位置
  • logpath:db的日志文件存放位置
  • logappend: 日志是否以追加方式写入
  • fork: 后台运行
  • port: 访问端口      //默认27017
  • noauth: 无认证访问(此处是为测试方便,请勿效仿)
  • replSet:副本集核心参数,副本集的名称,这个参数是必须的,而且必须三台机器完全一样
  • 更多参数可以根据需要添加

4. 设置环境变量

  vi ~/.bashrc     //    ~/ 表示打开当前用户目录下面的.bashrc文件
  拷贝以下设置到文件保存即可
    export MONGOHOME=/root/mongodb/mongodb-linux-x86_64-3.0.1
    export PATH=$MONGOHOME/bin:$PATH

5. 设置服务开机自启动:

  cd /etc/init.d        //进入启动项目文件夹下

  touch mongodb  创建mongodb文件,将以下内容拷贝到文件并保存

#!/bin/sh
### BEGIN INIT INFO
# Provides: mongod
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop
### END INIT INFO
# Source function library.
. /lib/lsb/init-functions
retval=0
pidfile=`ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'`
CONFIG="/root/mongodb/mongodb.conf"
PROGRAM="/root/mongodb/mongodb-linux-x86_64-3.0.1/bin/mongod"
MONGOPID=`ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'`
test -x $PROGRAM || exit 0
case "$1" in
start)
ulimit -n 3000
log_begin_msg "Starting MongoDB server"
$PROGRAM -f $CONFIG &
log_end_msg 0
;;
stop)
log_begin_msg "Stopping MongoDB server"
if [ ! -z "$MONGOPID" ]; then
kill -15 $MONGOPID
fi
log_end_msg 0
;;
status)
;;
*)
log_success_msg "Usage: /etc/init.d/mongodb {start|stop|status}"
exit 1
esac
exit 0

(在mongodb文件存在的情况下,可将mongodb的启动文件拖动到 /etc/init.d文件夹下)

   核对:启动项目位置及配置文件位置

    CONFIG="/root/mongodb/mongodb.conf"
    PROGRAM="/root/mongodb/mongodb-linux-x86_64-3.0.1/bin/mongod"
    MONGOPID=`ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'`

6. 配置好后reboot 重启系统

检测是否能进入mongo:

mongo -v  或者 mongo 命令。

 注意项:

  因为mongodb是安装在root用户下(Linux系统默认所安装的软件只能在当前用户下有使用权限,换一个用户就没有权限访问),当user用户登录后使用mongo命令时,会报错没有权限访问,这是我们需要设置user用户的访问mongodb的权限。

1:user用户登录

在user用户目录下 加入环境变量,指向mongo安装的文件夹:
vi ~/.bashrc 进入当前用户下面的.bashrc文件
  拷贝以下设置保存即可
  export MONGOHOME=/root/mongodb/mongodb-linux-x86_64-3.0.1
  export PATH=$MONGOHOME/bin:$PATH

2:mongodb的安装目录(root目录)访问权限

给mongodb的安装目录 :root目录设置访问权限(需要在root管理员用户下设置) 在root当存目录

cd /root
chmod 777 root (读写执行权限都有了)

chmod -R 777 root(文件的读写,创建文件夹等)
chmod a+x root  执行权限

设置完这两部,在user账号下,就能启动mongodb了。

如果在启动mongodb时报以下连接不上的mask错误,试试以下命令:

systemctl unmask mongodb
systemctl enable mongodb
systemctl start mongodb

3:在user用户下,判断开机启动项下面的mongodb文件是否有执行权限

  cd /etc/init.d/ 进入这个启动项目录
  ls -al mongodb 查看mongodb启动文件的权限 (./mongo) 按tab键不全 则是没有执行权限
  chmod a+x mongodb 给mongodb文件赋予执行权限   (需要在管理员权限下设置)

systemctl enable mongodb 对mongodb文件设置可用

systemctl start mongodb.service 启动服务

4: 其他可能涉及的命令:

如果系统开放了防火墙,还需要开放防火墙的端口,可以使得3台机器相互之间能访问,不会被墙掉。

列出INPUT 链所有的规则
iptables -L INPUT --line-numbers

#当然,自己不能被挡在外面,给自己开个后门
iptables -I INPUT -s 127.0.0.1 -p tcp --dport 27017 -j ACCEPT(出于业务逻辑的需要,有时还需要对服务器的公网IP授权)

iptables -I INPUT -s 172.16.9.241 -p tcp --dport 27017 -j ACCEPT
iptables -I INPUT -s 172.16.9.240 -p tcp --dport 27017 -j ACCEPT
iptables -I INPUT -s 172.16.9.85 -p tcp --dport 27017 -j ACCEPT

列出所有的服务,查看所有服务
systemctl list-units --type=service

df -h 查看磁盘空间

手动从配置文件启动服务 :mongod -config ./mongodb-3.2.18/mongodb.conf(配置文件路径)

三:设置副本集

在3个虚拟机上启动mongo服务都没有问题时,开始配置副本集。

随便选择某一台服务器做副本集初始化配置即可。

输入mongo命令,启动mongo   创建mongodb副本集操作实例

config={
_id:"testrepl",
members:[
{_id:,host:"172.16.9.241:27017"},
{_id:,host:"172.16.9.240:27017"},
{_id:,host:"172.16.9.84:27017"}]
} rs.initiate(config) ##########################
"_id": 副本集的名称
"members": 副本集的服务器列表
  "_id": 服务器的唯一ID
  "host": 服务器主机
  "priority": 是优先级,默认为1,优先级0为被动节点,不能成为活跃节点。优先级不位0则按照有大到小选出活跃节点。
  "arbiterOnly": 仲裁节点,只参与投票,不接收数据,也不能成为活跃节点。

第一次初始化时报以下错误:

replSetInitiate quorum check failed because not all proposed set members responded affirmatively: 172.16.9.85:27017 failed with Failed attempt to connect to 172.16.9.85:27017; couldn't connect to server 172.16.9.85:27017 (172.16.9.85), connection attempt failed    code:74

经查证发现root磁盘空间小了,副本集至少要求好几G空间,以用来交互数据使用。重新分配虚拟机空间后解决问题。

若初始化成功,会返回以下代码:

{
"ok" : 1
}

查看副本集状态: rs.status()  命令

创建mongodb副本集操作实例

注意事项:

1.只需要选择其中某一节点做初始化配置

2. 在副本集初始化的时候,一般都是copy不同的数据至各个结点,之后启动结点,添加至集群,之后查询状态会发现是  STARTUP2,这是因为集群初始化在同步数据,同步完数据之后,状态就变正常了

3. 在副本节点读取数据报错:
Error: error: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }

因为241为主副本集,mongodb默认是从主节点读写数据的,而副本节点上不允许读数据,因此在从服务器上需要做以下设置,需要设置副本节点可以读。

repset:SECONDARY>db.getMongo().setSlaveOk();   执行这句让副本集可以读

其实:有两种方法实现从机的查询:
第一种方法:db.getMongo().setSlaveOk();
第二种方法:rs.slaveOk();

上面两行命令即允许此连接从副本读取.

但是这种方式有一个缺点就是,下次再通过mongo进入实例的时候,查询仍然会报错,为此可以通过下列方式
vi ~/.mongorc.js
增加一行rs.slaveOk();
以后每次通过mongo命令进入都可以查询了。

可以测试当主节点挂掉,副本节点就会选举一个新的主服务器

创建mongodb副本集操作实例

创建mongodb副本集操作实例

当再次启动241服务器的mongo时,会恢复其primary身份。

到这里,副本集就已经配置完成。

对于切换日志的操作,

>use admin

> db.runCommand({logRotate:1})

参考文档1;文档2