1. mongodb 介绍
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库。
支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
1.1、Mongodb基本结构
MongoDB的逻辑结构是一种层次结构,主要由:文档(Document)、集合(Collection)、数据库(database)这三部分组成,逻辑结构是面向用户的,用户使用MongoDB开发应用程序使用的就是逻辑结构。
文档:文档(Document)是MongodDB中的核心概念,他是MongoDB逻辑存储的最小基本单元
集合:多个文档组成的集合
数据库:多个集合组成的数据库
MongoDb
关系型数据库Mysql
文档(document)
行(row)
集合(collections)
表(table)
数据库(databases)
数据库(databases)
文档,集合,数据库之间的关系如下图所示
1.2、Mongodb 相关特性
事务支持 MongoDB 目前只支持单文档事务,需要复杂事务支持的场景暂时不适合
灵活的文档模型 JSON 格式存储最接近真实对象模型,对开发者友好,方便快速开发迭代
高可用复制集 满足数据高可靠、服务高可用的需求,运维简单,故障自动切换
可扩展分片集群 海量数据存储,服务能力水平扩展
高性能 mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求
强大的索引支持 地理位置索引可用于构建 各种 O2O 应用、文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求
Gridfs 解决文件存储的需求
aggregation & mapreduce 解决数据分析场景需求,用户可以自己写查询语句或脚本,将请求都分发到 MongoDB 上完成
1.3、Mongodb 适用场景
-- 来自mongo官方技术分享
应用不需要事务及复杂 join 支持 必须 Yes
新应用,需求会变,数据模型无法确定,想快速迭代开发 ?
应用需要2000-3000以上的读写QPS(更高也可以) ?
应用需要TB甚至 PB 级别数据存储 ?
应用发展迅速,需要能快速水平扩展 ?
应用要求存储的数据不丢失 ?
应用需要99.999%高可用 ?
应用需要大量的地理位置查询、文本查询 ?
如果上述有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择 MongoDB 绝不会后悔。
应用案例:
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
视频直播,使用 MongoDB 存储用户信息、礼物信息等
不适用场景:
高度事务性,强一致性业务系统(银行,证券等) ,传统商业智能应用, 极为复制的业务逻辑查询
2. mongodb 搭建副本集群
2.1 三种集群模式介绍
mongoDB集群模式主要有主从(master/slaves),副本集(replication),和分片(sharding)。
2.1.1 主从模式(master/slave mode)
主从是所有集群模式中最简单的,如下图所示,由一主一从或一主多从组成。
主从模式是早期系统设计中最常见的,实现数据备份的同时,将读写分离,降低数据库的压力。
主从模式下,master节点出现故障的时候,需要手动恢复,已不再推荐使用
主从模式由两个角色组成:
master: 提供读写功能
slave: 提供数据备份和读功能
2.1.2 副本集模式(replication mode)
如下图所示,副本集由一组mongo实例组成,提供了数据冗余与高可用性。相对于主从模式,副本集模式可以在主节点挂掉的时候通过选举算法自动选举出新的主节点,保证服务的可用性。
副本集模式的缺点是每个节点都要存储一份完整的数据,当存储数据量越来越大的时候,只能通过扩大每一个节点的容量来实现扩容
副本集模式由三个角色组成:
primary: 主节点,对应的master/slave模式的master。主节点是唯一能够接收写请求的节点。一旦主节点不可用,会选出新的主节点。
secondaries: 从节点,对应的master/slave模式的slave。提供数据备份和读功能,并且能在主节点挂掉的时候被选举为新的主节点。
arbiter: 投票节点或者叫仲裁节点。该角色是可选的,所以图上也没有画出来。
投票节点其本身并不包含数据集,也无法被升级为主节点,但是,一旦当前的主节点不可用时,投票节点就会参与到新的主节点选举的投票中。
2.1.3 分片模式(sharding mode)
在副本集模式下,当数据量越来越大时,只能通过把节点的容量(升级服务器的硬件)不断的扩大来实现扩容,这种垂直扩容的方式容易达到极限(scale up),并且成本高,于是有了分片模式。
分片模式下,可以将数据拆分成多个数据块,存储在不同的节点上。当数据量越来越大的时候,可以通过添加分片来实现扩容。
如图所示,该模式有N个路由节点,N个配置节点,和N个数据节点,每个角色的作用如下:
ruoter: 路由节点。客户端的请求发到router,由router向config查询数据的元信息,然后将查询与写入请求分发到shard。
config: 配置节点。该节点的作用是记录对数据分片的规则,存储所有数据库元信息(路由、分片)的配置。
shard: 数据节点,真正存储数据的地方。
2.2 搭建副本集
环境准备:一台amaz2服务器
集群模式:1主 + 1从 + 1仲裁
1. mongo 副本集搭建过程
# 下载mongo 安装包
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.4.6.tgz
# 解压安装包
tar -zxvf mongodb-linux-x86_64-amazon-3.4.6.tgz
# 移动目录
mv mongodb-linux-x86_64-amazon-3.4.6/ /usr/local/mongodb
# 创建mongodb 所需的工作目录
cd /usr/local/mongodb
mkdir -p mongo1/{data1/db,log1} mongo2/{data2/db,log2} mongo3/{data3/db,log3} config
# 配置mongodb config 文件
# mongo1 配置文件
vim config/monogd1.conf
dbpath = /usr/local/mongodb1/data1/db # 指定数据库路径
logpath = /usr/local/mongodb1/log1/mongod.log # 指定mongodb日志文件
logappend = true # 使用追加的方式写日志
port = 27017 #设置端口号为27017
fork = true #设置以守护进程的方式启动
mongodreplSet = test #设置副本集的名字为test,同一副本集群的replSet名称必需相同
# mongo2 配置文件
vim config/monogd2.conf
dbpath = /usr/local/mongodb2/data2/db # 指定数据库路径
logpath = /usr/local/mongodb2/log2/mongod.log # 指定mongodb日志文件
logappend = true # 使用追加的方式写日志
port = 27018 #设置端口号为27017
fork = true #设置以守护进程的方式启动
mongodreplSet = test #设置副本集的名字为test,同一副本集群的replSet名称必需相同
# mongo3 配置文件
vim config/monogd3.conf
dbpath = /usr/local/mongodb3/data3/db # 指定数据库路径
logpath = /usr/local/mongodb3/log3/mongod.log # 指定mongodb日志文件
logappend = true # 使用追加的方式写日志
port = 27019 #设置端口号为27017
fork = true #设置以守护进程的方式启动
mongodreplSet = test #设置副本集的名字为test,同一副本集群的replSet名称必需相同
# 启动分别启动mongo实例
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/config/monogd1.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/config/monogd2.conf
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/config/monogd3.conf
# 登录mongo1
mongo 10.1.1.56:27017
其他的mong0实例 更换端口即可
# 初始化mongo 副本集群,如果mongo 已有数据,只能在有数据的实例上初始化,如果没有数据,任意一台实例即可
cd /usr/local/mongodb
./bin/mongo
use admin
config = {
"_id":"myrs",
"members":[
{"_id":0,"host":"10.1.1.56:27017"},
{"_id":1,"host":"10.1.1.56:27018"},
{"_id":2,"host":"10.1.1.56:27019",arbiterOnly:true}
]}
rs.initiate(config); #初始化配置
# 查看集群状态:
rs.status();
# 设置副本集为只读
test:SECONDARY> db.getMongo().setSlaveOk();
# 在主实例上插入数据测试复制功能
此时10.1.1.56:27017是主节点,用mongo来登录shell
mongo 10.1.1.56:27017
use l2c #创建l2c数据库
db.test.insert(
{
"cursor" : "BtreeCursor x_1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"nscannedObjectsAllPlans" : 0,
"nscannedAllPlans" : 0,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"x" : [
[
-Infinity,
0
]
]
},
"server" : "macleandeMacBook-Pro.local:27017",
"filterSet" : false
}); #插入测试数据
# 在其他只读节点 查看是否有数据
db.test.find();
# 在主节点关机测试集群切换情况,新主节点是否切换到其他副本集中
test RIMARY> use admin
test RIMARY> db.shutdownServer() |