MongoDB使用

来源:互联网 发布:淘宝怎样看自己的评价 编辑:程序博客网 时间:2024/06/03 15:08

1、预分片(shard

mongodb通过对数据的横向切分,将一个collection的数据分布到不同的片中。不同的片可以部署在不同的主机上,在数据分布均衡的情况下,可以同时对不同片内的数据进行增删改查操作,从而提升整个系统的吞吐量。

mongodb存储数据的基本单元是chunkchunk分布在各个片中,写入数据时,chunk会逐渐增大,当超过一个阀值时,会分裂成两个片,数据就会同时写入到这两个chunk中,因此,可以将mongodb的负载均衡功能看做是对chunk的负载均衡。如果该collection可以应用分片,mongodb会自动将某个chunk迁移到其他的片上。也可以手工拆分片,和将chunk在片之间做迁移。如果在collection建立后,数据写入前,对chunk进行拆分,并将chunk分布在集群的各个片中,这就是预分片。

实际上chunk的拆分和迁移并不只在collection未写入数据前操作,在任何时候都可以,但是官方不建议这么做,因为手工拆分可能会导致shard key分布不均匀。

2、片键(shard key

一个collection中可以拿出一个或多个字段组成shard key,一个chunk中包含其中一段shard key的数据集合。在不同chunk之间,shard key是严格排序的。所以,一条数据只要计算出shard key就能知道它应该写入到哪个chunk中;只要知道了要查询数据的shard key,就能直接定位到chunkShard key必须是索引字段,因此,要在一个colletin上先建立索引,才能选择shard key

(1)原始字段值作为shardkey

原始字段值作为shard key的好处就是能够保留原始数据的顺序,这在有排序或者按顺序取一段数据操作时非常有好处,可以避免不同节点之间的归并排序,提升性能。

但要避免在写入过程中按照shard key顺序写入,因为这会将所有写入操作集中到一个chunk上。因此,在设计shard key时,需要尽量考虑写入操作的shard key随机性,也要考虑查询操作的顺序性。

要说的一点是mongodb在拆分原始字段值shard key时,拆分结果并不让人满意。做了一个测试,一个字段的值是1-10000中任意随机数,mongodb自动拆分区间的结果是“min-95”、“95-9995”、“9995-max”。这个结果似乎是随机的,但无可避免的将绝大部分数据都写入了“95-9995”这个区间中,而并没有起到负载均衡的作用。

(2)hash shard key

哈希shard key是现在选择作为shard key的字段的值上做hash运算,将计算的结果作为shard key。在实际操作中,计算得出的hash值是Long.MIN_VALUELong.MAX_VALUE的任意长整型数值。

在将一个collection使用hash shard key进行分区之后,会自动分为六个chunk,这些chunkshard key区间分别是Long.MIN_VALUELong.MAX_VALUE进行六等分的其中一段。经过测试,只要字段值得种类找过六个,经过计算的hash值就会非常平均的分布在各个区间当中。

这种方式对数据写入和单条数据的查询性能非常有好处,所有chunk会分担大概均等的压力。但对业务字段的排序和查询性能会有不好的影响,因为数据分布太均匀,在做分段排序时也不得不从多个chunk中获取数据,再做归并排序。

3、读负载均衡

      Mongodb读数据的负载均衡是由数据横向shard和通过一个shard中的多个物理主机分担压力来共同实现的。我们主要考虑的是一个shard中的不同物理主机如何均衡的分担负载。Mongodb是通过客户端参数来设置读负载均衡的,主要通过ReadPreference这个参数来设置的,共有如下几种设置:

       (1)Primary:只从shard中的主节点进行读取。

       (2)PrimaryPreferred:主节点优先,只有主节点不可用,才会从从属节点读取。

       (3)Secondary:只从shard中的从属阶段读取。

       (4)SecondaryPreferred:从属节点优先,只有从节点不可用才会从主节点读。

       (5)Nearest:客户端与主节点和从属节点之间的距离,哪个近就从哪个读取。距离的单位是ping值。

4、写入操作一致性

   MongoDB作为典型的NoSql数据库,一个主要目标就是尽可能的提升系统吞吐量。他使用了BASE的基本原则来设计,即Basic available,提供基本的可用性,支持分区失败;Soft-state:软状态,允许短时间的状态不同步;Eventually Consistent:数据的最终一致性,而不是时时一致。对写入操作的可调节一致性设计就是这种设计思想的一种体现。通过WriteConcern这个类进行设置。

(1)不安全的操作

a)ERRORS_IGNORED:只是将消息发出,忽略一切错误,甚至网络错误也不理会。

b)UNACKNOWLEDGED:将消息发送给socket即返回,不确保数据写入到数据库,因此发生网络错误时会有提示。默认值。

(2)处于弱状态

a)ACKNOWLEDGED:确保已将数据写入到shard中的主节点中,这时如果有针对主节点的查询请求,已经可以查到该数据了。但不保证能从从属节点查询到。

b)FSYNCED:确保数据已写入到shard主节点的磁盘上,这样如果主节点磁盘不损坏,数据就不会因为掉电等原因丢失了。

c)JOURNALED:确保数据写入到服务端的Journal file中,Journal file是POSIX算法中一种保障数据强一致性的一种实现。这种做法可以保证在一个shard中不是所有节点都损坏的前提下数据的安全性。但并不能保证从属节点的数据一致性。

d)MAJORITY:确保数据写入到shard中的多数节点的内存中。

(3)分布式可见

a)REPLICA_ACKNOWLEDGED:保证数据被写入到shard中至少两个节点的内存中。如果shard中只有两个节点,客户端就可以通过nearest选项正确读取到数据了。

(4)最终一致性

MongoDB提供最终一致性的保证,即所有数据都写入到各节点的磁盘上,但实际操作中并没有保证最终一致性的操作设置,这种设置会影响系统的写入性能。

5、写入一致性与读负载均衡的配置选择

(1)数据读取与写入一致性

以一个shard有两个节点为例,要想实现数据读取性能最大化,那就应该使用ReadPreference.nearest()配置了,这样服务器会根据两个节点的繁忙程度决定由哪个节点对数据读取请求提供服务。但要注意MongoDB中两个节点的数据并不是时时都保持一致的。如果两个节点数据不一致,而同一个客户端发出的两次请求分别被两个节点所处理,那这个客户端就会得到不同的查询结果,这种不是由数据删除,而是由服务器状态不一致导致的低可用性在一般的应用中都是不可容忍的,因此要想使用ReadPreference.nearest()配置提高读取性能,就应该讲写入配置为WriteConcern.REPLICA_ACKNOWLEDGED。

MongoDB的操作锁是个需要改进的地方,目前锁级别已经由全局改为colletion,这大大提升了系统性能,但对一个collection既有读又有写的情况下,而且写入操作只能被shard中的主节点来处理,会大大影响系统的写入性能,实际上是一种以降低写入性能为代码,提升查询性能的做法。因此对一个实际在线的系统来说,最好的选择可能不是ReadPreference.nearest(),而是ReadPreference.SecondaryPreferred()或者ReadPreference.Secondary(),这样可以在允许数据有一定时间延迟的情况下,有效提升系统的吞吐量。

(2)读写分离

为了尽可能的提高MongoDB的吞吐量,有一种做法叫做读写分离,主要是数据查询与增删改操作的分离。

假设一个shard由两个节点组成,主机负责写入,使用性能较高的硬件,从机负责读取和查询,硬件性能可以差一些,使用自动主从互备的机制进行数据拷贝。这样实际上由主机拷贝过来的数据也是写入操作,只不过是单纯的顺序拷贝,性能消耗会少很多。而写入操作不会受查询锁的影响,从而达到最大吞吐量。

6、GridFS

GridFS是一个客户端逻辑视图,在服务端并不存在一个管理“GridFS”的对象。在客户端创建GridFS对象时,会在服务端建立两个表分别叫做${fsname}.files${fsname}.chunks,分别用来保存文件的元数据和文件块。在进行文件创建操作时,会首先写入chunks表,写入完成后,再将元数据写入到files表。因此GridFS操作实际上也是collection的操作,包括读写特性、分片、shard key的建立等,与其他类型的collection没有区别。因此我们可以通过对fileschunks表进行分片,拆分和迁移等操作来完成对GridFS的一致性和负载均衡等特性的设置。

0 0
原创粉丝点击