设为首页 收藏本站
查看: 1213|回复: 0

[经验分享] MongoDB(五)之分片

[复制链接]

尚未签到

发表于 2018-10-26 08:33:52 | 显示全部楼层 |阅读模式
  参考:http://www.lanceyan.com/tech/arch/mongodb_shard1.html
  一、mongodb分片简介
  在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的。而mongodb主打的就是海量数据架构,他不能解决海量数据怎么行!不行!“分片”就用这个来解决这个问题。 传统数据库怎么做海量数据读写?其实一句话概括:分而治之。上图看看就清楚了,如下 taobao岳旭强在infoq中提到的 架构图:
DSC0000.jpg

  上图中有个TDDL,是taobao的一个数据访问层组件,他主要的作用是SQL解析、路由处理。根据应用的请求的功能解析当前访问的sql判断是在哪个业务数据库、哪个表访问查询并返回数据结果。具体如图:
DSC0001.jpg

  说了这么多传统数据库的架构,那Nosql怎么去做到了这些呢?mysql要做到自动扩展需要加一个数据访问层用程序去扩展,数据库的增加、删除、备份还需要程序去控制。一但数据库的节点一多,要维护起来也是非常头疼的。不过mongodb所有的这一切通过他自己的内部机制就可以搞定!还是上图看看mongodb通过哪些机制实现路由、分片:
DSC0002.jpg

  从图中可以看到有四个组件:mongos、config server、shard、replica set。

  •   mongos,数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
  •   config server,顾名思义为配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,这个可不能丢失!就算挂掉其中一台,只要还有存货, mongodb集群就不会挂掉。
  •   shard,这就是传说中的分片了。上面提到一个机器就算能力再大也有天花板,就像军队打仗一样,一个人再厉害喝血瓶也拼不过对方的一个师。俗话说三个臭皮匠顶个诸葛亮,这个时候团队的力量就凸显出来了。在互联网也是这样,一台普通的机器做不了的多台机器来做,如下图:
DSC0003.jpg

  一台机器的一个数据表 Collection1 存储了 1T 数据,压力太大了!在分给4个机器后,每个机器都是256G,则分摊了集中在一台机器的压力。也许有人问一台机器硬盘加大一点不就可以了,为什么要分给四台机器呢?不要光想到存储空间,实际运行的数据库还有硬盘的读写、网络的IO、CPU和内存的瓶颈。在mongodb集群只要设置好了分片规则,通过mongos操作数据库就能自动把对应的数据操作请求转发到对应的分片机器上。在生产环境中分片的片键可要好好设置,这个影响到了怎么把数据均匀分到多个分片机器上,不要出现其中一台机器分了1T,其他机器没有分到的情况,这样还不如不分片!
  分片的一些名词解释:
  片键 :当设置分片时,需要从集合里面选择一个或几个键,把选择出来的键作为数据拆分的依据,这个键叫做片键或复合片键。 选好片键后,MongoDB将不允许插入没有片键的文档,但是允许不同文档的片键类型不一样。
  块(chunk) :在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。chunk的产生,会有以下两个用途:


  •   Splitting: 当一个chunk的大小超过配置中的chunk>
  •   Balancing: 在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载。
  二、环境搭建
  1、实验环境介绍
DSC0004.jpg

  2、同步时间
[root@www.example.com ~]#  ntpdate 202.120.2.101  
[root@hpf-linux ~]# ntpdate 202.120.2.101
  
[root@node1.example.com ~]# ntpdate 202.120.2.101
  
[root@node2.example.com ~]# ntpdate 202.120.2.101
  3、安装mongodb
  注意剩下三台前面已经安装了mongodb这里就不列举了。
[root@hpf-linux ~]#  
yum localinstall -y mongo-10gen-2.4.14-mongodb_1.x86_64.rpm mongo-10gen-server-2.4.14-mongodb_1.x86_64.rpm
  4、配置config server
[root@hpf-linux ~]# vim /etc/mongod.conf  
dbpath=/data/mongodb
  
configsvr = true
  
[root@hpf-linux ~]# mkdir -p /data/mongodb
  
[root@hpf-linux ~]# chown -R mongod.mongod /data/mongodb
  
[root@hpf-linux ~]# service mongod start
  
Starting mongod: about to fork child process, waiting until server is ready for connections.
  
forked process: 130046
  
all output going to: /var/log/mongo/mongod.log
  

  
child process started successfully, parent exiting
  
                                                           [确定]
  
[root@hpf-linux ~]# ss -tnlp |grep mongod
  
LISTEN     0      128                       *:28019                    *:*      users:(("mongod",130046,10))
  
LISTEN     0      128                       *:27019                    *:*      users:(("mongod",130046,9))
  5、配置mongos
  注意在前面做副本集实验时已经使用该机器,这里需要将在做副本集实验时的配置删除,并按以下配置。
[root@www.example.com ~]# vim /etc/mongod.conf  
#dbpath=/data/mongodb
  
configdb = 192.168.1.6:27019
  
[root@www.example.com ~]# mongos -f /etc/mongod.conf
  
Sat Sep 26 21:50:57.282 warning: running with 1 config server should be done only for testing purposes and is not recommended for production
  
about to fork child process, waiting until server is ready for connections.
  
forked process: 7485
  
all output going to: /var/log/mongo/mongod.log
  
child process started successfully, parent exiting
  
[root@www.example.com ~]# ss -tnlp |grep mongos
  
LISTEN     0      128                       *:28017                    *:*      users:(("mongos",7485,8))
  
LISTEN     0      128                       *:27017                    *:*      users:(("mongos",7485,6))
  6、shard节点配置并启动
  node1和node2节点也是在前面做副本集的实验中使用过,这里需要将在前面所增加的配置给删除,并按以下配置。
[root@node1.example.com ~]# vim /etc/mongod.conf  
dbpath=/data/mongodb
  
[root@node1.example.com ~]# service mongod start
  
[root@node2.example.com ~]# vim /etc/mongod.conf
  
dbpath=/data/mongodb
  
[root@node2.example.com ~]# service mongod start
  7、连入mongos
[root@www.example.com ~]# mongo --host 192.168.1.8  
MongoDB shell version: 2.4.14
  
connecting to: 192.168.1.8:27017/test
  
mongos> sh.status()
  
--- Sharding Status ---
  
  sharding version: {
  
"_id" : 1,
  
"version" : 3,
  
"minCompatibleVersion" : 3,
  
"currentVersion" : 4,
  
"clusterId" : ObjectId("5606a2c30b2c688bc754432d")
  
}
  
  shards:
  
  databases:
  
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
  

  
添加shard节点:
  
mongos> sh.addShard("192.168.1.9:27017")
  
{ "shardAdded" : "shard0000", "ok" : 1 }
  
mongos> sh.addShard("192.168.1.10:27017")
  
{ "shardAdded" : "shard0001", "ok" : 1 }
  
mongos> sh.status()
  
--- Sharding Status ---
  
  sharding version: {
  
"_id" : 1,
  
"version" : 3,
  
"minCompatibleVersion" : 3,
  
"currentVersion" : 4,
  
"clusterId" : ObjectId("5606a2c30b2c688bc754432d")
  
}
  
  shards:
  
{  "_id" : "shard0000",  "host" : "192.168.1.9:27017" }
  
{  "_id" : "shard0001",  "host" : "192.168.1.10:27017" }
  
  databases:
  
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
  
{  "_id" : "test",  "partitioned" : false,  "primary" : "shard0000" }
  将testdb库分片:
mongos> sh.enableSharding("testdb")  
{ "ok" : 1 }
  
mongos> use testdb
  
switched to db testdb
  
mongos> sh.shardCollection("testdb.testcoll",{Age: 1,Name: 1})
  
{ "collectionsharded" : "testdb.testcoll", "ok" : 1 }
  
mongos> sh.status()
  
--- Sharding Status ---
  
  sharding version: {
  
"_id" : 1,
  
"version" : 3,
  
"minCompatibleVersion" : 3,
  
"currentVersion" : 4,
  
"clusterId" : ObjectId("5606a2c30b2c688bc754432d")
  
}
  
  shards:
  
{  "_id" : "shard0000",  "host" : "192.168.1.9:27017" }
  
{  "_id" : "shard0001",  "host" : "192.168.1.10:27017" }
  
  databases:
  
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
  
{  "_id" : "test",  "partitioned" : false,  "primary" : "shard0000" }
  
{  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0001" }
  
  testdb.testcoll
  
   shard key: { "Age" : 1, "Name" : 1 }
  
   chunks:
  
    shard0001 1
  
   { "Age" : { "$minKey" : 1 }, "Name" : { "$minKey" : 1 } } -->> { "Age" : { "$maxKey" : 1 }, "Name" : { "$maxKey" : 1 } } on : shard0001 Timestamp(1, 0)
  增加数据用来查看是否能分片:
mongos> for(i=1;i use testdb
  
switched to db testdb
  
mongos> sh.status()
  
--- Sharding Status ---
  
  sharding version: {
  
"_id" : 1,
  
"version" : 3,
  
"minCompatibleVersion" : 3,
  
"currentVersion" : 4,
  
"clusterId" : ObjectId("5606a2c30b2c688bc754432d")
  
}
  
  shards:
  
{  "_id" : "shard0000",  "host" : "192.168.1.9:27017" }
  
{  "_id" : "shard0001",  "host" : "192.168.1.10:27017" }
  
  databases:
  
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
  
{  "_id" : "test",  "partitioned" : false,  "primary" : "shard0000" }
  
{  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0001" }
  
  testdb.testcoll
  
   shard key: { "Age" : 1, "Name" : 1 }
  
   chunks:
  
    shard0000 1
  
    shard0001 3
  
   { "Age" : { "$minKey" : 1 }, "Name" : { "$minKey" : 1 } } -->> { "Age" : 1, "Name" : "User1" } on : shard0000 Timestamp(2, 0)
  
   { "Age" : 1, "Name" : "User1" } -->> { "Age" : 64, "Name" : "User92614" } on : shard0001 Timestamp(2, 2)
  
   { "Age" : 64, "Name" : "User92614" } -->> { "Age" : 149, "Name" : "User899" } on : shard0001 Timestamp(2, 3)
  
   { "Age" : 149, "Name" : "User899" } -->> { "Age" : { "$maxKey" : 1 }, "Name" : { "$maxKey" : 1 } } on : shard0001 Timestamp(1, 4)
  
mongos> db.testcoll.find({Age: {$gt: 140}}).limit(3)
  
{ "_id" : ObjectId("5606b672ef76b4db97a7d713"), "Name" : "User100041", "Age" : 141, "Address" : "xinyang" }
  
{ "_id" : ObjectId("5606b672ef76b4db97a7d7a9"), "Name" : "User100191", "Age" : 141, "Address" : "xinyang" }
  
{ "_id" : ObjectId("5606b672ef76b4db97a7d83f"), "Name" : "User100341", "Age" : 141, "Address" : "xinyang" }
  
mongos> sh.getBalancerState()
  
true
  总结:
  这里只是简单的演示了mongodb的分片机制,在该实验中有几点问题需要解决:

  •   shard节点出现故障就会出现数据丢失,故shard节点需要做副本集来增加高可用。
  •   同样config server也需要做到高可用。
  以上就是我所想到的问题点,然而实际中还是有很多问题需要解决,本人水平有限,这里就不多说了,下面一个连接讲的架构就是利用三台机器做到的shard的高可用,但实际中还是不建议这么玩,在所有的分布式系统中建议还是增加主机使用,若机器较少,还是使用集中式的解决方案。毕竟关系型数据库技术是很成熟的,而所有的nosql也是这几年火起来的,若想使用还是要看公司的研发能力。个人认为在使用任何一个新技术术时一定不要盲目使用,需要看其缺点,而不是只看优点,同时根据自身的需求选择软件。只有最合适的没有最好的!我在使用四台虚拟机做该实验时本本是4G的内存,CPU是i5-5200U,可是还是卡的要死,所以伙伴们还是根据自身的硬件在玩mongodb吧,我这只是抛砖引玉。
DSC0005.jpg




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-626552-1-1.html 上篇帖子: mongodb服务安装,搭建副本集及原理概述 下篇帖子: Mongodb副本集的维护
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表