- MongoDB 数据结构
- MongoDB 索引
- MongoDB 并发控制
- MongoDB 视图 / 环形集合
- 数据分析
- MongoDB 运维
- ReplicaSet
- Sharding
- Morphia 框架 / MongoDB CRUD
MongoDB 数据结构
文档存储使用 BSON, 便于扩展 ( Schemeless )
BSON 支持多种数据类型,文档头部记录每个元素的 Size,读取时直接 Seek 到指定的点
DB 模型设计上有两种模式:嵌套 Embedded / 引用 Reference
引用结构在存储上可以减少冗余,但需要额外查询、且无法确保原子性。两种 Reference 设计
- Manual Reference:即维护类似外键的
col_id
- DBRef:
{ $ref: , $id: , $db: }
MongoDB 索引
建立索引前的查询通过全表扫描 ( COLLSCAN ),建立索引后通过索引查找 ( IXSCAN ) 然后读取 ( FETCH ),索引即主要为解决全表扫描带来的开销。MongoDB 采用B树的结构存储索引,加速索引中查询(等值查询 / 范围查询)、更新删除及排序操作。MongoDB 支持对文档中任意字段构建索引,索引类型有
Single Field Index
: 单字段索引,能加速对相应字段(文档或嵌套文档)的各种查询请求Compound Index
: 针对多字段联合创建索引,先按第一个字段排序、第一个字段相同按第二个字段排序(字段索引间组成上下层的树形结构)Multikey Index
: 针对数组创建的索引,为每个元素创建一个索引GeoSpatial Index
: 地理位置索引,能高效定位坐标范围
索引属性
Unique Index
: 唯一索引,确保相应字段不会重复,如 _idTTL Index
: 指定文档的过期时间,当存储的文档带有过期时间属性时适用,如日志数据Partial Index
: 部分索引,只对特定条件的文档建立索引Sparse Index
: 稀疏索引,只对存在相应字段的文档建立索引
索引分析
# 查看索引大小
db.collection.totalIndexSize()
# 查看索引执行策略
db.collection.find().explain()
# 查看索引构建的元数据信息
db.system.indexes.find()
关于 _id
: 生成规则 Timestamp(4) + Machine(3) + Pid(3) + Rand(3)
确保分布式的 UUID,可以由 ObjectId("xx").getTimestamp()
读取创建时间(即不需要类似 gmtCreated 字段)
Morphia 注解:
@Indexed
定义单值索引@Indexes
定义复合索引,类级别
MongoDB 并发控制
- 两段提交 2PC
- 读写策略一致性:WriteConcern
{w: 1}
/ ReadConcern (3.2+)
MongoDB 视图 / 环形集合
// …
数据分析
- Aggregation / MapReduce
- ETL: 实现 UDF 将 DBObject 转储到 ODPS
MongoDB 运维
- 数据备份及恢复 mongodump / mongorestore
- mongotop
- Github - bobthecow/Genghis: MongoDB admin app
ReplicaSet
MongoDB 复制集 使用多个 Mongo 实例确保高可用,具备 Auto Failover / Auto Recovery
- 主节点 Primary: 读写节点;主节点可能是动态的(如宕机后重新选主),连 RS 时不要直连主节点
- 从节点 Secondary: 只读节点;同步主节点所有 OpLog(local DB 中
oplog.rs
表)并顺序执行 - 投票节点 Arbiter: 无数据存储、且不会被投票升级为主,仅响应心跳和选主请求;顾名思义作用主要为选主仲裁上
- 最小 ReplicaSet:一主两从,才能实现 FO. 如果两个从节点全挂,主节点降级、不能提供服务
- 客户端如何连接 Rs:参考 Connection String URI,客户端可以自动检测主备关系并切换到新主
- ReplicaSet 配置:推荐使用 YAML 定义配置,并开启安全认证
Rs 问题排查及运维
- 确认 ReplicaSet 是否故障
rs.status()
- 查看日志中 Rs 相关的记录
tac mongo.log | grep '\bE REPL\b' | less
- 如何重启 ReplicaSet
- 从节点可直接重启
- 主节点:首先逐个重启从节点,降级主
rs.stepDown()
,重启之
- DB 监控方案
- 主备切换出现时,给出告警
- 从节点宕机时,给出告警
- 从节点 optimeDate 落后太多时,给出告警
Sharding
MongoDB 分片 使用场景在于存储容量或读写能力受单机限制(高并发读写)
Mongos 为请求路由,ConfigSrv 存储集群元数据。参考文档 https://yq.aliyun.com/articles/60096
如何确定 Mongos / Shard 数量(假设容量水位线和负载水位线 0.75)
- 容量场景
- numberOfShards = N / M / 0.75 (单个 Shard 存储能力为 M,存储总量 M)
- numberOfMongos = 2+
- 高并发场景
- numberOfShards = Q / M / 0.75 (单个 Shard QPS 为 M,总 QPS 为 Q)
- numberOfMongos = Q / Ms / 0.75(单个 Mongos QPS 为 Ms)
云产品时代,开放给用户只是数据库连接接口,用户不需要关心 HA 和运维。
Morphia 框架 / MongoDB CRUD
// …