您的位置:首页 > 数据库 > Mongodb

《MongoDB扩展技术》读书笔记之二(完)

2013-11-09 22:37 232 查看

3.2  进行数据分片

配置服务器

配置服务器只是普通的mongod实例。

生产环境中,建议采用3个配置服务器,分布在不同的故障域(failure domain)。

不能运行任意个数的配置服务器,因为它们之间的交互是复杂的。

另外,配置服务器并不使用“普通”mongod所采用的复制机制,而且也不应该按副本集或主从设置启动。只要把配置服务器当作未连接的普通mongod启动就行了。

$mongod

mongos

一个分片配置需要至少一个mongos(但无上限),它就像派对上的主人,会介绍宾客(即分片)相互认识。

集群管理都是通过mongos完成的!

要记住:必须监视所有mongos进程。所以启动太多mongos也是麻烦,一般每个应用程序服务器一个mongos进程就挺好。

$mongos --configdb ny-01,sf-01,moon-01

分片

设置分片需要在admin数据库中执行命令

$mongo ny-02:27017/admin

添加一台服务器分片:> db.runCommand({"addShard" : "sf-02:27017", "name" : "this is shard1", "maxSize" : 20000}) #添加分片时,加上name字段,可以随意命名分片。#限制分片大小:默认情况下,MongoDB会在分片间均匀地分配数据。但如果一台是10T,另一台是500G,应该使用maxSize来指定分片能增长到的最大存储量,单位MB。要记住maxSize更像是一个建议而非规定。MongoDB不会从maxSize处截断一个分片,或是组织它再增加哪怕一个字节,而是会停止将数据移动到该分片,当然还可能会挪走一部分数据。

添加一个副本集分片:> db.runCommand({"addShard" : "rs/rs1-a,rs1-c", "name" : "replicaSet1"})  #副本集叫做rs,mongos会连上任意一个集合成员来推出其他成员。所以只填一个成员也是可以的({"addShard" : "rs/rs1-a"})

启用分片:> db.adminCommand({"enableSharding" : "blog"})

对集合分片:> db.adminCommand({"shardCollection" : "blog.posts", key : {"date" : 1, "author" : 1}})#注意,命令里包含了数据库名blog.posts,而非posts。

如果要对一个已经包含数据的集合进行分片,数据片键上必须有索引。所有文档也都必须有片键(且值不能为null)。在集合分片完成后,才可以插入片键值为null的文档。

3.3  增减容量

不管MongoDB多么轻巧地操作,移动数据块仍然会加重负载。即意味着,如果当前服务器容量耗尽时再添加分片可能会导致应用程序在一系列连锁反应下逐步瘫痪。(简单的例子,当前分片1的内存刚够容纳应用程序,而平衡器却让它往新分片2上发送一个数据块,使得分片A把数据块加载到内存,导致应用程序不得不开始访问磁盘)

添加更多分片(扩容)的教训:要尽早(在还有足够空间做调度时)添加分片,要在非忙时段再添加分片。

被添加的分片不必是空的,但不能包含集群中已有的数据库。

移除分片:> db.runCommand({removeShard : "this is shard1"}) #注意!命令会立即返回“started successfully”。需要多运行几次,确认state从“ongoing”变为“completed”才意味着分片已经完全清空,可以安全关闭。

要修改某个集群中的副本集,就假定它是独立运行的来进行:连接主服务器(而非通过mongos)并修改相应配置

第4章 使用集群

查询:读负载的同时,意味着你必须要接受过时的数据。(CAP原则)

#要通过mongos查询一台从机,必须设置“slave okay”就像:> db.getMongo().setSlaveOk()

使用集群时,就不能把整个集合看做是一个“即时快照”(snapshot in time)。例如:

【计数】mongos将count发送给每个分片各自执行,mongos把结果累加后返回。如果有一个迁移正在进行,许多文档就会同时存在(进而被纳入计数)于多个分片上。

【唯一索引】通常情况下,只有每次执行写操作时锁住整个集群(直到写操作确认成功),才能保证分片间不存在重复。因此,除片键以外任何键都难以保证唯一性(因为特定文档只能属于一个数据块,所以它只需在那个分片唯一,就能保证整个集群唯一)。

【更新】和唯一索引面临相同的麻烦,即没法保证操作在多个分片间只发生一次。因此更新单个文档时,一定要在条件中使用片键(update的第一个参数)。如果碰到奇怪的错误信息,考虑一下执行的操作是否对整个集群必须是原子化的。

1.6版里,除非声明了“out”参数,否则MapReduce会创建临时集合。mongos会维护自己的连接池而且从不关闭对分片的连接,因此,临时集合永远不会被清除(因为创建他们的连接从未被关闭)。

第5章  管理

对于单个MongoDB实例来说,对集群的大部分管理工作都可以通过mongo shell来完成。

> db.printShardingStatus() #收集所有与集群有关的重要信息


应该连接什么?

如果执行的只是正常的读写或管理操作,答案永远是“mongos”,而不是分片,也不是配置服务器。

如果操作并非寻常(为了直接查看某个分片的数据或是手动修改一个被搞乱的配置),可能就要连接配置服务器或分片了。

记住配置服务器和分片都只是一般的mongod而已。


5.2  监控

所有对监控单个节点的建议都试用于监控多个节点。

当机器数量变多时,网络会变得越来越重要。

如果可能,请保留一个已经连上集群的shell。创建一个连接要求MongoDB暂时给连接一个锁,假如mongod正好卡在写锁上,shell会一直尝试获取锁,进而永远不能完成连接。

mongostat:可用监控工具中最全面的,它能返回负载、页错误、连接数等信息。在集群中,可以每台服务器单独启动一个mongostat,也可以在某个mongos上运行mongostat --discover来分析出集群的
a587
所有成员并显示其状态。

Web管理界面:如果使用副本集,请确保使用 --rest 选项启动他们。http://localhost:28017/_replSet(mongod运行端口号27017+1000)

5.3  备份

在运行的集群上做备份其实是非常有难度的。因为数据不停地被应用修改,而且被平衡器搬来搬去。如果要从备份中恢复,首先查看下配置服务器,明确哪些数据库应该在要被恢复的分片上,然后只从备份中恢复这些块的数据(还有mongorestore)

so,有条件的话,每个分片都做replica  set吧!

5.4 关于架构的建议

创建应急站点:名字暗示了正在运行的是一个Web站点,不多对多数类型应用都适用。可以让它通过缓存提供数据,或者直接把站点做成静态的。

挖一条‘虚拟护城河“:通过队列控制对集群的访问,阻止或最小化各类问题。队列可以让应用程序在计划的中断时继续处理写入,或者至少避免丢失中断时尚未完成的写入。队列可以吸收短时间内爆发的大量请求并释放一个和缓稳定的请求流,也就是俗称的削峰,而不是让洪流淹没集群。常见的队列包括Amazon SQS、RabbitMQ,甚至就是一个MongoDB集合(当然一定得把它和被保护的集群分开来)。当前,此方案的前提是,应用可以忍受微小的延迟。

5.5  错误处理

分片停机:所有命中该分片的读写都会返回错误。应用程序应该处理这种错误,以便平滑的保持有损服务,而不是彻底宕机。

多数分片停机:如果副本集失去了多数成员,则没有服务器能自动成为主机,集合会变成只读。要确保应用程序仅发送给它带有slaveOkay选项的请求。

配置服务器停机:所有配置服务器必须协同工作。一台配置服务器停机不会立即对集群性能产生影响,但是会导致无法修改任何配置,比如添加mongos服务器。唯一特殊的是在数据迁移时,最后几步之一便是更新配置服务器,任何配置服务器宕机(即无法更新配置),都会让迁移回退。

mongos进程死掉:推荐在每个应用服务器上跑一个mongos并且让每个应用程序服务器和它本地的mongos通信。同时,大部分驱动允许声明一组可连接的mongos,并会按顺序尝试连接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息