1. MongoDB架构分析
1.1 MongoDB架构演进
MongoDB的核心优势就在于灵活的文档模型+高可用复制集+可扩展分片集群
架构路程:
l 单节点,它无疑存在数据单点和服务单点的情况。
l 主备节点,Master只能容忍一个节点失效,一旦Master节点宕机无法服务写请求。
l 一主多备,就可以容忍多节点失效且扩展了读能力,数据可靠性更高,但是还是存在Master单点故障。
l 复制集,通过raft协议选举出primary。所有的写请求都会被发送到primary节点并同步到secondary,当primary故障时,会自动从secondary中选举出primary。但它的问题在于存储容量与写服务受限于primary。
l 分片集群,可将数据分为多个shard,并且每个shard可以chunk出多块数据,实现自动负载均衡。
1.2 Replication
Primary会接受所有的写操作。Primary在oplog(操作日志)记录了所有发生改变的数据。
所有的secondary会同步primary的数据,当primary故障时,会从剩余的secondary中选举出一个合适的primary。
1.2.1 仲裁节点
可以添加一个额外的mongod实例作为仲裁节点。仲裁节点不会进行数据复制,仅仅参与选举primary的投票。它的目的很简单,就是通过响应心跳保证复制集的成员。由于不存储数据,它可以比一个全功能的副本集成员提供更好的服务和较低的资源开销。但是一般建议副本集为奇数节点,而仲裁节点是在副本集为偶数节点时才使用,所以这个功能很少用。
1.2.2 延迟节点
数据落后于其他节点一段固定时间,可用于数据回滚恢复。
1.2.3 自动故障转移
虽然自动故障转移每次时间不同,但是一般这个过程会在一分钟之内完成。例如,会花费10-30S为副本集声明primary不可达,然后花10-30S时间选举primary。所以在测试故障转移的时候,可能在primary宕掉之后不会立即看到secondary选举为primary,需要一定的时间。
1.3 Sharding
MongoDB的Shard集群主要包含以下组件:
l Shard:每个shard会包含所要分片数据的子集。每个shard可以被作为副本集去部署。
l Mongos:它实际上是一个查询路由,为客户端应用程序和分片集群之间提供一个接口。
l Config servers:作为配置服务,存储了集群的元数据。在MongoDB3.4版本中它必须作为复制集而被部署(CSRS)。
1.3.1 Shards key
在集合中分配文档是通过shard key。它以一个不可变的属性或字段存在目标集合的每个文档中。
当进行集合分片时可以选择shard key,要注意分片之后它是不可改变的并且一个shard 集合只能包含一个shard key。
使用shard key时集合必须有一个索引。对于空集合,如果不存在一个合适的索引键,那么会为指定的shard key创建索引。
Shard key的选择非常重要。会影响到性能、效率和分片集群的可扩展性。
应该避免的问题:
l Shard key取值范围太小。
l Shard key某个值的文档特别多,会导致单个chunk太大,影响chunk迁移和负载均衡。
l 根据非shard key查询会导致scanner-gather查询,影响效率。
1.3.2 Chunks
MongoDB分片数据到chunks中。基于shard key,chunk有一个范围。Chunksize默认为64M大小。
MongoDB在分片集群中迁移chunks 是通过balancer策略。Balancer会尝试在集群中均衡数据大小。
1.3.3 sharding优点
l 读/写:MongoDB的读写负载在集群的shards中。可以进行水平伸缩,增减shard。可以进行范围查询。
l 存储容量:允许每个分片包含总数据的一个子集。随着数据的增长,可添加更多的shard来增加集群容量。
l 高可用:如果一个或者多个shard不可用,仍然可以为读写操作提供很好的性能。在停机期间,子集数据在不可用的shard不能被访问到,读或写操作可以指定到健康有效的shards,这样仍然是可以被成功的访问到。
1.3.4 分片策略
范围:
根据某个字段的值,顺序划分为多个范围,每个范围对应一个shard,能很好的支持范围查询。
Hash:
根据某个字段的hash值,顺序划分为多个范围,每个范围对应一个 Shard,能将读写均匀的分布到各个 Shard。这个过程是MongoDB自动完成,不需要客户端完成hash分配。