MongoDB私人学习笔记

俗话说"好记性不如烂笔头",编程的海洋如此的浩大,养成做笔记的习惯是成功的一步!

此笔记主要是ZooKeeper3.4.9版本的笔记,并且笔记都是博主自己一字一字编写和记录,有错误的地方欢迎大家指正。


一、基础知识:

1、MongoDB的名称来源于Humongous Database,中文意思就是巨大无比的数据库,顾名思义,MongoDB就是为处理大数据而生, 以解决海量数据的存储和高效查询使用为使命。是NoSQL数据库的一种,是基于文档保存数据的形式,有C++语言编写的开源数据库系统。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成,MongoDB 文档类似于 JSON 对象,有数值、字符串、布尔值、日期、数组、对象ID等类型,字段值还可以包含其他文档,数组及文档数组。

官方网址:https://www.mongodb.com

2、MongoDB通常在如下情形下考虑使用:

1)用作操作日志的记录,例如用户在网站上的操作行为记录。

2)记录的数据是比较松散,没有统一结构的形式的数据。因为MongoDB本身存储的数据是不需要有强硬的结构化。

3)大尺寸、低价值的数据,例如日志信息、大量的消息推送记录等数据。

4)高伸缩性的场景,因为MongoDB性能高,并且非常容易扩展,有着强大的集群功能。

注意:MongoDB本身不支持事务和多表(文档)的级联,故如果有此需求的场景,不应该使用MongoDB。

3、mongodb3.2.11-linux-x86_64-rhel70-3.2.11.tgz是基于Linux readHead系统的安装文件(CentOS系统也适合使用)。mongodb-linux-x86_64-2.4.9.tgz是旧版本的安装文件,留着备用。

注意:此笔记都是基于3.2.11版本来记录的。

mongodb.conf是基本的配置文件,本身压缩包是没有创建配置文件的,需要自己去创建。

jar_lib文件夹存放的是java连接MongoDB的jar包。jar包下载地址http://central.maven.org/maven2/org/mongodb/mongo-java-driver/

4、Mongodb与传统的关系型数据的术语对应关系:

RDBMS(关系型数据库管理系统) MongoDB

数据库 数据库

表格 集合

行 文档

列 字段

表联合 嵌入文档

主键 主键 (MongoDB 提供了 key 为 _id)

5、MongoDB默认的服务端口是27017,默认的数据库文档存储路径为 /data/db,默认情况下只允许本地通过127.0.0.1地址来访问,

如果允许通过其他ip地址来访问,则需要配置bind_ip=0.0.0.0,开放通过所有地址均可访问。

6、MongoDB的特性:

(1)对于单个文档,MongoDB的操作是原子性的,即操作单个文档是数据安全的。

(2)本身不支持事务,但是可以通过组合一些命令来达到简单的事务效果,但是无法实现复杂的事务情形。

可以参考官方网站的例子,通过两阶段提交来实现简单的事务效果。

地址:https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits

(3)MongoDB默认的数据库标识是自动生成的,字段名称为_id,值为ObjectId类型,并且ObjectId内部的值是唯一的。

如果在存储数据时指定了_id字段,那么将不再自定生成。存储的格式例子:

{ "_id" : ObjectId("583c6a7a9abb612322fd08c8"), "2" : true, "a" : 1 }

{ "_id" : ObjectId("583c6be49abb612322fd08c9"), "2" : true, "a" : 1 }

{ "_id" : 123, "a" : 1 }

如果手动设置ObjectId类型,长度必须要求为24位。

(4)MongoDB的shell脚本操作使用的是JavaScript脚本语言,故拥有JavaScript语言的特性,例如区分大小写,单双引号的使用,

浮点型数值精度丢失,定制JSON对象等。

7、MongoDB的集群:

1、replica set 通过副本集的方式来达到集群的效果,但是仅仅没有负载均衡的能力。由一个主节点多个从节点的形式组成,默认所以的读写操作都在主节点上(可以设置从节点拥有读的能力,但不可以设置写操作),数据会自动同步

到从节点。当主节点宕机后,会自动选取从节点升级为主节点,接替主节点的工作,故拥有容灾备份的能力,

但是因为同一时刻只有一个主节点,所以没有负载均衡的能力。

2、sharding 通过分片区的方式来达到负载均衡的效果,但是没有容灾备份的能力。将数据进行分片,由多个服务器来分别承担分片数据,通过路由计算规则来觉得存储的数据所在的分区位置,故客户端对数据的读写操作,可能分到不同的片区由不同的服务器来处理,达到了负载均衡的能力,但是如果有个别片区的服务宕机了,那么就无法提供这一片区的数据服务,没有容灾备份的能力。

3、sharding + replica set 集合分片区和副本集的特性,将其整合在一起,使得既有容灾备份的效果,又有负载均衡的能力。相当于将sharding分片区进行分组,每个分片区组都存储完整的数据,一个组就相当于一个副本集,建立多个组就相当于有多个副本集,当一个组的sharding分片区有服务器宕机时,其他组的sharding分片区服务器能马上代替其工作。

附加:主从节点的数据复制是根据oplog(operation log)操作日志来同步的,从节点读取主节点的oplog来更新自己的数据库。oplog达到指定大小时,会滚动到文件头重新记录,覆盖掉以前的操作日志,故oplog的空间不能过于小,导致从节点同步数据丢失。

8、mongodb自带有命令形式的客户端,可以通过mongo命令登录进行操作mongodb。如果需要图形界面来操作,则需要额外安装图形界面的应用来支持,或者使用图形工具软件来连接。常用的有如下几款:

MongoDBCompass(官方版):地址为 https://www.mongodb.com/try/download/compass?jmp=docs

Robo 3T(原名:Robomongo)

mongobooster

二、使用笔记:

1、最简单的形式启动服务:

解压mongodb3.2.11-linux-x86_64-rhel70-3.2.11.tgz后,进入解压后的bin目录,执行如下命令便可以简单的启动MongoDB服务:

./mongod --dbpath=/usr/user/mongodb-linux-x86_64-rhel70-3.2.11/data/db

注意:--dbpath是指定数据库路径,必须要先创建好该路径目录。

MongoDB的数据库文档默认是存储在/data/db目录下的,如果没有预先创建好该目录会启动报错。

注意是mongod命令,不是mongo命令,bin目录下有两个名字非常相近的命令,但功能是完全不同的。

附加:MongoDB关闭服务的方式:

(1)执行mongod命令来关闭 ./mongod --shutdown --dbpath=/usr/user/mongodb-linux-x86_64-rhel70-3.2.11/data/db

必须要指定好正确的db路径,因为停止服务时要移除数据库的锁标识。

(2)进入mongo的shell操作工具(执行命令./mongo 127.0.0.1:27021来进入操作工作),切换到admin数据库来停止服务。

use admin

db.shutdownServer()

(3)查询进程进行kill掉。

ps -ef|grep mongo

kill 进程号

2、进入bin目录,可以通过 ./mongod -h 来查看更多的可执行参数,"mongod命令可以使用的参数列表.txt"就是可以执行的参数列表。

3、通过指定配置文件来启动服务:

进入解压的目录,执行命令: ./bin/mongod --config mongodb.conf

其中mongodb.conf是自己创建的配置文件(注意文件路径),其中最基本的配置内容有:

#数据库路径

dbpath=/usr/local/mongodb/db

#日志路径

logpath=/usr/local/mongodb/logs/mongodb.log

#以追加方式写入日志

logappend=true

#默认的服务端口

port=27017

#后台形式运行服务,使用此形式必须要配置日志路径

fork=true

#禁用http查看界面。默认就是关闭的。

nohttpinterface=true

4、MongoDB的http查看界面,是通过web形式展现的,默认是没开启此功能的,需要配置 nohttpinterface=false

如果想让web界面提供更多的功能,需要在启动时指定 -rest参数,如: ./bin/mongod --config mongodb.conf -rest

本地启动该服务后,可以在web查看到所有的命令 http://localhost:28017/_commands

5、常用命令:

(1)普通命令:

show dbs 查看所有的数据库

use mydb 使用mydb数据库

show collections 查看当前数据库下的所有集合(表)

db 当前数据库引用,对数据库的操作都需要db开头

db.stats() 查看当前数据库的状态

db.version() 使用的MongoDB版本号。

db.getMongo() 查看当前连接数据库的地址。

db.mydb.isCapped() 查看当前集合是否固定长度的集合。

db.createCollection("mydb") 创建集合,默认创建的是非固定长度的集合。

db.createCollection("mydb",{capped:true,size:10000,max:1000}) 创建固定长度的集合,size表示集合大小,max表示文档数。

db.runCommand({"convertToCapped":"mydb",size:10000}) 将已存在的mydb集合转换为固定长度的集合。

(2)删除命令

db.dropDatabase() 删除当前数据库。

db.col_name.drop() 删除集合。col_name是集合名词。

db.collection.remove(<query>,{justOne: <boolean>,writeConcern: <number>})

query :(可选)删除的文档的条件。

justOne : (可选)如果设为 true 或 1,则只删除一个文档。默认为false,即删除所有符合条件的文档。

writeConcern :(可选)抛出异常的级别。有-1,0,1,2级别,默认级别是1,即如果写入失败则立刻返回错误。

例子:

删除mycoll集合下的所有数据。

db.mycoll.remove({})

删除标题为mongo的所有数据。

db.mycoll.remove({"title":"mongo"})

删除标题为mongo的第一条数据。

db.mycoll.remove({"title":"mongo"},true)

(3)新增命令

db.mycoll.insert({'key01':'val01','key02':'val02'})

插入数据到mycoll集合中,如果该集合不存在,则会新建一个。

db.mycoll.save({'_id':ObjectId("56064f89ade2f21f36b03136"),'key01':'val01','key02':'val02'})

保存数据。如果有_id=56064f89ade2f21f36b03136的数据,即数据已经存在,则直接进行替换,否则就插入新的数据。

(4)更新命令

db.collection.update(<query>,<update>,{upsert: <boolean>,multi: <boolean>,writeConcern: <number>})

query : update的查询条件,类似sql update查询内where后面的。如果需要更新所有数据,则直接传入{}空json对象。

update : update的对象和一些更新的操作符(如,inc...)等,也可以理解为sql update查询内set后面的

upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。

multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。

writeConcern :可选,抛出异常的级别。

例子:

替换title为mongo的第一条数据,注意是替换形式,既把title为mongo的记录直接就变为title:"newMongoDB",states:"ok"。

db.mycoll.update({title:"mongo"},{title:"newMongoDB",states:"ok"},false)

更新title为mongo的第一条数据,使用了$set操作符,注意不是替换,是局部更新。

db.mycoll.update({title:"mongo"},{$set:{title:"newMongoDB",states:"ok"}})

更新title为mongo的所有数据。ps:如果该数据没有states字段,那么就好新增此字段,如果有就直接更新。

db.mycoll.update({title:"mongo"},{$set:{title:"newMongoDB",states:"ok"}},false,true)

更新title为mongo的的数据,如果不存在任何的记录,则插入更新的数据。

db.mycoll.update({title:"mongo"},{$set:{title:"newMongoDB",states:"ok"}},true,false)

更新所有的数据,所有money字段的值+1,如果money字段不存在,则新增money字段,值设置为1。

db.col.update({},{$inc:{"money":1}},{multi:true})

注意:在更新数据时,对于已经存在的字段则进行更新操作,如果该数据没有更新的字段,则会新增此字段。

(5)查询命令

db.mycoll.find() 查询mycoll集合的所有文档。

db.mycoll.findOne() 查询当前mycoll集合的文档,只获取第一条数据,并美化后才输出。

db.mycoll.find().pretty() 查询mycoll集合的所有文档,并美化后才输出。

db.mycoll.find().limit(<num>) 限制条数查询。num是限制的条数,如果没输入任何数值,则默认查询全部。

db.mycoll.find().skip(<num>) 对查询结果跳过指定的条数。num是限制的条数,如果没输入任何数值,则默认不跳过任何条数。

ps:附加命令pretty、limit等命令,是可以组合在一起使用的。

db.col.find().sort({<key>:-1}) 查询结果进行排序。key是排序字段,值-1表示降序,1表升序。可以使用多个字段按顺序排序。

ps:如果数据没有该排序字段,则认为是属于最小值,降序中排在最后。

find()和findOne()都可以带条件查询,查询的条件:

AND条件: db.mycoll.find({title:"mongo",state:"ok"}) 查询title="mongo" AND state="ok"的数据。

OR条件: db.mycoll.find({$or:[{title:"mongo"},{state:"ok"}]}) 查询title="mongo" OR state="ok"的数据。

IN关键字:db.mycoll.find({_id:{$in:[1,2,3,4]}}) 查询_id为1,2,3,4中任何一个数值的数据。

等于: {<key>:<value>} db.col.find({"by":"菜鸟教程"}) 相当于where by = '菜鸟教程'

等于写法2: {<key>:{eq:\}} db.col.find({"by":{eq:"mon"}}) 相当于where by = 'mon'

小于: {<key>:{lt:\}} db.col.find({"likes":{lt:50}}) 相当于where likes < 50

小于或等于: {<key>:{lte:\}} db.col.find({"likes":{lte:50}}) 相当于where likes <= 50

大于: {<key>:{gt:\}} db.col.find({"likes":{gt:50}}) 相当于where likes > 50

大于或等于: {<key>:{gte:\}} db.col.find({"likes":{gte:50}}) 相当于where likes >= 50

不等于: {<key>:{ne:\}} db.col.find({"likes":{ne:50}}) 相当于where likes != 50

类型查询:{<key>:{type:\}} db.col.find({"likes":{type:2}}) 查询likes字段值类型是String字符串类型的,类型详见附加。

正则表达式:{<key>:{$type:/<value>/}} db.col.find({"name":/^china/i}) 查询name名称已china开头并且不区分大小写的数据。

正则表达式写法2: db.col.find({"name":{regex:"\^china",options:"$i"}}) 查询name名称已china开头并且不区分大小写的数据。

其他例子:

查询 title="mongo" AND (state="OK" OR date=ISODate("2016-11-29T02:48:10.115Z"))的数据

db.mycoll.find({title:"mongo",$or:[{state:"ok"},{date:ISODate("2016-11-29T02:48:10.115Z")}]})

查询 (title="mongo" AND state="OK") OR (date=ISODate("2016-11-29T02:48:10.115Z"))的数据

db.mycoll.find({$or:[{title:"mongo",state:"ok"},{date:ISODate("2016-11-29T02:48:10.115Z")}]})

find()和findOne()可以指定输出的字段:

查询标题为mongo的数据,并且只显示title和falg字段值,其中_id是默认显示的。

db.mycoll.find({"title":"mongo"},{title:1,flag:1})

查询第一条数据,并且只显示title和falg字段值,_id不显示。

db.mycoll.findOne({},{_id:0,title:1,flag:1})

(6)索引命令

db.collection.ensureIndex({<key>:-1}}, <option>) 给集合创建索引。当数据量大时,必须创建索引才能加快查询速度,注意默认_id没有加入索引的。

例子:

给mycol的title字段创建升序索引,给description字段创建降序索引,相当于传统数据库的联合索引,注意字段顺序。

db.mycoll.ensureIndex({"title":1,"description":-1})

给mycol的title字段创建升序索引,并且通过后台运行的方式来创建。ps:创建索引时会阻塞其他数据库操作,可通过后台方式来防止此情况。

db.mycoll.ensureIndex({open: 1}, {background: true})

给mycol的title字段创建升序索引,后台方式运行,并且要求title是唯一索引。dropDups表示相同的title记录是否删除,默认不删除。

db.mycoll.ensureIndex({title: 1}, {background: true,unique:true,dropDups:false})

提示:如果查询的数据字段都是同一个索引的一部分,那么直接是从索引中获取查询结果,而无需再查找文档,速度将非常的快。

例如:创建索引db.users.ensureIndex({gender:1,user_name:1}) ,然后查询db.users.find({gender:"M"},{user_name:1,_id:0})。

注意:集合中索引不能超过64个,索引名的长度不能超过125个字符,一个复合索引最多可以有31个字段。可以通过explain()来查看查询是否使用了索引。

(7)聚合命令

db.collection.aggregate(<option>) 聚合操作主要用于处理数据(例如统计、计算平均值等),并返回处理结果。

例子:

根据money字段进行分组,并统计出各分组的总金额。ps:$group操作符,_id字段是必须要写的,表示分组字段。

db.mycol.aggregate({group:{_id:"money",total:{sum:"money"}}})

先用match进行数据过滤,要求金额必须大于21小于等于60,然后对其数据进行分组,统计出总数量。

注意_id:null表示所以数据合并为一个分组。此处使用了MongoDB的概念,对match操作后的数据给group进一步操作。

db.col.aggregate([{match:{money:{gt:21,lte:60}}},{group:{_id:null,count:{$sum:1}}}])

对文档数据输出进行定制。$project操作符就是修改输出的数据。只输出_id,money,flag字段的数据,

其余字段一律不输出,并且flag的数据来源于state字段,相当于给输出字段修改名称。

db.col.aggregate({project:{_id:1,money:1,flag:"state"}})

6、特殊的命令详解:

(1)insert和save的区别:

insert 是直接插入数据,如果主键已经存在,则会报_id_ dup key主键重复的异常,导致插入失败。

save 也是插入数据,但是如果主键已经存在,则是直接进行更新。

(2)save和update的区别:

save 如果数据存在,则是直接进行替换,而非局部更新。

update 如果没有指定$set操作符,则和svae功能一样,是属于直接替换。

如果使用了$set操作符,则只对指定的字段进行更新,属于局部更新,并且可以同时更新多条数据。

7、MongoDB的备份与恢复:

(1)备份操作:

mongodump -h dbhost -d dbname -o dbdirectory

-h:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017

-d:需要备份的数据库实例,例如:test

-o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,

系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

(2)恢复操作:

mongorestore -h dbhost -d dbname --directoryperdb dbdirectory

-h:MongoDB所在服务器地址

-d:需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2

--directoryperdb:备份数据所在位置,例如:c:\data\dump\test。

--drop:恢复的时候,先删除当前数据,然后恢复备份的数据。慎用!

8、MongoDB自带的监控工具:

(1)状态监测工具:

mongostat

(2)操作耗时监测工具:

mongotop <num>

<num> 是监测间隔,表示多少秒一次获取监测数据,默认1秒。

9、默认情况下,mongodb是不需要验证的,如果要开启验证,则需要在配置文件中设置并且创建账号密码,步骤如下:

(1)进入其中一个数据库(通常是使用默认的admin库):use admin

(2)创建用户:

db.createUser({user:"admin",pwd:"tcljr@*2020",roles:["root"]})

db.createUser({user:"tcljr",pwd:"tcljr@*2020",roles:["readWrite"]})

db.createUser({user:"riskmg",pwd:"tcljr@*2020",roles:[{role:"readWrite",db:"sit-riskmg"}]})

说明:如果没有指定db,则默认是使用当前数据库名的集合。如果需要给不同数据库创建用户,需要切换到不同数据库后再创建。

(3)在配置文件中,将auth=true,然后重启mongodb服务。

(4)通过moongodb的shell客户端进入 ./bin/mongo 10.0.112.35:27017

(5)切换到对应数据库,然后进行验证:

use admin

db.auth("admin","tcljr@*2020")

注意:必须要先选择数据库,如果选择的数据库不正确,即使账号密码正确都会认证失败。

说明:如果不进行验证,则是无法查看数据库和数据的,例如show dbs会不显示任何数据库。

(6)如果是有使用副本集群,如果开启了auth=true认证,则必须要配置认证文件keyFile,否则集群节点之间无法通讯。

keyFile文件可通过 openssl rand -base64 1024 > mongodb.key 来生成,生成的字符长度如果超过1024,则可以手动删除一部分。

三、java使用MongoDB的方式:

1、http://central.maven.org/maven2/org/mongodb/mongo-java-driver/

2、SpringBoot整合mongodb:

(1)增加maven依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-mongodb</artifactId>

</dependency>

(2)配置application.yml文件:

spring:

data:

#mongodb配置(集群配置(也可以用于单机))

mongodb:

uri: mongodb://10.0.112.35:27017,10.0.112.35:27018,10.0.112.36:27017,10.0.112.36:27018,10.0.112.37:27017/riskmg

#mongodb配置(单机配置)

(3)直接注入MongoTemplate依赖即可使用:

@Resource

private MongoTemplate mongoTemplate;

/*************************************************************附加*******************************************************/

1、MongoDB 中可以使用的类型如下表所示:

类型 数字

Double 1

String 2

Object 3

Array 4

Binary data 5

Undefined 6 已废弃。

Object id 7

Boolean 8

Date 9

Null 10

Regular Expression 11

JavaScript 13

Symbol 14

JavaScript (with scope) 15

32-bit integer 16

Timestamp 17

64-bit integer 18

Min key 255 Query with -1.

Max key 127

2、原子操作常用命令

$set

用来指定一个键并更新键值,若键不存在并创建。

{ $set : { field : value } }

$unset

用来删除一个键。

{ $unset : { field : 1} }

$inc

$inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。

{ $inc : { field : value } }

$push

用法:

{ $push : { field : value } }

把value追加到field里面去,field一定要是数组类型才行,如果field不存在,会新增一个数组类型加进去。

$pushAll

同$push,只是一次可以追加多个值到一个数组字段内。

{ $pushAll : { field : value_array } }

$pull

从数组field内删除一个等于value值。

{ $pull : { field : _value } }

$addToSet

增加一个值到数组内,而且只有当这个值不在数组内才增加。

$pop

删除数组的第一个或最后一个元素

{ $pop : { field : 1 } }

$rename

修改字段名称

{ $rename : { old_field_name : new_field_name } }

$bit

位操作,integer类型

{$bit : { field : {and : 5}}}

3、原子操作数据模型

考虑下面的例子,图书馆的书籍及结账信息。

实例说明了在一个相同的文档中如何确保嵌入字段关联原子操作(update:更新)的字段是同步的。

book = {

_id: 123456789,

title: "MongoDB: The Definitive Guide",

author: [ "Kristina Chodorow", "Mike Dirolf" ],

published_date: ISODate("2010-09-24"),

pages: 216,

language: "English",

publisher_id: "oreilly",

available: 3,

checkout: [ { by: "joe", date: ISODate("2012-10-15") } ]

}

你可以使用 db.collection.findAndModify() 方法来判断书籍是否可结算并更新新的结算信息。

在同一个文档中嵌入的 available 和 checkout 字段来确保这些字段是同步更新的:

db.books.findAndModify ( {

query: {

_id: 123456789,

available: { $gt: 0 }

},

update: {

$inc: { available: -1 },

$push: { checkout: { by: "abc", date: new Date() } }

}

} )

4、ObjectId类型

(1)ObjectId 是一个12字节 BSON 类型数据,有以下格式:

前4个字节表示时间戳

接下来的3个字节是机器标识码

紧接的两个字节由进程id组成(PID)

最后三个字节是随机数。

(2) 手动创建ObjectId对象:myobj = new ObjectId() 或者myobj = ObjectId()

(3)ObjectId的可操作api:

ObjectId("5349b4ddd2781d08c09890f4").getTimestamp() 获取对象时间戳。

new ObjectId().str 获取对象标识的字符串格式。

5、实现_id的自增长

MongoDB的主键id不支持数值自增长的形式,可以通过编写自定义函数来实现。

//自定义增长的函数

function getNextSequenceValue(sequenceName){

var sequenceDocument = db.counters.findAndModify(

{

query:{_id: sequenceName },

update: {$inc:{sequence_value:1}},

new:true //new 表示返回个性化后的文档

});

return sequenceDocument.sequence_value;

}

//使用方式

db.mycol.insert({"_id":getNextSequenceValue("productid"), "product_name":"Samsung S3","category":"mobiles"})

6、MongoDB的副本集配置:

步骤一:创建多个数据库目录。

进入/usr/user/mongodb-linux-x86_64-rhel70-3.2.11/目录,创建dbs目录,然后进入dbs目录,

创建db01、db02、db03、arb目录。

步骤二:启动MongoDB服务。

./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/db01 --port 27017 --replSet myrs

./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/db02 --port 27018 --replSet myrs

./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/db03 --port 27019 --replSet myrs

./bin/mongod --dbpath /usr/user/mongodb-linux-x86_64-rhel70-3.2.11/dbs/arb --port 30000 --replSet myrs

步骤三:使用mongo的shell登录到其中一个服务端。

./bin/mongo 10.17.2.61:27017

步骤四:在mongo的shell中初始化副本集。

//创建配置对象。注意host主机地址切勿填写为localhost本地地址,将会导致java客户端连接出异常。

var config={_id:"myrs",members:[{_id:1,host:"10.17.2.61:27017"},{_id:2,host:"10.17.2.61:27018"},{_id:3,host:"10.17.2.61:27019"}]}

//初始化。注意只能初始化一次,mongodb会将初始化后的数据写入文件,下次重新启动服务不用再初始化。

rs.initiate(config)

注意:

rs开头表示是对replica set 副本集的操作。initiate方法只运行初始化一次。

如果想修改config配置,可以使用rs.reconfig(config:{force:true})来强制更改配置。

执行完配置后,可以通过rs.config()来看配置情况,rs.status()来查看集群状态。

步骤五:添加arbiter仲裁节点。

arbiter仲裁节点不备份数据,只是再当主服务器宕机时,有仲裁节点来选定从节点哪个变为主节点。

如果没有仲裁节点,从节点将自己从内部选取,故可以不需要仲裁节点,但要求节点数必须是奇数,如果是偶数则必须要仲裁节点。

rs.addArb("10.17.2.61:30000")

提示:如果需要动态的添加节点或删除节点,可以使用rs.add("host:port")命令来添加副本集节点,

删除从节点或者仲裁节点使用rs.remove("host:port")。

步骤六:指定一个主节点。

默认情况下,当前所以节点都是从节点,可以使用rs.status()来查看状态。

登录需要指定为主节点的mongo的shell客户端,执行命令rs.isMaster() 来提升当前节点为主节点。

提示:默认从节点是不可以做读写的,可以设置为运行从节点进行读操作,但写操作是一直都禁止的。

登录从节点的mongo的shell客户端,执行命令 rs.slaveOk(),注意只是针对当前会话的设置,

如果退出重进,需要重新执行这个命令。

步骤七:测试。

可以将主节点的进程kill掉,可以看到从节点有一个自动提升为主节点。

提升:当有节点宕机后,其他节点还是会定时的发布心跳来检测节点是否恢复,会打印大量的日志信息,需要处理好日志级别。

步骤八:java客户端连接副本集。

Builder builder = MongoClientOptions.builder();

builder.serverSelectionTimeout(3000000);

builder.requiredReplicaSetName("myrs");

builder.readConcern(readCon);

builder.writeConcern(writeCon);

MongoClientOptions op = builder.build();

/*多个副本集节点,指定多个ip地址。必须有一一列举副本集节点的ip,

*MongoClient客户端之后在指定ip的副本集读取和操作数据,如果没有指定,即使他也是副本集的一个,也不会拿取数据。

*下面的ip中,即使有一个ip的服务宕机了,也不影响操作,可以继续提供服务。

*/

List<ServerAddress> list = new ArrayList<ServerAddress>();

list.add(new ServerAddress("10.17.2.61", 27017));

list.add(new ServerAddress("10.17.2.61", 27018));

list.add(new ServerAddress("10.17.2.61", 27019));

list.add(new ServerAddress("10.17.2.61", 30000));

MongoClient client = new MongoClient(list, op);

相关推荐
好奇的菜鸟1 小时前
如何在IntelliJ IDEA中设置数据库连接全局共享
java·数据库·intellij-idea
巴伦是只猫1 小时前
【机器学习笔记Ⅰ】13 正则化代价函数
人工智能·笔记·机器学习
DuelCode2 小时前
Windows VMWare Centos Docker部署Springboot 应用实现文件上传返回文件http链接
java·spring boot·mysql·nginx·docker·centos·mybatis
优创学社22 小时前
基于springboot的社区生鲜团购系统
java·spring boot·后端
好好研究2 小时前
学习栈和队列的插入和删除操作
数据结构·学习
幽络源小助理2 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
猴哥源码2 小时前
基于Java+springboot 的车险理赔信息管理系统
java·spring boot
YuTaoShao3 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展
新中地GIS开发老师3 小时前
新发布:26考研院校和专业大纲
学习·考研·arcgis·大学生·遥感·gis开发·地理信息科学
Dcs3 小时前
超强推理不止“大”——手把手教你部署 Mistral Small 3.2 24B 大模型
java