MongoDB
2023-02-12 21:24:10 2 举报
MongoDB
作者其他创作
大纲/内容
{\"op\":\"i\
{\"op\":\"u\
a disk leaf page
readConcern:majorityx:2
Client Application
data
Driver
routing table span style=\
Replication
mongo2(192.168.65.2)mongo03.commongo04.com
db.chunk1
Journal
MongoDB索引
WT_CURSOR
MongoDB基础架构MongoDB从3.0开始引入可插拔存储引擎的概念。目前主要有MMAPV1、font color=\"#f44336\
page header
Heartbeat
Primary
WiredTiger读写模型
Chunk4
QueryParser
Primary Oplog Data
30
routing table span style=\
75
\"94301\"
CheckPoint
\"ca2\
New Primary Elected
internal page
MMap
update x:3
Flash
15
Replication(60 Seconds)
Config
Mongos
Secondary
Mongos27017
x=1
Shard1
⑥
WiredTiger
Log
...
WriteConcern
主备(延迟)节点
local.oplog.rs
WiredTiger读写模型读缓存理想情况下,MongoDB可以提供近似内存式的读写性能。WiredTiger引擎实现了数据的二级缓存,第一层是操作系统的页面缓存,第二层则是引擎提供的内部缓存(MongoDB为了尽可能保证业务查询的“热数据”能快速被访问,其内部缓存的默认大小达到了内存的一半)。写缓存当数据发生写入时,MongoDB并不会立即持久化到磁盘上,而是先在内存中记录这些变更,之后通过CheckPoint机制将变化的数据写入磁盘。CheckPoint(检查点)机制快照(snapshot)描述了某一时刻(point-in-time)数据在内存中的一致性视图,而这种数据的一致性是WiredTiger通过MVCC(多版本并发控制)实现的。当建立CheckPoint时,WiredTiger会在内存中建立所有数据的一致性快照,并将该快照覆盖的所有数据变化一并进行持久化(fsync)。成功之后,内存中数据的修改才得以真正保存。默认情况下,MongoDB每60s建立一次CheckPoint,在检查点写入过程中,上一个检查点仍然是可用。这样可以保证一旦出错,MongoDB仍然能恢复到上一个检查点。Journal日志Journal是一种预写式日志(write ahead log)机制,主要用来弥补CheckPoint机制的不足。如果开启了Journal日志,那么WiredTiger会将每个写操作的redo日志写入Journal缓冲区,该缓冲区会频繁地将日志持久化到磁盘上。默认情况下,Journal缓冲区每100ms执行一次持久化。
Chunk3
write
update array(tail)
routing table
Secondary(Hidder)
Shard0
Disk
20
MongoDB与WiredTiger引擎
WiredTiger Cache
60s/times
Election for New Primary(Delay Priority = 0)
{x:180}
Secondary(Delayed)
Multikey Index
Key Space For
Primary(new)
block header
主备(隐藏)节点
Secondary27010
offset=4
Read Page
50
LRU evict
分片策略
⑤
MongoDB
chunk分裂在默认情况下,一个chunk的大小为64MB,该参数由配置的chunksize参数指定。如果持续地向该chunk写入数据,并导致数据量超过了chunk大小,则MongoDB会自动进行分裂,将该chunk切分为两个相同大小的chunk。chunk分裂是基于分片键进行的,如果分片键的基数太小,则可能因为无法分裂而会出现jumbo chunk(超大块)的问题。jumbo chunk对水平扩展有负面作用,该情况不利于数据的均衡,业务上应尽可能避免。自动均衡① 分片shard0在持续的业务写入压力下,产生了chunk分裂。② 分片服务器通知Config Server进行元数据更新。③ Config Server的自动均衡器对chunk分布进行检查,发现shard0和shard1的chunk数差异达到了阈值,向shard0下发moveChunk命令以执行chunk迁移。④ shard0执行指令,将指定数据块复制到shard1。该阶段会完成索引、chunk数据的复制,而且在整个过程中业务侧对数据的操作仍然会指向shard0;所以,在第一轮复制完毕之后,目标shard1会向shard0确认是否还存在增量更新的数据,如果存在则继续复制。⑤ shard0完成迁移后发送通知,此时Config Server开始更新元数据库,将chunk的位置更新为目标shard1。在更新完元数据库后并确保没有关联cursor的情况下,shard0会删除被迁移的chunk副本。⑥ Config Server通知mongos服务器更新路由表。此时,新的业务请求将被路由到shard1。路由策略在 Sharded Cluster 里,用户可以将集合的数据以 chunk 为单位分散存储到多个 shard 上。当写入新文档时,mongos 从config server 上获取集合的路由表本地,如写入{shardKey: 150}的文档,则请求被路由到shard1上写入。mongos 从 config server 上获取到路由表后,会缓存在本地内存,避免每次写入/查询都去 config server 上取表。而在 Sharded Cluster 里,mongos 会自动在 shard 之间迁移 chunk 以均衡负载(用户也可以发送 moveChunk 命令来手动迁移)。那么一旦 chunk 发生迁移后,mongos 本地缓存的路由表就会失效,从而请求被路由到错误的 shard,这个问题该如何解决?MongoDB 的做法是给路由表增加版本信息,比如最初的路由表包含6个 chunk,路由信息的版本为 v6(各个条目版本的最大值)。从 shard0迁到 shard1之后,条目的版本增加为路由表当前版本再加1, 即变为7,这个信息会记录在 shard 本地,同时也会更新到 config server 里。
PlanExecutor
Config Secondary27019
复制集架构Mongodb复制集(Replication Set)由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,提供数据的高可用。复制集提供冗余和高可用性,是所有生产部署的基础。它的现实依赖于两个方面的功能:1. 数据写入时将数据迅速复制到另一个独立节点上2. 在接受写入的节点发生故障时自动选举出一个新的替代节点三节点复制集模式常见的复制集架构由3个成员节点组成,其中存在几种不同的模式。PSS模式PSS模式由一个主节点和两个备节点所组成,即Primary +Secondary +Secondary。此模式始终提供数据集的两个完整副本,如果主节点不可用,则复制集选择备节点作为主节点并继续正常操作。旧的主节点在可用时重新加入复制集。PSA模式PSA模式由一个主节点、一个备节点和一个仲裁者节点组成,即Primary+Secondary+Arbiter。其中,Arbiter节点不存储数据副本,也不提供业务的读写操作。Arbiter节点发生故障不影响业务,仅影响选举投票。此模式仅提供数据的一个完整副本,如果主节点不可用,则复制集将选择备节点作为主节点。
Election for New Primary
data analysis
Storage Interface Layer
Secondary Oplog Data
Config Secondary
{x:25}
BlockManager
Single Field Indexes
路由策略
Secondary2
Oplog同步
font color=\"#323232\
Disk IO
Chunk1
复制集成员角色
x=1{w: 1}
②
cache
Client
MongoDB事务
Shard2
18
x
Secondary1
数据均衡
Config Server
read
db.chunk4
存储结构
幂等性每一条oplog记录都描述了一次数据的原子性变更,对于oplog来说,必须保证是幂等性的。也就是说,对于同一个oplog,无论进行多少次回放操作,数据的最终状态都会保持不变。某文档x字段当前值为100,用户向Primary发送一条{$inc: {x: 1}},记录oplog时会转化为一条{$set: {x: 101}的操作,才能保证幂等性。幂等性的代价简单元素的操作,$inc 转化为 $set并没有什么影响,执行开销上也差不多,但当遇到数组元素操作时,情况就不一样了。font color=\"#0d47a1\
min
①
49
ReadConcern
CacheEviction
CacheBtree
1
2
3
4
5
6
MongoDB多文档事务在MongoDB中,对单个文档的操作是原子的。由于可以在单个文档结构中使用内嵌文档和数组来获得数据之间的关系,不必跨多个文档和集合进行范式化,所以这种单文档原子性避免了许多实际场景中对多文档事务的需求。writeConcernwriteConcern 决定一个写操作落到多少个节点上才算成功。MongoDB支持客户端灵活配置写入策略,以满足不同场景的需求。font color=\"#e74f4c\" style=\"\
事务隔离级别
{x:175}
WiredTiger数据文件在磁盘的存储结构B+ Tree中的leaf page包含一个页头(page header)、块头(block header)和真正的数据(key/value),其中页头定义了页的类型、页中实际载荷数据的大小、页中记录条数等信息;块头定义了此页的checksum、块在磁盘上的寻址位置等信息。WiredTiger有一个块设备管理的模块,用来为page分配block。如果要定位某一行数据(key/value)的位置,可以先通过block的位置找到此page(相对于文件起始位置的偏移量),再通过page找到行数据的相对位置,最后可以得到行数据相对于文件起始位置的偏移量offsets。索引的分类font color=\"#0d47a1\" style=\"font-weight: normal;\
ckpt_lsn
Compound Index
100ms/times
key/value
moveChunk
update x:2
Config Secondary27019
Primary(old)
范围分片
session
t4
\"xyz\
PSA模式
{x:26}
writedata
{x:-75}
offset=6
RocksDB
mongo3(192.168.65.3)mongo05.commongo06.com
复制集成员角色属性一:Priority = 0当 Priority 等于 0 时,它不可以被复制集选举为主,Priority 的值越高,则被选举为主的概率更大。通常,在跨机房方式下部署复制集可以使用该特性。假设使用了机房A和机房B,由于主要业务与机房A更近,则可以将机房B的复制集成员Priority设置为0,这样主节点就一定会是A机房的成员。属性二:Vote = 0 不可以参与选举投票,此时该节点的 Priority 也必须为 0,即它也不能被选举为主。由于一个复制集中最多只有7个投票成员,因此多出来的成员则必须将其vote属性值设置为0,即这些成员将无法参与投票。成员角色Primary:主节点,其接收所有的写请求,然后把修改同步到所有备节点。一个复制集只能有一个主节点,当主节点“挂掉”后,其他节点会重新选举出来一个主节点。Secondary:备节点,与主节点保持同样的数据集。当主节点“挂掉”时,参与竞选主节点。分为以下三个不同类型: · Hidden = false:正常的只读节点,是否可选为主,是否可投票,取决于 Priority,Vote 的值; · Hidden = true:隐藏节点,对客户端不可见, 可以参与选举,但是 Priority 必须为 0,即不能被提升为主。 由于隐藏节点不会接受业务访问,因此可通过隐藏节点做一些数据备份、离线计算的任务,这并不会影响整个复制集。 · Delayed: 延迟节点,必须同时具备隐藏节点和Priority0的特性,会延迟一定的时间(SlaveDelay 配置决定)从上游复制增量,常用于快速回滚场景。Arbiter:仲裁节点,只用于参与选举投票,本身不承载任何数据,只作为投票角色。比如你部署了2个节点的复制集,1个 Primary,1个Secondary,任意节点宕机,复制集将不能提供服务了(无法选出Primary),这时可以给复制集添加⼀个 Arbiter节点,即使有节点宕机,仍能选出Primary。 Arbiter本身不存储数据,是非常轻量级的服务,当复制集成员为偶数时,最好加入⼀个Arbiter节点,以提升复制集可用性。
{score:1} Index
Data File
insert({x:1})v6
{x:MaxKey}
auth
7
8
9
10
WiredTiger Cache(50%)
Chunk2
幂等性
insert({x:1})v7
t6
复制集架构
readConcern:localx:1
Synchronizing ...
\"aa1\
Operating System Page Cache(50%)
77
\"10036\"
t3
success
③
Election for New Primary(Hidden Priority = 0)
什么是Chunkchunk的意思是数据块,一个chunk代表了集合中的“一段数据”。chunk所描述的是范围区间,例如,db.users使用了userId作为分片键,那么chunk就是userId的各个值(或哈希值)的连续区间。集群在操作分片集合时,会根据分片键找到对应的chunk,并向该chunk所在的分片发起操作请求,而chunk的分布在一定程度上会影响数据的读写路径,这由以下两点决定:1.chunk的切分方式,决定如何找到数据所在的chunk2.chunk的分布状态,决定如何找到chunk所在的分片分片算法font color=\"#5b79e8\
leaf page
walk btree
{\"addr.zip\":1} Index
索引类型
Election
哈希分片
offset=1
56
Secondary 1
{ userid:\"xyz\
t1
Seeconday
什么是chunk
max
owner
verison
MinKey
-200
shard0
-100
shard2
0
100
shard0->shad1
4->7
200
shard1
MaxKey
ShardN
Disk other File
MongoDB复制集
db.chunk2
复制集数据同步机制
readConcern:linearizablex:3
①update
Primary27010
Config Primary
Shard3
Config Primary27019
Primary27011
t5
Arbiter(vote only)
disconnect
{x:MinKey}
db.chunk3
① db.user.insertOne({x:1})font color=\"#323232\
PSS模式
主备节点
update array(head)
Secondary27011
Secondary(Hidden)
t2
reads
CategoryManagement
slave Delay=60
inc
MongoDB分片集群架构
P
S1
S2
t0
x=0
root page
Replica
Sharded Cluster
chunk分裂
45
复制集数据同步机制在复制集架构中,主节点与备节点之间是通过oplog来同步数据的,这里的oplog是一个特殊的固定集合,当主节点上的一个写操作完成后,会向oplog集合写入一条对应的日志,而备节点则通过这个oplog不断拉取到新的日志,在本地进行回放以达到数据同步的目的。什么是oplog1. MongoDB oplog 是 Local 库下的一个集合,用来保存写操作所产生的增量日志(类似于 MySQL 中 的 Binlog)。2. 它是一个 Capped Collection(固定集合),即超出配置的最大值后,会自动删除最老的历史数据,MongoDB 针对 oplog 的删除有特殊优化,以提升删除效率。3. 主节点产生新的 oplog Entry,从节点通过复制 oplog 并应用来保持和主节点的状态一致;查看oplogts字段描述了oplog产生的时间戳,可称之为optime。optime是备节点实现增量日志同步的关键,它保证了oplog是节点有序的。optime属于BSON的Timestamp类型,这个类型一般在MongoDB内部使用。既然oplog保证了节点级有序,那么备节点便可以通过轮询的方式进行拉取。同步源选择MongoDB是允许通过备节点进行复制的,这会发生在以下的情况中:在settings.chainingAllowed开启的情况下,备节点自动选择一个最近的节点(ping命令时延最小)进行同步。
Reconclie
writes
Secondary 3
Journal Log
Hash Function
MongoDB 分片集群架构MongoDB 分片集群(Sharded Cluster)是对数据进行水平扩展的一种方式。MongoDB使用 分片集群来支持大数据集和高吞吐量的业务场景。在分片模式下,存储不同的切片数据的节点被称为分片节点,一个分片集群内包含了多个分片节点。当然,除了分片节点,集群中还需要一些配置节点、路由节点,以保证分片机制的正常运作。核心概念数据分片:分片用于存储真正的数据,并提供最终的数据读写访问。分片仅仅是一个逻辑的概念,它可以是一个单独的mongod实例,也可以是一个复制集。图中的Shard1、Shard2都是一个复制集分片。在生产环境中也一般会使用复制集的方式,这是为了防止数据节点出现单点故障。配置服务器(Config Server):配置服务器包含多个节点,并组成一个复制集结构,对应于图中的ConfigReplSet。配置复制集中保存了整个分片集群中的元数据,其中包含各个集合的分片策略,以及分片的路由表等。查询路由(mongos):mongos是分片集群的访问入口,其本身并不持久化数据。mongos启动后,会从配置服务器中加载元数据。之后mongos开始提供访问服务,并将用户的请求正确路由到对应的分片。在分片集群中可以部署多个mongos以分担客户端请求的压力。
\"nb1\
\"78610\"
x=1 {w:\"majority\"}
db.users
MongoDB基础架构
ThreadPool
④
mongo1(192.168.65.1)mongo01.commongo02.com
Secondary 2
0 条评论
下一页