一次线上事故,我顿悟了MongoDB的精髓


大家好我是哪吒最近项目在使用MongoDB作为图片和文档的存储数据库为啥不直接存MySQL里还要搭个MongoDB集群麻不麻烦

让我们一起一探究竟继续学习MongoDB分片的理论与实践实现快速入门丰富个人简历提高面试level给自己增加一点谈资秒变面试小达人BAT不是梦。

MongoDB拒绝连接显然是MongoDB服务又挂了。

在这里插入图片描述

连接MongoDB服务器一探究竟。

通过ps -aef|grep mongo查看mongo服务是否还在不出所料都不在了。

在这里插入图片描述

大概率是因为磁盘满了。

df -TH查看磁盘空间。

在这里插入图片描述

磁盘100%如何解决

cd到log目录下通过rm -rf *删除所有日志再重启MongoDB。

mongodb启动异常about to fork child process, waiting until server is ready for connection

在这里插入图片描述

由于MongoDB是集群部署的启动时会进行数据同步可能会比较耗时性子急的我怎么能忍直接Ctrl C强制停止然后再重新启动。

通过ps -aef|grep mongo查看一下进程两个一样的进程赫然在列。

通过ps -aef|grep mongo | grep -v grep | awk '{print $2}' | xargs kill -9强制停止所有mongo进程。

在这里插入图片描述

将data目录下的 mongod.lock 和 diagnostic.data文件删掉再重启MongoDB启动脚本mongos_start.shmongod --config data/mongodb.conf完美解决。

在这里插入图片描述

MongoDB服务器的部署目录中都是什么含义呢它们之间又有什么关系呢下面简单介绍一下MongoDB的分片。

在这里插入图片描述

一、什么是MongoDB分片

分片是指跨机器拆分数据的过程也可以叫做分区。

MongoDB支持手动分区使用这种方法应用程序会维护到多个不同数据库服务器端的连接每个服务器端都是完全独立的。应用程序不仅管理不同服务器上不同数据的存储还管理在适当的服务器上查询数据。但当从集群中添加或删除节点或者面对数据分布或负载模式的变化时难以维护。

MongoDB支持自动分片这种方式试图将数据库架构从应用程序中抽离出来并简化系统管理。MongoDB自动均衡分片上的数据使节点的添加和删除变得更容易。

MongoDB的分片机制允许你创建一个由许多分片组成的集群并将集合中的数据分散在集群中在每个分片上放置数据的一个子集。这允许应用程序超出单机服务器或副本集的资源限制。

分片组成的集群对应用程序来说就像一台单机服务器分片前运行一个或多个称为mongos的路由进程mongos维护着一个“目录”指明了每个分片包含哪些数据。应用程序可以正常连接到此路由服务器并发出请求。路由服务器知道哪些数据在哪个分片上可以将请求转发到适当的分片。如果有对请求的响应理由服务器会收集它们并将它们合并然后再返回给应用程序对应用程序而言它只知道自己连接到了一个单独的mongod。

在这里插入图片描述

二、MongoDB如何分片?

在单台机器上快速建立一个集群。首先使用--nodb--norc选项启动mongo shellmongo --nodb --norc

使用ShardingTest类创建集群。运行如下代码

st = ShardingTest({
	name:"one-min-shards",
	chunkSize:1,
	shards:2,
	rs:{
		nodes:3,
		oplogSize:10
	},
	other:{
		enableBalancer:true
	}
});
  • name分片集群的标签
  • shards制定了集群由两个分片组成
  • rs将每个分片定义为一组3个节点的副本集
  • enableBalancer在集群启动后启用均衡器

ShardingTest是为了支持服务器端测试套件设计的它在保持尽可能低的资源占用以及建立体系结构相对复杂的分片集群方面提供了很多便利。当运行ShardingTest后它会创建一个包含两个分片的集群每个分片都是一个副本集。同时会对副本集进行配置并使用必要的选项启动每个节点以建立复制协议。它会启动一个mongos来管理跨分片的请求这样客户端就可以像与一个独立的mongod通信一样与集群进行交互。最后它会为用于维护理由表信心的配置服务器启动一个额外的副本集以确保查询被定向到正确的分片。

分片的主要使用场景是拆分数据集以解决硬件和成本的限制或为应用程序提供更好的性能。

当ShardingTest完成集群设置后将启动并运行10个进程你可以连接到这些进程两个副本集各有3个节点、一个配置服务器副本集3个节点以及一个mongos。默认情况下这些进程会从20000端口开始。mongos会运行在20009端口上。

三、何时分片

通常情况下分片用于

  • 增加可用RAM
  • 增加可用磁盘空间
  • 减少服务器的负载
  • 处理单个MongoDB无法承受的吞吐量

在这里插入图片描述

四、搭建MongoDB分片服务器

1、配置服务器 config进程

配置服务器是集群的大脑保存着关于每个服务器包含哪些数据的所有元数据因此必须首先创建配置服务器。配置服务器非常重要运行时必须启动日志功能并确保它的数据存储在非临时性驱动器上。

配置服务器必须在任何一个mongos进程之前通过mongod -f config.conf启动因为mongos需要从配置服务器中提取配置信息。

当对配置服务器进行写入时MongoDB会使用“majority” 的 writeConcern级别
当对配置服务器进行读取时MongoDB会使用“majority” 的 readConcern级别

这确保了分片集群元数据在不发生回滚的情况下才会被提交到配置服务器副本集。它还确保了只有那些不受配置服务器故障影响的元数据才能被读取。这可以确保所有mongos路由节点对分片集群中的数据组织方式具有一致性。

在服务器资源方面配置服务器应该具有充分的网络和CPU资源配置服务器只保存了集群中数据的目录因此只需要很少的硬盘存储资源。

由于配置服务器的重要性在进行任何集群维护前都应该先对配置服务器的数据进行备份。

2、mongos进程

mongos 是路由服务器供应用程序连接使用。通过mongod -f config.conf启动路由服务器mongos进程需要知道配置服务器的地址因此需要在config.conf中配置 configdb=configReplSet/配置服务器的三个地址通过配置logpath保存MongoDB的日志。

应该启动一定数量的mongos进程并尽可能将其放在靠近所有分片的位置这样可以提高查询性能。

3、将副本集转换为分片

在依次启动配置服务器、路由服务器后可以添加分片了如果之前已经存在副本集那么这个副本集就会成为第一个分片。

从MongoDB 3.4 开始对于分片集群分片的mongod实例必须配置 --shardsvr 选项也就是在config.conf中添加shardsvr=true将副本集转换为分片的过程中需要对副本集的每个成员都重复以上动作。

将副本集作为分片添加到集群后就可以将应用程序的连接从副本集改为mongos路由服务器了并通过设置防火墙切断应用程序与分片的直接连接。

4、数据分片

1如何数据分片

假如有一个test数据库并在name键上对worker集合进行分片。

  1. 先对数据库进行分片> sh.enableSharding("test")
  2. 再对集合进行分片sh.shardCollection("test.worker",{"name":1})

如果worker集合已经存在则必须在name字段上有索引否则shardCollection会返回错误。如果分片的集合不存在mongos会自动在name片键上创建索引。

shardCollection命令会将集合拆分成多个数据块MongoDB会在集群中的分片间均匀的分散集合中的数据。

在这里插入图片描述

五、MongoDB如何追踪集群数据

1、数据块

因为MongoDB的数据量巨大MongoDB一般会将文档以数据块的形式进行分组这些数据块是片键指定范围内的文档MongoDB一般会用一个较小的表来维护数据块与分片之间的映射关系。

需要注意

  1. 块与块之间不能重叠
  2. 一个块中的文档数量过大时会自动拆分成两个文档
  3. 一个文档总是属于且仅属于一个块

2、块范围

  1. 新分片的集合中只有一个块块的边界是负无穷到正无穷
  2. 随着块的增长MongoDB会自动将其拆分成两块范围从负无穷到valuevalue到正无穷。范围较小的块包含比value小的值范围较大的块包含value和比value大的值

因此mongos可以很容易的找到文档在哪个块。

3、拆分块

各个分片的主节点mongod进程会跟踪它们当前的块一旦达到某个阈值就会检查该块是否需要拆分如果需要拆分mongod就会从配置服务器请求全局块大小配置值然后执行块拆分并更新配置服务器上的元数据。配置服务器会创建新的块文档并修改旧块的范围。

当客户端写入一个块时mongod会检查该块的拆分阈值。

在这里插入图片描述

如果已经达到了拆分阈值mongod就会向均衡器发送一个请求将最顶部的块进行迁移否则该块会留在此分片上。

在这里插入图片描述

因为具有相同片键的两个文档一定会处于相同的块中所以只能在片键值不同的文档之间进行拆分。

下面文档如果以readTime分片是可以的。

但是如果我读书读的比较快所有书籍在一个月的时间里都读完了readTime就会是一样的了那就无法分片了。

因此拥有不同的片键值在分片时显得尤其重要。

{"name":"哪吒编程","book":"Java核心技术","readTime":"October"}
{"name":"哪吒编程","book":"Java编程思想","readTime":"October"}
{"name":"哪吒编程","book":"深入理解Java虚拟机","readTime":"October"}
{"name":"哪吒编程","book":"effective java","readTime":"November"}
{"name":"哪吒编程","book":"重构 改善既有代码的设计","readTime":"November"}
{"name":"哪吒编程","book":"高性能MySQL","readTime":"December"}
{"name":"哪吒编程","book":"Spring技术内幕","readTime":"December"}
{"name":"哪吒编程","book":"重学Java设计模式","readTime":"December"}
{"name":"哪吒编程","book":"深入理解高并发编程","readTime":"January"}
{"name":"哪吒编程","book":"Redis设计与实现","readTime":"January"}

分片的前提条件是所有的配置服务器必须启动并可以访问。如果mongod不断接到对一个块的写请求则它会持续尝试拆分该块并失败而这些拆分尝试会拖慢mongod。mongod反复尝试分片却无法成功分片的过程被称为拆分风暴

在这里插入图片描述

六、均衡器

均衡器负责数据的迁移。均衡器会定期检查分片之间是否存在不均衡如果存在就会对块进行迁移。在MongoDB 3.4 以上的版本上均衡器位于配置服务器副本集的主节点成员上。

均衡器是配置服务器副本集主节点上的后台进程它会监视每个分片上的块数量。只有当一个分片上的块数量达到特定迁移阈值时均衡器才会被激活。


在这里插入图片描述

Java学习路线总结搬砖工逆袭Java架构师

10万字208道Java经典面试题总结(附答案)

Java基础教程系列

Java高并发编程系列

数据库进阶实战系列

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go