《极客时间教程 - MongoDB 高手课》笔记二
《极客时间教程 - MongoDB 高手课》笔记二
第三章:分片集群与高级运维之道
分片集群机制及原理
MongoDB 常见部署架构
TODO: 补图
为什么要使用分片集群?
——分而治之
分片如何解决?
TODO:补图
分片组件:
- 路由节点(mongos) - 提供集群单一入口转发应用端请求选择合适数据节点进行读写合并多个数据节点的返回。无状态,建议至少 2 个。
- 配置节点(config) - 提供集群元数据存储分片数据分布的映射。
- 数据节点(shard) - 以复制集为单位水平扩展,最大 1024 分片。分片之间数据不重复所有分片在一起才可完整工作
分片特点:
- 应用全透明,无特殊处理
- 数据自动均衡
- 动态扩容,无须下线
- 提供三种分片方式
- 基于范围
- 优点:范围查询性能好
- 缺点:数据分布不均;容易出现热点问题
- 基于 Hash
- 优点:数据分布均匀
- 缺点:范围查询效率低
- 基于 zone / tag
分片集群设计
分片的基本标准:
- 关于数据:数据量不超过 3TB,尽可能保持在 2TB 一个片;
- 关于索引:常用索引必须容纳进内存;
按照以上标准初步确定分片后,还需要考虑业务压力,随着压力增大,CPU、RAM、磁盘中的任何一项出现瓶颈时,都可以通过添加更多分片来解决。
合理的架构–需要多少个分片
- A = 所需存储总量 / 单服务器可挂载容量。如:8TB / 2TB = 4
- B = 工作集大小 / 单服务器内存容量。如:400GB / (256G * 0.6)= 3
- C = 并发量总数 / (单服务器并发量 * 0.7)。如:30000 / (9000*0.7) = 6
- 分片数量= max(A, B, C) = 6
关键概念
- 片键 shard key:文档中的一个字段
- 文档 doc :包含 shard key 的一行数据
- 块 Chunk :包含 n 个文档
- 分片 Shard:包含 n 个 chunk
- 集群 Cluster:包含 n 个分片
选择合适片键
- 取值基数(Cardinality) - 取值基数要大,因为备选值有限,不利于水平扩展
- 取值分布 - 应尽可能均匀,以避免热点问题
- 分散写,集中读
- 被尽可能多的业务场景用到
- 避免单调递增或递减的片键
足够的资源
mongos 与 config 通常消耗很少的资源,可以选择低规格虚拟机;
资源的重点在于 shard 服务器:
- 需要足以容纳热数据索引的内存;
- 正确创建索引后 CPU 通常不会成为瓶颈,除非涉及非常多的计算;
- 磁盘尽量选用 SSD;
实验:分片集群搭建及扩容(略)
MongoDB 监控最佳实践
常用的监控工具及手段
- MongoDB Ops Manager
- Percona
- 通用监控平台
- 程序脚本
监控信息的来源:
- db.serverStatus()(主要)
- db.isMaster()(次要)
- mongostats 命令行工具(只有部分信息)
注意:db.serverStatus() 包含的监控信息是从上次开机到现在为止的累计数据,因此不能简单使用。
serverStatus() 主要信息
- connections: 关于连接数的信息;
- locks: 关于 MongoDB 使用的锁情况;
- network: 网络使用情况统计;
- opcounters: CRUD 的执行次数统计;
- repl: 复制集配置信息;
- wiredTiger: 包含大量 WirdTiger 执行情况的信息:
- block-manager: WT 数据块的读写情况;
- session: session 使用数量;
- concurrentTransactions: Ticket 使用情况;
- mem: 内存使用情况;
- metrics: 一系列性能指标统计信息;
监控报警的考量
- 具备一定的容错机制以减少误报的发生;
- 总结应用各指标峰值;
- 适时调整报警阈值;
- 留出足够的处理时间;
建议监控指标
指标 | 意义 | 获取 |
---|---|---|
opcounters(操作计数器) | 查询、更新、插入、删除、getmore 和其他命令的的数量。 | db.serverStatus().opcounters |
tickets(令牌) | 对 WiredTiger 存储引擎的读/写令牌数量。令牌数量表示了可以进入存储引擎的并发操作数量。 | db.serverStatus().wiredTiger.concurrentTransactions |
replication lag(复制延迟) | 这个指标代表了写操作到达从结点所需要的最小时间。过高的 replication lag 会减小从结点的价值并且不利于配置了写关 | db.adminCommand({'replSetGetStatus': 1}) |
oplog window(复制时间窗) | 这个指标代表 oplog 可以容纳多长时间的写操作。它表示了一个从结点可以离线多长时间仍能够追上主节点。通常建议该值应大于 24 小时为佳。 | db.oplog.rs.find().sort({$natural: -1}).limit(1).next().ts -db.oplog.rs.find().sort({$natural: 1}).limit(1).next().ts |
connections(连接数) | 连接数应作为监控指标的一部分,因为每个连接都将消耗资源。应该计算低峰/正常/高峰时间的连接数,并制定合理的报警阈值范围。 | db.serverStatus().connections |
Query targeting(查询专注度) | 索引键/文档扫描数量比返回的文档数量,按秒平均。如果该值比较高表示查询系需要进行很多低效的扫描来满足查询。这个情况通常代表了索引不当或缺少索引来支持查询。 | var status = db.serverStatus()status.metrics.queryExecutor.scanned / status.metrics.document.returnedstatus.metrics.queryExecutor.scannedObjects / status.metrics.document.returned |
Scan and Order(扫描和排序) | 每秒内内存排序操作所占的平均比例。内存排序可能会十分昂贵,因为它们通常要求缓冲大量数据。如果有适当索引的情况下,内存排序是可以避免的。 | var status = db.serverStatus()status.metrics.operation.scanAndOrder / status.opcounters.query |
节点状态 | 每个节点的运行状态。如果节点状态不是 PRIMARY、SECONDARY、ARBITER 中的一个,或无法执行上述命令则报警 | db.runCommand("isMaster") |
dataSize(数据大小) | 整个实例数据总量(压缩前) | 每个 DB 执行 db.stats(); |
StorageSize(磁盘空间大小) | 已使用的磁盘空间占总空间的百分比。 |
MongoDB 备份与恢复
MongoDB 的备份机制分为:
- 延迟节点备份
- 全量备份 + Oplog 增量
最常见的全量备份方式包括:
- mongodump;
- 复制数据文件;
- 文件系统快照;
方案一:延迟节点备份
安全范围内的任意时间点状态 = 延迟从节点当前状态 + 定量重放 oplog
主节点的 oplog 时间窗 t 应满足:t >= 延迟时间 + 48 小时
方案二:全量备份加 oplog
- 最近的 oplog 已经在 oplog.rs 集合中,因此可以在定期从集合中导出便得到了 oplog;
- 如果主节点上的 oplog.rs 集合足够大,全量备份足够密集,自然也可以不用备份 oplog;
- 只要有覆盖整个时间段的 oplog,就可以结合全量备份得到任意时间点的备份。
全量备份(mongodump、复制数据文件、文件系统快照) + oplog = 任意时间点备份恢复 (PIT)
复制文件全量备份注意事项
- 必须先关闭节点才能复制,否则复制到的文件无效;
- 也可以选择 db.fsyncLock() 锁定节点,但完成后不要忘记 db.fsyncUnlock() 解锁;
- 可以且应该在从节点上完成;
- 该方法实际上会暂时宕机一个从节点,所以整个过程中应注意投票节点总数。
全量备份加 oplog 注意事项–文件系统快照
- MongoDB 支持使用文件系统快照直接获取数据文件在某一时刻的镜像;
- 快照过程中可以不用停机;
- 数据文件和 Journal 必须在同一个卷上;
- 快照完成后请尽快复制文件并删除快照;
Mongodump 全量备份注意事项
- 使用 mongodump 备份最灵活,但速度上也是最慢的;
- mongodump 出来的数据不能表示某个个时间点,只是某个时间段
备份与恢复操作(略)
MongoDB 安全架构(略)
MongoDB 安全加固实践(略)
MongoDB 索引机制(一)
MongoDB 索引数据结构为 B-树。
B-树:基于 B 树,但是子节点数量可以超过 2 个。
MongoDB 索引类型
- 单键索引
- 组合索引
- 多值索引
- 地理位置索引
- 全文索引
- TTL 索引
- 部分索引
- 哈希索引
组合索引的最佳方式:ESR 原则
- 精确(Equal)匹配的字段放最前面
- 排序(Sort)条件放中间
- 范围(Range)匹配的字段放最后面
MongoDB 索引机制(二)
MongoDB 读写性能机制
客户端请求流程图
TODO:补图
应用端-选择节点
对于复制集读操作,选择哪个节点是由 readPreference 决定的:
- primary/primaryPreferred
- secondary/secondaryPreferred
- nearest
如果不希望一个远距离节点被选择,应做到以下之一
- 将它设置为隐藏节点;
- 通过标签(Tag)控制可选的节点;
- 使用 nearest 方式;
数据库端-执行请求(读)
不能命中索引的搜索和内存排序是导致性能问题的最主要原因
数据库端-执行请求(写)
数据库端-合并结果
- 如果顺序不重要则不要排序
- 尽可能使用带片键的查询条件以减少参与查询的分片数
性能诊断工具
mongostat: 用于了解 MongoDB 运行状态的工具
mongotop: 用于了解集合压力状态的工具
mongod 日志:日志中会记录执行超过 100ms 的查询及其执行计划
高级集群设计:两地三中心
容灾级别
- 无备源中心 - 没有灾难恢复能力,只在本地进行数据备份。
- 本地备份+异地保存 - 本地将关键数据备份,然后送到异地保存。灾难发生后,按预定数据恢复程序恢复系统和数据。
- 双中心主备模式 - 在异地建立一个热备份点,通过网络进行数据备份。当出现灾难时,备份站点接替主站点的业务,维护业务连续性。
- 双中心双活 - 在相隔较远的地方分别建立两个数据中心,进行相互数据备份。当某个数据中心发生灾难时,另一个数据中心接替其工作任务。
- 双中心双活 +异地热备 =两地三中心 - 在同城分别建立两个数据中心,进行相互数据备份。当该城市的 2 个中心同时不可用(地震/大面积停电/网络等),快速切换到异地
网络层解决方案
TODO:补图
应用层解决方案
- 负载均衡、虚拟 IP
- 分布式 Session
- 使用同一套数据
数据跨中心同步
- DBMS 跨机房基于日志同步
- 文件系统跨机房基于存储镜像同步
多数据中心要点:
- 正常运行状态 - 集群内一个主节点接受写,其他节点只读。
- 主节点故障 - 主数据中心内自动切主切换时间 5-10 秒
- 主数据中心对外网络故障或者整个数据中心不可用,主数据中心主节点自动降级。从节点升级为主节点选举时间 5-30 秒。
- 双中心双活,分流模式 -需要跨中心写数据,同城双中心需要低延迟专线。
- 节点数量建议要 5 个,2+2+1 模式
- 主数据中心的两个节点要设置高一点的优先级,减少跨中心换主节点
- 同城双中心之间的网络要保证低延迟和频宽,满足 writeConcern: Majority 的双中心写需求
- 使用 Retryable Writes and Retryable Reads 来保证零下线时间
- 用户需要自行处理好业务层的双中心切换