mongodb集群

mongodb集群

mongodb集群有三种模式,主从模式,副本集模式、sharding分片集模式。

主从模式:官网也不再推荐上生产环境,主要是安全性太低

副本集和sharding分片集模式:目前使用的最广的方案,通常这2种方案的选择通过数据量和并发数来权衡。

在GB级别的基本上副本集方案可满足,TB级别或以上采用sharding分片集模式,解决单机容量单机并发能力。这两种既有自己的优势也有自己的缺点,比如sharding分片集模式分片越多,性能自然下降越多

副本集

这节课讲了mongodb的副本集架构常用的就是一主一从一仲裁

也叫复制集,本质上来说就是一种具有监控能力的主从模式,类似redis中的哨兵主从集群

一组Mongodb复制集,就是一组mongod进程,这些进程维护同一个数据集合。复制集提供了数据冗余和高等级的可靠性,这是生产部署的基础。说白了,就是高级主从。

保证数据在生产部署时的冗余和可靠性,通过在不同的机器上保存副本来保证数据的不会因为单点损坏而丢失。能够随时应对数据丢失、机器损坏带来的风险。(容灾性)

复制集的基本架构

  • 副本集:一个副本集就是一组MongoDB实例组成的集群,由一个主(Primary)服务器和多个备份(Secondary)服务器构成
  • 主节点(primary):主节点接收所有写入操作。主节点将对其数据集所做的所有更改记录到其 oplog(operation log,操作日志)日志。
  • 副节点(secondary):复制主节点的 oplog日志 并将操作应用到其数据集,如果主节点不可用,一个合格的副节点将被选举为新的主节点。
  • 仲裁节点(arbiter):负载选举,当主节点不可用(主节点客观下线状态),它将从副节点中选一个作为主节点。

复制集的基本架构由3台服务器组成,有2种组成模式:

  • 三成员的复制集,有3个主从节点(1主2从)

  • 两成员的复制集,有2个主从节点,1个仲裁节点(arbiter)。(1主1从1仲裁)====》可靠

不存在arbiter节点

一个主节点;

两个从节点组成,主节点宕机时,这两个从节点都可以经过primary选举以后被选为主节点。

在这里插入图片描述

​ 当主库宕机后,两个从库都会进行竞选,其中一个变为主库,当原主库恢复后,作为从库加入当前的复制集群即可。

在这里插入图片描述

存在arbiter节点

在三个成员的复制集中,有两个正常的主从节点和一个arbiter节点:

一个主节点

一个从节点,可以在选举中成为主库

一个仲裁节点,在选举中,只进行投票,不能成为主库

在这里插入图片描述

说明:由于arbiter节点没有复制数据,因此这个架构中仅提供一个完整的数据副本。arbiter节点只需要更少的资源,代价是更有限的冗余和容错。

当主库宕机时,将会选择从库成为主,主库修复后,将其加入到现有的复制集群中即可。

在这里插入图片描述

Primary选举

复制集通过replSetInitiate命令(或mongo shell的rs.initiate())进行初始化,初始化后各个成员间开始发送心跳消息,并发起Priamry选举操作,获得『大多数 总服务器-仲裁节点/ 2 > 50%』成员投票支持的节点,会成为Primary,其余节点成为Secondary。

『大多数』的定义

假设复制集内投票成员数量为N,则大多数为 N/2 + 1,当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,复制集将无法提供写服务,处于只读状态。

投票成员数大多数容忍失效数
110
220
321
431
532
642
743

通常建议将复制集成员数量设置为奇数,从上表可以看出3个节点和4个节点的复制集都只能容忍1个节点失效,从『服务可用性』的角度看,其效果是一样的。(但无疑4个节点能提供更可靠的数据存储)

docker-compose搭建MongoDB复制集

keyfile是mongodb副本集的实例之间的权限认证,复制集要求每一个服务器下的keyfile内容必须相同。内容不同,那么该实例添加到副本集的时候,会出现不可达的状态。同时对于keyfile文件还要求如下:

  • keyfile文件的权限必须是600/400;(4、2、1表示读、写、执行权限)-rw------- (600) 只有拥有者有读写权限
  • keyfile文件的内容必须在各个服务器下完全相同。

生成keyfile秘钥文件命令如下,但是因为在windows下容易出现权限问题,所以我们可以基于系统镜像创建Dockerfile构建自定义镜像,并在Dockerfile中编写生成keyfile文件的命令和设置权限的命令。

756就是秘钥长度,最好3的倍数。

openssl rand -base64 756 > data/conf/mongodb.key
chmod 600 data/conf/mongodb.key

Dockerfile,内容:

FROM mongo:4.4.11

RUN mkdir -p /data/conf \
  && openssl rand -base64 756 > /data/conf/mongodb.key \
  && chown mongodb:mongodb /data/conf/mongodb.key \
  && chmod 400 /data/conf/mongodb.key

编译镜像,如下;

docker build -t mongo-replica-set .

docker-compose.yml,代码:

version: '3.7'

services:
  # 主节点
  master:
    image: mongo-replica-set
    restart: always
    privileged: true
    container_name: master
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123
    command: --replSet replica-set --keyFile /data/conf/mongodb.key
    volumes:
      - ./data/mongo/d1:/data/db
  # 副节点
  secondary:
    image: mongo-replica-set
    restart: always
    privileged: true
    container_name: secondary
    ports:
      - 27018:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123
    command: --replSet replica-set --keyFile /data/conf/mongodb.key
    volumes:
      - ./data/mongo/d2:/data/db
  # 仲裁节点
  arbiter:
    image: mongo-replica-set
    restart: always
    privileged: true
    container_name: arbiter
    ports:
      - 27019:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123
    command: --replSet replica-set --keyFile /data/conf/mongodb.key
    volumes:
      - ./data/mongo/d3:/data/db

networks:
  # 默认使用自己创建的网络
  default:

复制集初始化配置
docker-compose -mongo docker-compose.yml up -d

# 选择一个容器进行配置
docker exec -it master /bin/bash

# 配置时需要在admin数据库中
mongo
use admin

# 验证权限
db.auth('root','123')
# 验证通过后,则可以执行副本集的初始化操作initiate(),设置当前mongodb为primary节点
rs.initiate({
	"_id" : "replica-set",
	"members" : [
		{
			"_id" : 0,
			"host" : "master:27017"
		},
		{
			"_id" : 1,
			"host" : "secondary:27017"
		},
		{
			"_id" : 2,
			"host" : "arbiter:27017"
		}
	]
})


# 最后,SECONDARY节点默认是不可读写的,所以要进入从节点,执行如下操作:
docker exec -it secondary /bin/bash
mongo
rs.secondaryOk()

docker exec -it arbiter /bin/bash
mongo
rs.slaveOk()

分片集(sharding set)

当数据量比较大的时候,我们需要把数据分片保存并运行在不同的服务器中,以降低CPU、内存和IO的压力,Sharding分片集就是mongo数据库用于横向扩容的技术。

分片是数据跨多台机器存储,MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署。MongoDB分片技术类似MySQL的水平切分和垂直切分,mongo数据库实现Shardin分片集主要有两种方式:垂直扩展和横向切分(也叫水平扩展)。

  • 垂直扩展的方式就是进行计算机资源扩容,添加更多的CPU,内存,磁盘空间等。(原来一个分片存5G数据,扩到10G)

  • 水平扩展则是通过数据分片的方式将数据集分布在多个服务器上。,通过集群统一提供服务。(原来一个服务器有两个分片只有一个服务器,再买一个服务器增加分片的数量)

分片设计思想

分片为应对高吞吐量大数据量提供了方法。使用分片减少了每个分片需要处理的请求数,因此通过水平扩展,集群可以提高自己的存储容量和吞吐量。举例来说,当插入一条数据时,项目应用只需要访问存储这条数据的分片.

分片是一种分布式系统中用于提高性能和可扩展性的方法。它涉及到将数据集分割成多个较小的部分,每个部分称为一个“分片”。这些分片可以分布在不同的服务器或节点上。以下是分片的一些关键概念和好处:

  1. 高吞吐量:在分布式系统中,如果所有请求都发送到单个服务器,那么这个服务器可能会因为处理大量请求而过载。通过分片,请求可以分散到多个服务器上,每个服务器只处理一部分请求,这样可以提高整体的吞吐量。

  2. 大数据量:随着数据量的增加,单个服务器可能无法存储所有的数据,或者处理数据的速度会下降。分片允许数据被分散存储在多个服务器上,这样可以有效地管理大数据量。

  3. 减少每个分片需要处理的请求数:通过将数据和请求分散到多个分片,每个分片只需要处理分配给它的那部分数据的请求。这减少了单个分片的负载,提高了处理效率

  4. 水平扩展:当系统需要处理更多的数据或请求时,可以通过增加更多的分片来实现水平扩展。这意味着可以通过简单地添加更多的服务器或节点来提高系统的容量和性能。

  5. 局部性原理:分片通常基于某种键(如用户ID、地理位置等)来分配数据,这样可以确保相关的数据项存储在同一个分片中。这有助于提高数据访问的局部性,因为相关的请求可以被路由到同一个分片。

  6. 容错性:分片还可以提高系统的容错性。如果一个分片失败,只有该分片的数据和请求会受到影响,而其他分片可以继续工作

举例来说,假设有一个电子商务平台,它需要存储和处理大量用户的订单信息。如果不使用分片,所有的订单数据都存储在同一个数据库服务器上,那么随着订单数量的增加,这个服务器可能会变得不堪重负。通过分片,可以将订单数据根据用户的地理位置或ID进行分片,分布在不同的服务器上。当用户下订单时,系统只需要与存储该用户订单数据的分片进行交互,这样可以减少延迟,提高响应速度

总的来说,分片是一种有效的数据管理和负载分配策略,它可以帮助分布式系统更高效地处理大量数据和请求。

使用分片减少了每个分片存储的数据。例如如果数据库1tb的数据集,并有4个分片,然后每个分片可能仅持有256 GB的数据。如果有40个分片,那么每个切分可能只有25GB的数据。

在这里插入图片描述

分片机制的优势

1.对集群进行抽象,让集群“不可见”

MongoDB自带了一个叫做mongos的专有路由进程。mongos就是掌握统一路口的路由器,其会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。

2.保证集群总是可读写

MongoDB通过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就可以确保有服务器换掉时,其他的从库可以立即接替坏掉的部分继续工作。

*3.使集群易于扩展

当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。

分片集群架构

组件说明
Config Server配置服务器,是mongod实例,可以理解为真实数据的元数据,存储了集群的所有节点、分片数据路由等信息。默认需要配置3个Config Server节点。Config Server中存储的信息:所有存取数据的方式,所有shard节点的信息,分片功能的一些配置信息。
Mongos数据路由,作为与客户端打交道的模块,提供对外应用访问,所有操作均通过mongos执行。一般有多个mongos节点。数据迁移和数据自动平衡。Mongos本身并不持久化数据,Sharded cluster所有的元数据都会存储到Config Server,而用户的数据会议分散存储到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的碎片。
Mongod真正的数据存储位置,存储应用数据记录。一般有多个Mongod节点,以chunk为单位存数据,达到数据分片目的。

在这里插入图片描述

Mongos的路由功能

当数据写入时,MongoDB Cluster根据分片键设计写入数据。

当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。

分片集群中的数据分布

(1)使用chunk(数据块)来把数据存储不同的分片(shard)

(2)集群搭建完成之后,默认开启一个chunk,大小是64M,chunk的大小容量可以通过配置chunksize修改。

(3)存储数据的容量只要超过64M,chunk会进行平均分裂,如果单位时间存储需求很大,设置更大的chunk

(4)chunk会被自动均衡迁移到各个Shard分片节点下面。(保证每个分片下的数据量比较平均)

Chunk(数据库)是什么

就是一个存储数据的单位,是为了方便分割(分裂)数据和迁移数据的。在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。chunk的产生,会有以下两个用途:

Splitting(切割):当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分成更小的chunk,从而避免chunk过大的情况

Balancing(迁移):在MongoDB中,balancer是一个后台进程,负责chunk(数据块)的迁移,从而均衡各个shard server的负载,系统初始化时默认只有1个chunk,chunk size默认值64M,生产环境中根据业务选择合适的chunk size是最好的。mongoDB会自动拆分和迁移chunks。

迁移前:

在这里插入图片描述

迁移后:

在这里插入图片描述

Chunksize的选择

适合项目业务的chunksize是最好的。

chunk的分裂和迁移非常消耗IO资源;chunk分裂的时机:在插入和更新,读数据不会分裂。

  • 小的chunksize:数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源
  • 大的chunksize:数据分裂少。数据块迁移速度慢迁移的时候就会比较集中消耗IO资源

chunksize的值通过如果没有特殊的要求,可以设置为通常100-200M。

Chunk分裂及迁移

随着数据的增长,其中的数据大小超过了配置的chunksize,默认是64M,则这个chunk就会分裂成两个。数据的增长会让chunk分裂得越来越多。

在这里插入图片描述

这时候,各个shard 上的chunk数量就会不平衡。这时候,mongos中的一个组件balancer 就会执行自动平衡。把chunk从chunk数量最多的shard节点挪动到数量最少的节点。

在这里插入图片描述

chunkSize对分裂及迁移的影响

MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值或者100~200M左右;chunkSize 会直接影响到 chunk(数据块) 分裂、迁移的行为。

chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能导致数据分布不均。

chunkSize 太小,容易出现 jumbo chunk(即分片键shardKey的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)而无法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而无法迁移。

理解:分片键shardKey的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂

分片(Sharding)流程简介

  1. 分片键(Shard Key): 首先,你需要选择一个分片键,这通常是文档中的一个字段或多个字段的组合。分片键用于确定文档应该存储在哪个分片上。

  2. 数据分裂(Splitting): 当文档被插入到一个分片中时,如果该分片上的数据量达到一定阈值(由 chunkSize 控制),那么这个分片就会被分裂成两个或更多的新分片。

  3. 数据迁移(Migration): 分片集群中的平衡器(balancer)会监控数据分布,并自动将分片从一个分片移动到另一个分片,以保持数据的均衡分布。

分裂(Splitting)过程

  1. 插入文档: 当你向集合中插入一个新文档时,MongoDB会根据分片键的值将文档分配到一个合适的分片。

  2. 达到 chunkSize: 当一个分片中的数据量达到 chunkSize 指定的大小时,这个分片就会被认为是“满了”。

  3. 分裂操作: MongoDB会自动将这个“满了”的分片分裂成两个新的分片。分裂操作会选择一个分裂点,通常是分片键值的中间点。

迁移(Migration)过程

  1. 平衡器检查: 平衡器定期检查集群中的分片分布情况。

  2. 数据不均衡: 如果平衡器发现某些分片的数据量比其他分片多,它就会启动迁移过程,将数据从“过载”的分片移动到“欠载”的分片。

  3. 迁移分片: 平衡器会选择一个分片,并将其一部分(或一个整个分片)迁移到另一个分片上。

Jumbo Chunk 问题

如果在分裂过程中,由于 chunkSize 设置得过小,某个分片键的值的分布非常不均匀,导致大量文档都落在同一个分片中,这个分片就会变得非常大,形成一个jumbo chunk。

  • 无法分裂: 因为 chunkSize 太小,MongoDB无法找到合适的分裂点来分裂这个过大的分片。
    • 如果 chunkSize 很小,那么分片会很快达到这个大小限制并触发分裂操作。但是,如果**分片键的某些取值非常常见(某个取值出现频率很高),那么新插入的文档很可能会因为相同的分片键值而被分配到同一个分片中,导致这些文档只能放到一个 chunk 里,无法再分裂**。
  • 无法迁移: 因为jumbo chunk太大了,它不能被迁移到其他分片上,因为迁移过程需要先将chunk分裂成更小的部分

解决方案

  1. 增加 chunkSize: 临时增加 chunkSize 的值,允许更大的分片存在,然后尝试再次分裂和迁移。

  2. 手动分裂: 使用 splitChunk 命令手动指定一个分裂点,将jumbo chunk分裂成更小的分片。

  3. 优化分片键: 选择一个更分散的分片键,或者使用复合分片键,以避免数据过于集中。

  4. 数据重新分布: 删除或归档旧数据,或者重新设计数据模型,以减少jumbo chunk的形成。

希望这个详细的流程解释能帮助你更好地理解分片、分裂、迁移以及jumbo chunk问题。

​ chunk 自动分裂只会在数据写入时触发,所以如果将 chunkSize 改小,系统需要一定的时间来将 chunk 分裂到指定的大小。

chunk 只会分裂,不会合并,所以即使将 chunkSize 改大,现有的 chunk 数量不会减少,但 chunk 大小会随着写入不断增长,直到达到目标大小。

MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值或者100~200M左右;chunkSize 会直接影响到 chunk(数据块) 分裂、迁移的行为,所以设置适合项目业务的chunksize数值是最好的。chunksize的值通过如果没有特殊的要求,可以设置为通常100 - 300M。

chunk的分裂和迁移非常消耗IO资源。

chunk分裂的时机:在插入和更新时分裂。注意:读数据不会分裂。

chunk 只会分裂,不会合并。

  • 小的chunksize:

    数据分裂多,迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。

    chunkSize 太小,容易出现 jumbo chunk(即分片键shardKey的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)导致无法迁移的情况出现。

  • 大的chunksize:

    数据分裂少,迁移速度慢,数据块迁移的时候就会比较集中消耗IO资源。

    chunkSize 越大,则可能出现 chunk 内文档数太多()而无法迁移

数据分片

分片键

MongoDB中数据的分片是以集合为基本单位的,集合中的数据通过片键(Shard key)被分成多部分。其实分片键就是在集合中选一个键(字段),用该键的值作为数据拆分的依据。

所以一个好的分片键对分片至关重要。分片键必须是一个索引,通过sh.shardCollection加会自动创建索引(前提是此集合不存在相同索引的情况下)。一个自增的分片键对写入和数据均匀分布就不是很好,因为自增的分片键总会在一个分片上写入,后续达到某个阀值可能会写到别的分片。但是按照分片键查询会非常高效。

随机分片键对数据的均匀分布效果很好。注意尽量避免在多个分片上进行查询。在所有分片上查询,mongos会对结果进行归并排序。

对集合进行分片时,你需要选择一个分片键,分片键是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照分片键将数据划分到不同的数据块(chunk)中,并将数据块(chunk)均衡地分布到所有分片节点中。

为了按照分片键划分数据块,MongoDB使用基于范围或者 基于哈希的分片方式。

注意:

  • 分片键是不可变。

  • 分片键必须有索引。

  • 分片键大小限制512bytes。

  • 分片键用于分片集中的路由查询(mongos)。

  • MongoDB不接受已进行collection级分片的collection上插入无分片

  • 键的文档(也不支持空值插入)

基于范围的分片(Range Sharding)

Sharded Cluster支持将单个集合的数据分散存储在多shard上,用户可以指定根据集合内文档的某个字段即shard key来进行范围分片(range sharding)。

  1. 选择分片键:首先,你需要选择一个字段作为分片键。这个字段的值将决定文档存储在哪个分片上。

  2. 范围划分:MongoDB会根据分片键的值的范围来分配文档。例如,如果分片键是年龄,那么可能的一个范围是 [0, 30),另一个范围是 [30, 60),等等。每个范围都会映射到一个分片

  3. 优点

    • 查询效率:如果你的查询是基于范围的,比如 find({age: {$gte: 20, $lt: 30}}),那么基于范围的分片可以提供更好的性能,因为相关的文档很可能位于同一个分片上。
  4. 缺点

    • 数据倾斜:如果分片键的值分布不均匀某些分片可能会比其他分片拥有更多的文档,导致数据倾斜。
    • 热点问题:如果某个范围内的文档经常受到查询,那么这个分片可能会变成一个热点,影响性能。
  5. 查询

    基于范围的分片可以提供高效的查询性能,特别是当查询范围与分片键的范围对齐时。如果查询的范围完全落在一个分片的范围内,查询不需要合并;如果查询范围跨越多个分片,那么就需要在多个分片上执行查询并将结果合并。

基于哈希的分片(Hashed Sharding)

对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块。在使用基于哈希分片的系统中,拥有”相近”片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些。

  1. 计算哈希值:MongoDB会对分片键的值计算一个哈希值。这个哈希值是一个数字,它将被用来确定文档应该存储在哪个分片上。

  2. 分配文档:通过将哈希值映射到分片集合上,MongoDB可以确保文档在整个集群中均匀分布。例如,如果有4个分片,那么哈希值会被模4,结果为0的文档会被存储在分片1上,结果为1的文档会被存储在分片2上,以此类推。

  3. 优点

    • 数据均匀分布:基于哈希的分片通常能够提供更均匀的数据分布,因为哈希函数可以将键值均匀地分布在所有分片上。
    • 减少热点:由于数据是随机分布的,所以不太可能出现某个分片因为特定查询而成为热点的情况。
  4. 缺点

    • 查询效率对于范围查询,基于哈希的分片可能不如基于范围的分片效率高,因为相关的文档可能分布在不同的分片上,需要在多个分片上执行查询然后合并结果
  5. 查询

    基于哈希的分片提供了良好的数据分布负载均衡,但是它通常需要在多个分片上执行查询并将结果合并,这可能会影响查询性能。因此,设计分片键和分片策略时,应该考虑到应用程序的查询模式,以优化性能。如果应用程序经常执行非分片键的查询,可能需要考虑使用基于范围的分片或其他策略,以减少跨分片查询的需求。

Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,但不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档。

docker-compose搭建分片集集群

docker network create mongo

mongo-compose.yaml,代码:

version: '3.7'
services:
  shard1:
    image: mongo:4.4.11
    container_name: mongo_shard1
    # --shardsvr: 这个参数仅仅只是将默认的27017端口改为27018,如果指定--port参数,可用不需要这个参数
    # --directoryperdb:每个数据库使用单独的文件夹
    command: mongod --shardsvr --directoryperdb --replSet shard1
    volumes:
      - ./data/mongo/localtime:/etc/localtime
      - ./data/mongo/shard1:/data/db
    privileged: true
    mem_limit: 16000000000
    networks:
      - mongo   

  shard2:
    image: mongo:4.4.11
    container_name: mongo_shard2
    command: mongod --shardsvr --directoryperdb --replSet shard2
    volumes:
      - ./data/mongo/localtime:/etc/localtime
      - ./data/mongo/shard2:/data/db
    privileged: true
    mem_limit: 16000000000
    networks:
      - mongo

  shard3:
    image: mongo:4.4.11
    container_name: mongo_shard3
    command: mongod --shardsvr --directoryperdb --replSet shard3
    volumes:
      - ./data/mongo/localtime:/etc/localtime
      - ./data/mongo/shard3:/data/db
    privileged: true
    mem_limit: 16000000000
    networks:
      - mongo

  config1:
    image: mongo:4.4.11
    container_name: mongo_config1
    # --configsvr: 这个参数仅仅是将默认端口由27017改为27019, 如果指定--port可不添加该参数
    command: mongod --configsvr --directoryperdb --replSet fates-mongo-config --smallfiles
    volumes:
      - ./data/mongo/localtime:/etc/localtime
      - ./data/mongo/config1:/data/configdb
    networks:
      - mongo

  config2:
    image: mongo:4.4.11
    container_name: mongo_config2
    command: mongod --configsvr --directoryperdb --replSet fates-mongo-config --smallfiles
    volumes:
      - ./data/mongo/localtime:/etc/localtime
      - ./data/mongo/config2:/data/configdb
    networks:
      - mongo

  config3:
    image: mongo:4.4.11
    container_name: mongo_config3
    command: mongod --configsvr --directoryperdb --replSet fates-mongo-config --smallfiles
    volumes:
      - ./data/mongo/localtime:/etc/localtime
      - ./data/mongo/config3:/data/configdb
    networks:
      - mongo

  mongos:
    image: mongo:4.4.11
    container_name: mongo_mongos
    # mongo3.6版默认绑定IP为127.0.0.1,此处绑定0.0.0.0是允许其他容器或主机可以访问
    command: mongos --configdb fates-mongo-config/config1:27019,config2:27019,config3:27019 --bind_ip 0.0.0.0 --port 27017
    ports:
     - 27017:27017
    volumes:
      - ./data/mongo/localtime:/etc/localtime
    depends_on:
      - config1
      - config2
      - config3
    networks:
      - mongo
networks:
  mongo:
    external: true

run.sh,代码:

#!/bin/sh
# docker-compose启动mongodb分片容器组服务
docker-compose -f mongo-compose.yaml up -d

# 睡眠半分钟,等待mongodb所有容器起来之后将它们配置加入分片
sleep 30s

# 操作config1,配置config副本集,将config容器组作为config角色,此时config1作为config副本集里的主节点
docker-compose -f mongo-compose.yaml exec config1 bash -c "echo 'rs.initiate({_id: \"mongo-config\",configsvr: true, members: [{ _id : 0, host : \"config1:27019\" },{ _id : 1, host : \"config2:27019\" }, { _id : 2, host : \"config3:27019\" }]})' | mongo --port 27019"

# 操作shard1、shard2、shard3,将shard容器组作为shard角色。
docker-compose -f mongo-compose.yaml exec shard1 bash -c "echo 'rs.initiate({_id: \"shard1\",members: [{ _id : 0, host : \"shard1:27018\" }]})' | mongo --port 27018"
docker-compose -f mongo-compose.yaml exec shard2 bash -c "echo 'rs.initiate({_id: \"shard2\",members: [{ _id : 0, host : \"shard2:27018\" }]})' | mongo --port 27018"
docker-compose -f mongo-compose.yaml exec shard3 bash -c "echo 'rs.initiate({_id: \"shard3\",members: [{ _id : 0, host : \"shard3:27018\" }]})' | mongo --port 27018"

# 将shard1、shard2、shard3加入分片集群组。
docker-compose -f mongo-compose.yaml exec mongos bash -c "echo 'sh.addShard(\"shard1/shard1:27018\")' | mongo"
docker-compose -f mongo-compose.yaml exec mongos bash -c "echo 'sh.addShard(\"shard2/shard2:27018\")' | mongo"
docker-compose -f mongo-compose.yaml exec mongos bash -c "echo 'sh.addShard(\"shard3/shard3:27018\")' | mongo"

运行

sh run.sh

上面仅仅借助docker-compose实现分片集的部署机制。真正的运维环境中,Mongodb集群应该分布在不同的机器,同时,Mongodb库默认是不会将你的表进行分片的,是需要手动配置的,如果不配置,数据都会全部存放在主节点,不会均匀分配到各个分片。

举例:

// 注意:分片的片键必须是索引

// 先让当前库支持分片,school是举例数据库,可以填写实际要分片的库名。
sh.enableSharding("school")


// 把当前集合加入分片,递增片键(timestamp已经作为索引了),student表示要分片的集合,可以填写实际要分片的集合名称。
sh.shardCollection('school.student',{timestamp:1})

// 刷新路由
db.adminCommand("flushRouterConfig")

// 让当前分片支持均衡调度, 当某个shard中的chunk达到一定的数量,则balancer会自动的将部分chunk块迁移到其它shard中,保证所有的shard中拥有的 chunk 块数量基本一致。
sh.enableBalancing("school.student")

// 开启均衡调度
sh.startBalancer()

// 查看详细分片信息
sh.status({"verbose":1})

// 查看该表的分片数据信息
db.student.getShardDistribution()

若有错误与不足请指出,关注DPT一起进步吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我DPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值