前言
本篇文章会通过在MongoDB中的主从集群,以及集群之间同步机制和选举,以及如何达到读写分离、CAP分布式理论在mongodb中如何实现,如何使用主从集群等方面去详细解释mongodb应对高并发,分片集群中的概念 ,如何使用分片集群等多方面去解析应对海量数据的解决方法。
主从集群
首先mongodb 集群 :分为主从集群、和分片集群 ,部署多个MongoDB,集群。分为有状态集群、无状态集群。 从是否存放数据来区分。
无状态集群
无需存放数据,所有的访问的数据,都在数据库上的。 并且不用管数据是否一致,数据安全等。
有状态集群(衍生出主从节点)
数据存在集群本身的,数据的状态,需要与其他节点进行交互,维护状态。而要解决问题的方案也就是主从集群,master 用来处理写 操作 从节点 ,并且 主节点挂点时,会读从节点上的数据。一旦遇到这个问题就会出现CAP分布式理论。数据一致性理论。 也是主从集群基础起来的分片集群。
概念
主从集群由一组mongod维护相同数据集的实例。一个副本集包含多个数据承载节点和一个仲裁器节点(可选)。在数据承载节点中,只有一个成员被视为主要节点,而其他节点则被视为次节点。
主从复制集群提供冗余并提高数据可用性。使用不同数据库服务器上的多个数据副本,复制可提供一定程度的容错能力,以防止丢失单个数据库服务器。
其中会涉及到 heartbeat心跳检测,来保证应用之间是否正常。
集群同步机制和选举
同步机制Oplog 以及 心跳机制 选举机制 副本回滚 这都是 在主从集群 需要考虑到的事情
数据进行回滚。 从CAP出发 保证 A 这都是 在 mongodb中需要涉及到的。
主从集群由一组mongod维护相同数据集的实例。一个副本集包含多个数据承载节点和一个仲裁器节点(可 选)。在数据承载节点中,只有一个成员被视为主要节点,而其他节点则被视为次节点。
主从复制集群提供冗余并提高数据可用性。使用不同数据库服务器上的多个数据副本,复制可提供一定程度的容错能力,以防止丢失单个数据库服务器。
同步机制Oplog
在所有节点上 有 local.oplog.rs集合 ,默认硬盘5%
如果写并发非常大,超过预定大小,怎么处理?
总的来说 这个 oplog上是个圆环。
oplogSizeMB,考虑并发大小来定义
通过下面的指令指定同步方式
use admin
db.adminCommand({replSetSyncFrom:"ip:port"})
指定来同步方式。
心跳机制
默认2s,超过认为不可用
settings.heartbeatIntervalMillis
并在主节点挂了过后,也有自己的一套选举机制
主节点与其他次节点,electionTimeoutMillis,默认10s 用大多数机制:n/2+1=3/2+1=2
vote:0 表示不参加投票选举,只作为负载
priority: 0-1000, 数值越高,具有优先权成为主节点
当主节点不可用,则选举符合要求的次节点为主节点 如果副本集成员数为偶数,添加仲裁器来进行选举主节点。
仲裁器是mongod进程,但不维护数据集,通过响应其他副本集成员的心跳和选举请求来维护集群中的仲裁机制。
仲裁节点的角色不会变化,而主节点可降级并成为一个次节点,一个次节点选举过程中可能成为主节点
大多数机制
大多数机制下,是不会出现脑裂的。
n/2+1=4/2+1=3
一旦出现 断开的场景,另外两台是不能写入的。 不能选取主节点
偶数个节点是为了解决什么问 题?推荐使用奇数个?
为了避免,机房,网段分区,出现网络不通的情况,导致整个服 务不可用解决高可用的问题
误解:
节省资源、为了防止出现脑裂
读写分离
默认情况下,客户端从主节点读取数据;客户端可以指定读取首选项,以将读取操作发送到次节点。
集群搭建
构建集群
通过命令方式
配置
集群的三个节点通过下面的命令方式启动。
# 创建备用目录
sudo mkdir -p /mongodb/data01 /mongodb/data02 /mongodb/data03
启动集群成员
# 第一个节点 sudo mongod --replSet "rs1" --bind_ip 0.0.0.0 --dbpath /mongodb/data01 --port 28018 --oplogSize 128
# 第二个节点
sudo mongod --replSet "rs1" --bind_ip 0.0.0.0 --dbpath /mongodb/data02 --port 28019 --oplogSize 128
# 第三个节点
sudo mongod --replSet "rs1" --bind_ip 0.0.0.0 --dbpath /mongodb/data03 --port 28020 --oplogSize 128
- --replSet用来指定同一个集群中的集群名称,集群成员通过集群名字来找到组织。
- --bind_ip表示对集群成员的ip地址进行开放,集群成员之间需要网络通讯,多个地址用逗号分隔。 这里 我们用0.0.0.0来允许所有地址访问,实际环境不建议这么做。
- --dbpath指定数据目录的路径
- --port同一台机器上的伪集群,需要用不同的端口号来启动
- --oplogSize限制每个mongod实例使用的磁盘空间
初始化集群成员
进入到前面的任意端口 shell 窗口,比如 28019
sudo mongo --port 28019
在 shell 界面中,使用下面的配置来启动
这样我们就成功通过命令的方式启动了一个主从集群。
ip 地址不要配置为 127.0.0.1 的原因 : Java 客户端驱动程序连接的时候会报下面的异常:
Exception in monitor thread while connecting to server 127.0.0.1:28019
因为 java 客户端,从上面的配置中获取了集群成员的列表信息,客户端以 127.0.0.1 发起访问,客户端本地没有这个端口,所以报错。
配置文件方式
配置文件方式,其实就是讲命令方式中的配置挪到了配置文件中。
配置
# 如果是yum安装方式,可以将默认配置文件复制出三个配置文件
sudo cp /etc/mongod.conf /etc/rep-mongod01.conf
sudo cp /etc/mongod.conf /etc/rep-mongod02.conf
sudo cp /etc/mongod.conf /etc/rep-mongod03.conf
# 如果不是,则创建,准备三个配置文件
sudo vim /etc/rep-mongod01.conf
sudo vim /etc/rep-mongod02.conf
sudo vim /etc/rep-mongod03.conf
# 准备目录
sudo mkdir -p /mongodb/dataOne /mongodb/dataTwo /mongodb/dataThree
配置文件中的配置内容如下:
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
# Where and how to store data.
storage:
dbPath: /mongodb/dataOne
journal: enabled: true
# engine:
# wiredTiger:
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongod.pid # 不同的实例
timeZoneInfo: /usr/share/zoneinfo
# network interfaces
net:
port: 38017
bindIpAll: true
# replication:
replication:
oplogSizeMB: 128
replSetName: "rs0"
配置文件需要修改的三个地方,数据目录、端口号、集群配置,三个配置文件的属性配置如下:
具体的可以参考下面的搭建方式包括 分片集群等。
MongoDB集群搭建搭建的pdf 提取码:9h46
使用主从集群
在使用时,不要直接master
并且在使用时,
- 验证主从集群可用性 关闭主节点,集群能否正常提供服务?
- 读写分离 将写操作应用在主节点、读操作应用在次节点
- 读策略 local、available、majority、linearizable、snapshot
local,只从主节点读取数据、可能会发生 脏读,数据可能发生回滚。
available, 从次节点读取数据,读取本地。 可能导致脏读,没有得到大多数节点认可。
majority,需要大多数节点的认可的数 据。
linearizable,只允许主节点读取,写策略 是大多数,得到认可的数据。
snapshot,多文档事务,多数节点从内存 认可的数据
- 写策略 { w: , j: , wtimeout: }
并用关心写的结果,写进去了,不需要响应的话。
检查点:
每隔60s将内存数据持久化到磁盘上
j:
false/true true,在检查点与最新操作之间,预写日志
预估时间, 默认的需要直接写入才能确定。
MongoDB分片
本质在于 数据块太大 ,从而使用分片,把数据块拆小;包括根据日期或者 hash 去拆分开
分片集群中得角色:
mongos:mongs充当查询路由器 ,在客户端应用程序和分片群集之间提供接口。
config server:配置 服务器 存储集群得元数据和配置设置。从mongodb 3.4开始 必须将服务器部署为副本
shard :每个shard 包含共享数据的子集,每个shard 可以部署为主副本集。
可以带来分而治之的思想。
为什么需要 分片集群,也是存储分布式,数据量大量增加, 单台cpu有瓶颈。
分片集群是个双刃剑,在提高系统可扩展性和性能的同时,增大了系统的复杂性,所以在实施之前请确定是必须的。
分片集群工作原理
除了分片,还有自带的数据块进行分区的效果
MongoDB分片集群推荐的模式是:分片集合,它是一种基于分片键的逻辑对文档进行分组,分片键的选择对分片非常重要,分片键一旦确定,MongoDB对数据的分片对应用是透明的;
Tips:随着数据量的的增大,分片会分割和迁移,以满足数据的均匀分布。
- 请求分流:通过路由节点将请求分发到对应的分片和块中
- 数据分流:内部提供平衡器保证数据的均匀分布,数据平均分布式请求平均分布的前提
- 块的拆分:3.4版本块的最大容量为64M或者10w的数据,当到达这个阈值,触发块的拆分,一分为二
- 块的迁移:为保证数据在分片节点服务器分片节点服务器均匀分布,块会在节点之间迁移。一般相差8个分块的时候触发
不断拆分,根据不同的数据块大小进行迁移
搭建方式 采用下面进行就行
MongoDB集群搭建搭建的pdf 提取码:9h46
在安装过程中 可以使用help查看对应的命令。
分片注意点与建议
分片注意点:
- 热点 :某些分片键会导致所有的读或者写请求都操作在单个数据块或者分片上,导致单个分片服务器严重不堪重负。自增长的分片键容易导致写热点问题;
- 不可分割数据块:过于粗粒度的分片键可能导致许多文档使用相同的分片键,这意味着这些文档不能被分割为多个数据块,限制了mongoDB均匀分布数据的能力;
- 查询障碍:分片键与查询没有关联,造成糟糕的查询性能。
建议:
- 不要使用自增长的字段作为分片键,避免热点问题;
- 不能使用粗粒度的分片键,避免数据块无法分割;
- 不能使用完全随机的分片键值,造成查询性能低下;
- 使用与常用查询相关的字段作为分片键,而且包含唯一字段(如业务主键,id等);
- 索引对于分区同样重要,每个分片集合上要有同样的索引,分片键默认成为索引;分片集合只允许在 id和分片键上创建唯一索引;
WiredTiger引擎
MongoDB从3.0引入了可插拔存储引擎的概念。目前主要有WiredTiger、inMemory存储引擎可供选择。在 3.2版本之前MMAPV1是默认的存储引擎,其采用linux操作系统内存映射技术,但一直饱受诟病;3.4以上版本默认的存储引擎是WiredTiger,相对于MMAPV1,WiredTiger有如下优势:
- 读写操作性能更好,WiredTiger能更好的发挥多核系统的处理能力;
- MMAPV1引擎使用表级锁,当某个单表上有并发的操作,吞吐将受到限制。WiredTiger使用文档级 锁,由此带来并发及吞吐的提高
- 相比MMAPV1存储索引时WiredTiger使用前缀压缩,更节省对内存空间的损耗;
- 提供压缩算法,可以大大降低对硬盘资源的消耗,节省约60%以上的硬盘资源;
写入原理
Journaling类似于关系数据库中的事务日志。Journaling能够使MongoDB数据库由于意外故障后快速恢复。 MongoDB2.4版本后默认开启了Journaling日志功能,mongod实例每次启动时都会检查journal日志文件看是否需要恢复。 由于提交journal日志会产生写入阻塞,所以它对写入的操作有性能影响,但对于读没有影响。在生产环境中开启Journaling是很有必要的。
配置项
InMemory存储引擎
InMemory存储引擎, MongoDB Enterprise中可用 。它不是将文档存储在磁盘上,而是将它们保留在内存中。 默认情况下,内存存储引擎使用50%的物理RAM减去1 GB。
使用场景 :
内存中存储引擎是非持久性的,不会将数据写入持久性存储。非持久数据包括应用程序数据和系统数据,例如用户,权限,索引,副本集配置,分片群集配置等。
高性能的读取:副本集中的用来提供高性能查询的次要节点,可以从其他节点恢复数据,不太适用于副本集的主要节点。
配置文件 :
storage:
engine: inmemory
大文件存储GridFS
在MongoDB中,使用GridFS存储大于16 MB的文件,GridFS是用于存储和检索超过16 MB的BSON文档。
GridFS不支持多文档事务。
GridFS不会将文件存储在单个文档中,而是将文件分为多个部分或大块,并将每个大块存储为单独的文档。默认情况下,GridFS使用默认的块大小为255 kB;默认值为255 kB。也就是说,除了最后一个块,GridFS会将文件划分为255 kB的块。最后一块只有必要的大小。类似地,不大于块大小的文件仅具有最终块,仅使用所需的空间以及一些其他元数据。
GridFS使用两个集合来存储文件。fs.chunks集合存储文件块,fs.files集合存储文件元数据
使用GridFS很简单,通过mongofiles工具就能直接对文档进行增删改查操作。
mongofiles工具包含的功能参考帮助
mongofiles –help
上传文件:put
查看文件列表:list
下载文件:get
删除文件:delete
查找文件:search