基于MongoDB进行分布式数据存储的步骤

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

本文是研究Mongodb分布式数据存储的副产品,通过本文的相关步骤可以将一个大表中的数据分布到几个mongo服务器上。

  MongoDB的1.6版本中auto-sharding功能基本稳定并可以尝试放到生产环境下使用。因为其是auto-sharding,即mongodb通过mongos(一个自动分片模块,用于构建一个大规模的可扩展的数据库集群,这个集群可以并入动态增加的机器)自动建立一个水平扩展的数据库集群系统,将数据库分表存储在sharding的各个节点上。

  一个mongodb集群包括一些shards(包括一些mongod进程),mongos路由进程,一个或多个config服务器

  (注:本文的测试用例需求64位的mongo程序,因为我在32位的mongo没成功过)。

  下面是一些相关词汇说明:

  Shards : 每一个shard包括一个或多个服务和存储数据的mongod进程(mongod是MongoDB数据的核心进程)典型的每个shard开启多个服务来提高服务的可用性。这些服务/mongod进程在shard中组成一个复制集

  Chunks: Chunk是一个来自特殊集合中的一个数据范围,(collection,minKey,maxKey)描叙一个chunk,它介于minKey和maxKey范围之间。例如chunks 的maxsize大小是100M,如果一个文件达到或超过这个范围时,会被切分到2个新的chunks中。当一个shard的数据过量时,chunks将会被迁移到其他的shards上。同样,chunks也可以迁移到其他的shards上

  Config Servers : Config服务器存储着集群的metadata信息,包括每个服务器,每个shard的基本信息和chunk信息Config服务器主要存储的是chunk信息。每一个config服务器都复制了完整的chunk信息。

  接着看一下要配置的测试环境信息:

  模拟2个shard服务和一个config服务, 均运行在10.0.4.85机器上,只是端口不同:

  Shard1:27020

  Shard2:27021

  Config:27022

  Mongos启动时默认使用的27017端口

  在C,D,E磁盘下分别建立如下文件夹:

  mongodb\bin

  mongodb\db

  然后用CMD命令行依次打开相应文件夹下的mongd文件:

  c:\mongodb\bin\mongod --dbpath c:\mongodb\db\ --port 27020

  d:\mongodb\bin\mongod --dbpath d:\mongodb\db\ --port 27021

  e:\mongodb\bin\mongod --configsvr --dbpath e:\mongodb\db\ --port 27022
         (注:config配置服务器)

  启动mongos时,默认开启了27017端口:

  e:\mongodb\bin\mongos --configdb 10.0.4.85:27022
然后打开mongo:

  E:\mongodb\bin>mongo 回车 (有时加端口会造成下面的addshard命令出问题)

  > use admin

  switched to db admin

  > db.runCommand( { addshard : "10.0.4.85:27020", allowLocal : 1, maxSize:2 , minKey:1, maxKey:10} )

  --添加sharding,maxsize单位是M,此处设置比较小的数值只为演示sharding效果

  { "shardAdded" : "shard0000", "ok" : 1 }

  > db.runCommand( { addshard : "10.0.4.85:27021", allowLocal : 1, minKey:1000} )

  { "shardAdded" : "shard0001", "ok" : 1 }
注:如果要移除sharding,可用下面写法

  db.runCommand( { removeshard : "localhost:10000" } );

  > db.runCommand({listshards:1}); 查看shard节点列表

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->      {
        "shards" : [
                {
                        "_id" : "shard0000",
                        "host" : "10.0.4.85:27020"
                },
                {
                        "_id" : "shard0001",
                        "host" : "10.0.4.85:27021"
                }
        ],
        "ok" : 1
      }

  接下来创建相应数据库并设置其"可以sharding",新建自动切片的库user001:

  > config = connect("10.0.4.85:27022")

  > config = config.getSisterDB("config")

  > dnt_mongodb=db.getSisterDB("dnt_mongodb");

  dnt_mongodb

  > db.runCommand({enablesharding:"dnt_mongodb"})

  { "ok" : 1 }
注:一旦enable了个数据库,mongos将会把数据库里的不同数据集放在不同的分片上。除非数据集被分片(下面会设置),否则一个数据集的所有数据将放在一个分片上。

  > db.printShardingStatus();

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->   --- Sharding Status ---
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
      { "_id" : "shard0000", "host" : "10.0.4.85:27020" }
      { "_id" : "shard0001", "host" : "10.0.4.85:27021" }
  databases:
        { "_id" : "admin", "partitioned" : false, "primary" : "config" }
        { "_id" : "dnt_mongodb", "partitioned" : true, "primary" : "shard0000" }
> db.runCommand( { shardcollection : "dnt_mongodb.posts1", key : {_id : 1}, unique: true } )

  { "collectionsharded" : "dnt_mongodb.posts1", "ok" : 1 }

  --使用shardcollection 命令分隔数据集,key自动生成 [必须为唯一索引unique index]。

  如果要进行GridFS sharding,则需进行如下设置:

  db.runCommand( { shardcollection : "dnt_mongodb.attach_gfstream.chunks", key : { files_id : 1 } } )

  {"ok" : 1} ,更多内容参见http://eshilin.blog.163.com/blog/static/13288033020106215227346/

  > db.printShardingStatus()

  --- Sharding Status ---

  sharding version: { "_id" : 1, "version" : 3 }

  shards:

  { "_id" : "shard0000", "host" : "localhost:27020" }

  { "_id" : "shard0001", "host" : "localhost:27021" }

  databases:

  { "_id" : "admin", "partitioned" : false, "primary" : "config" }

  { "_id" : "user001", "partitioned" : true, "primary" : "shard0000" }

  dnt_mongodb.posts1e chunks:

  { "name" : { $minKey : 1 } } -->> { "name" : { $maxKey :

  1 } } on : shard0000 { "t" : 1000, "i" : 0
下面我用一个工具来批量向dnt_mongodb数据库的 posts1表中导入数据,大约是16万条数据。导入过程中mongos会显示类似如下信息:

  Tue Sep 07 12:13:15 [conn14] autosplitting dnt_mongodb.posts1 size: 47273960 shard: ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 1|0 min: { _id: MinKey } max: { _id: MaxKey } on: { _id: 19 }(splitThreshold 47185920)

  Tue Sep 07 12:13:15 [conn14] config change: { _id: "4_85-2010-09-07T04:13:15-0", server: "4_85", time: new Date(1283832795994), what: "split", ns: "dnt_mongodb.posts1", details: { before: { min: { _id: MinKey }, max: { _id: MaxKey } }, left: { min: { _id: MinKey }, max: { _id: 19 } }, right: { min: { _id: 19 }, max: {_id: MaxKey } } } }

  Tue Sep 07 12:13:16 [conn14] moving chunk (auto): ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 1|1 min: { _id: MinKey } max: { _id: 19 } to: shard0001:10.0.4.85:27021 #objects: 0

  Tue Sep 07 12:13:16 [conn14] moving chunk ns: dnt_mongodb.posts1 moving ( ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 1|1 min: { _id: MinKey }max: { _id: 19 }) shard0000:10.0.4.85:27020 -> shard0001:10.0.4.85:27021

  Tue Sep 07 12:13:23 [WriteBackListener] ~ScopedDBConnection: _conn != null

  Tue Sep 07 12:13:23 [WriteBackListener] ERROR: splitIfShould failed: ns: dnt_mongodb.posts1 findOne has stale config

  Tue Sep 07 12:13:28 [WriteBackListener] autosplitting dnt_mongodb.posts1 size: 54106804 shard: ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 2|1min: { _id: 19 } max: { _id: MaxKey } on: { _id: 71452 }(splitThreshold 47185920)

  Tue Sep 07 12:13:28 [WriteBackListener] config change: { _id: "4_85-2010-09-07T04:13:28-1", server: "4_85", time: new Date(1283832808738), what: "split", ns: "dnt_mongodb.posts1", details: { before: { min: { _id: 19 }, max: { _id: MaxKey }}, left: { min: { _id: 19 }, max: { _id: 71452 } }, right: { min: { _id: 71452 }, max: { _id: MaxKey } } } }

  在完成自动sharding之后,可以使用mongo看一下结果:

  > use dnt_mongodb

  switched to db dnt_mongodb

  > show collections

  posts1

  system.indexes

  > db.posts1.stats()

  {

  "sharded" : true,

  "ns" : "dnt_mongodb.posts1",

  "count" : 161531,

  "size" : 195882316,

  "avgObjSize" : 1212.6608267143768,

  "storageSize" : 231467776,

  "nindexes" : 1,

  "nchunks" : 5,

  "shards" : {

  "shard0000" : {

  "ns" : "dnt_mongodb.posts1",

  "count" : 62434,

  "size" : 54525632,

  "avgObjSize" : 873.3323509626165,

  "storageSize" : 65217024,

  "numExtents" : 10,

  "nindexes" : 1,

  "lastExtentSize" : 17394176,

  "paddingFactor" : 1,

  "flags" : 1,

  "totalIndexSize" : 2179072,

  "indexSizes" : {

  "_id_" : 2179072

  },

  "ok" : 1

  },

  "shard0001" : {

  "ns" : "dnt_mongodb.posts1",

  "count" : 99097,

  "size" : 141356684,

  "avgObjSize" : 1426.4476623913943,

  "storageSize" : 166250752,

  "numExtents" : 12,

  "nindexes" : 1,

  "lastExtentSize" : 37473024,

  "paddingFactor" : 1,

  "flags" : 1,

  "totalIndexSize" : 3424256,

  "indexSizes" : {

  "_id_" : 3424256

  },

  "ok" : 1

  }

  },

  "ok" : 1

  }
通过上面的结果,可以出现16万条记录均分在了两个sharding上,其中shard0000中有62434条,shard0001中有99097条。下面看一下这两个sharding-chunk的分布情况(图中的错误提示‘输入字符串格式不正确’主要因为运行环境与编译程序使用的环境不同,一个是64,一个是32位系统):

 

  可以看到数据被按区间自动分割开了,有点像sqlserver的数据分区表,只不过这是自动完成的(目前我没找到可以手工指定区间上下限的方式,如有知道的TX可以跟我说一下)。当然在本文中的测试中,共有5个chunk,其中4个位于shard0001,这种情况可以在每次测试过程中会发生变化,包括两个sharding被分配的记录数。另外就是在mongodb移动过程前后会在shard0000上生成一个文件夹,里面包括一些bson文件,名字形如(表格+日期等信息):

  post-cleanup.2010-09-07T04-13-31.1.bson

  该文件主要包括一些数据库,表结构及相关记录等信息,我想应该是用于数据恢复备份的。
 










本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/784377,如需转载请自行联系原作者
相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
7月前
|
存储 安全 数据管理
新型数据库技术:基于区块链的分布式数据存储系统
传统数据库系统面临着中心化管理、数据安全性和可信度等方面的挑战。本文介绍了一种基于区块链技术的新型数据库系统,通过分布式存储和去中心化的特性,提高了数据的安全性和可信度,同时实现了高效的数据管理和共享。该系统在多个领域如金融、医疗和物联网等具有广阔的应用前景。
|
2月前
|
JavaScript 网络架构
Vue中实现分布式动态路由:基础步骤详解
Vue中实现分布式动态路由:基础步骤详解
30 2
|
2月前
|
SQL NoSQL MongoDB
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
一款基于分布式文件存储的数据库MongoDB的介绍及基本使用教程
49 0
|
7月前
|
存储 分布式计算 搜索推荐
【专栏】数据之海,分布式计算、数据存储与管理、数据分析与挖掘成为关键技术
【4月更文挑战第27天】在大数据时代,数据量爆炸性增长、类型多样及处理速度需求提升带来挑战。分布式计算、数据存储与管理、数据分析与挖掘成为关键技术,如Hadoop、Spark、HDFS、NoSQL等。实际应用包括互联网搜索、推荐系统、金融科技、智能城市等领域,大规模数据处理发挥关键作用,持续推动创新与奇迹。
159 3
|
4月前
|
存储 NoSQL 算法
MongoDB保姆级指南(中):从副本集群、分片集群起航,探索分布式存储的趋势!
本文一起来聊聊MongoDB集群,顺带以MongoDB集群为起点,共同探讨一下分布式存储的发展趋势~
312 15
|
4月前
|
存储 监控 NoSQL
震撼!揭秘高可用 MongoDB 分片集群搭建的神秘魔法,开启数据存储的无敌模式!
【8月更文挑战第9天】在数字化时代,数据至关重要。MongoDB作为流行非关系型数据库,通过搭建高可用分片集群确保系统稳定性和性能。分片技术将大数据集分布于多服务器以实现水平扩展。搭建集群需准备服务器资源,配置环境,启动配置服务器、路由服务器及分片服务器,并设置分片策略。例如,对特定数据库和集合启用分片。此架构适用于高流量应用如大型电商平台,确保数据高效处理和高可用性。搭建过程需持续监控和优化,合理规划分片策略以维持系统稳定运行。
40 3
|
4月前
|
Java 前端开发 Spring
技术融合新潮流!Vaadin携手Spring Boot、React、Angular,引领Web开发变革,你准备好了吗?
【8月更文挑战第31天】本文探讨了Vaadin与Spring Boot、React及Angular等主流技术栈的最佳融合实践。Vaadin作为现代Java Web框架,与其他技术栈结合能更好地满足复杂应用需求。文中通过示例代码展示了如何在Spring Boot项目中集成Vaadin,以及如何在Vaadin项目中使用React和Angular组件,充分发挥各技术栈的优势,提升开发效率和用户体验。开发者可根据具体需求选择合适的技术组合。
86 0
|
4月前
|
存储 算法 NoSQL
(三)漫谈分布式之集群篇:探寻N个9高可用与PB级数据存储的实现原理!
本文来详细聊聊集群的各方面知识,为诸位量身打造出结构化的集群知识体系。
139 0
|
6月前
|
存储 数据采集 NoSQL
Scrapy与MongoDB的异步数据存储
在数据采集过程中,处理大量的数据请求和存储任务是常见的需求。使用Scrapy来爬取数据并将其存储到MongoDB中是一个高效的解决方案。本文将介绍如何实现一个异步插入MongoDB的Scrapy管道。
|
7月前
|
NoSQL 分布式数据库 MongoDB
【MongoDB 专栏】MongoDB 的分布式事务解决方案
【5月更文挑战第11天】本文探讨了MongoDB的分布式事务处理,涉及两阶段提交(2PC)、TCC补偿事务、分布式锁和幂等处理。2PC通过协调者与参与者确保数据一致性,而TCC提供更高性能和容错性。分布式锁解决并发冲突,幂等处理保证事务正确性。根据业务需求选择合适方案,并关注性能、可靠性和容错。
351 2
【MongoDB 专栏】MongoDB 的分布式事务解决方案