本次直播分享次要分为五个局部开展:
第一局部:次要介绍 MongoDB 的外围劣势;
第二局部:次要总结云上 MongoDB 用户常见的一些问题;
第三局部:介绍腾讯云 MongoDB 智能索引举荐实现流程及其实现原理;
第四局部:介绍腾讯云 MongoDB 内核 SQL 限流性能及其实现;
第五局部:次要分享腾讯云 DBbrain for MongoDB 的两个典型诊断案例
MongoDB 有哪些外围劣势?
MongoDB 是一个基于分布式文件存储的数据库,由 C++ 语言编写。首先,咱们来看下它有哪些外围劣势,上面列举几个:
分布式
MongoDB 是开源的分布式数据库,能够解决传统数据库存储容量上的瓶颈问题,用户不用再提前思考分库分表等操作。同时,MongoDB 也是一个人造高可用的数据库,比方在一主两从的工作模式下,当主节点意外宕机,从节点就会接替主节点的工作,整个过程毋庸依赖任何第三方组件。
lschema-free
MongoDB 的表构造绝对自在,增加字段方便快捷,相比于传统数据库在一张大表里增加字段,运维老本被大大降低。
高性能
MongoDB 晚期应用 MMAPv1 存储引擎,起初替换为 WiredTiger 存储引擎,它反对行级粒度锁、热点数据缓存等个性,这给 MongoDB 带来了高性能、低提早、高吞吐等能力。
高压缩比
在默认配置下,MongoDB 应用 snappy 压缩算法,可达到均匀 2 到 4 倍的文本数据压缩能力,如果应用 zlib 压缩算法则能够晋升到 3 至 7 倍,然而 zlib 对性能有肯定影响,因而线上通常应用默认配置即可。经测试,在默认配置的状况下,同样一份数据写入 MongoDB、MySQL、ES 的实在磁盘耗费比约为 1 : 3 : 6。
欠缺的客户端拜访策略
MongoDB 反对五种平衡拜访策略:
primary:读主节点,当主节点异样时,可能造成短期内的业务异样。
primaryPreferred:主节点优先,当主节点异样时能够读从节点。
secondary:读从节点,把流量平平衡调配给多个从节点,实现负载平衡。
secondaryPreferred:从节点优先,如果从节点异样,则读取主节点。
nearest:就近拜访,在多机房场景下,就近拜访能够避免出现跨机房拜访的状况。
腾讯云 MongoDB 外围劣势
腾讯云 MongoDB 以后已服务于游戏、电商、社交、教育、新闻资讯、金融、物联网、软件服务、汽车出行、音视频等多个行业。
相比用户自建 MongoDB 数据库,腾讯云 MongoDB 在智能运维、可用性、安全性、性能等方面更具劣势。同时通过 DBbrain 提供一站式监控的诊断剖析,并且能给出相应的优化倡议,同时也集成了官网的常用工具,让用户应用更不便。
此外,腾讯云 MongoDB 还在内核里做了一些定制化的开发,比方解决表数量达到百万级别时的性能问题、提供 SQL 限流性能缩小流量过大导致的集群不可用问题。平安方面,腾讯云 MongoDB 能够将数据恢复到 7 天内的任意工夫点,并且提供 24 小时的业余反对服务。除此之外,也人造集成了云上高可用、高性能等通用能力。
云上 MongoDB 集群常见问题
3.1. 分片集群应用问题
云上分片集群常常遇到的问题如上,次要包含大表不启用分片、分片形式不是最优、片建抉择不当、高峰期没有设置 balance 窗口集群抖动。
大数据量大流量表不启用分片
有些用户有错误认识,就是从正本集切到多分片集群,认为啥也不做,集群人造性能就是正本集好几倍,存储容量默认是正本集几倍。
分片集群如果不启用分片性能,数据和流量默认都会到主分片,也就是分片集群中的一个分片,因而大数据量、大流量集群切记启用分片性能。
分片形式
通常状况,如果用户次要是点查,例如依照订单 id 查问,则能够抉择 hash 分片形式,这样除了保障读取性能同时,同时确保数据离散写入不同分片,保障了写入性能并防止了数据不平衡引起的大量 moveChunk 操作。
如果用户查问次要是范畴查问,个别倡议采纳范畴分片形式。
如果既有大量点查,又有大量范畴类查问,为了防止范畴查问引起的所有分片播送查问,因而倡议范畴分片,这样点查和一般范畴查问都能够从一个分片获取数据。
片建抉择
分片集群片建通常抉择高频类查问字段作为片建字段,同时留神 insert、update 等写入操作肯定要带上片建字段,否则 mongos 会返回异样信息,因为不晓得该去写操作那个分片的数据。
balance 窗口设置
分片集群抖动很多都和 moveChunk 相干,moveChunk 操作会减少锁、资源耗费,同时波及路由刷新等流程,因而倡议分片集群设置 balance 窗口期,尽量业务低峰期进行 balance 操作。
分片形式和片建抉择比拟非凡,和业务应用形式关系密切,因而须要提取评估,确保读写性能最优。
3.2. 索引问题
索引问题留神包含索引操作过程问题和索引内容问题,上面进行具体阐明。
索引操作过程不合理
以正本集增加索引为例,createIndex 创立索引胜利实际上在主节点胜利后就返回了,从节点还没有增加索引胜利。如果用户做了读写拆散,并且从节点压力比拟大,这时候可能从节点执行索引工夫会更长,如果用户主节点执行胜利后,createindex 返回立马又增加其余索引,这时候可能存在多个索引在从节点执行的状况,这样从节点压力会很大。
此外,用户如果增加一个索引“胜利”,这时候从节点实际上还在执行该索引,用户立马删除该表某个索引,这时候从节点会不可拜访,因为删除索引会增加 MODE_X 排它锁。
如果业务十分外围,不容许任何抖动,还能够应用通过滚动增加索引形式来增加索引,具体操作步骤详见:
https://www.mongodb.com/docs/…
https://www.mongodb.com/docs/…
MongoDB 智能索引举荐实现
智能索引举荐次要是基于索引规定和代价估算来实现的,整体架构如下:
智能索引举荐分为四个模块:
agent 模块:实时收集 mongod 节点日志,而后输入日志到 kafka 模块。
kafka 模块:存储 mongo 节点收集的日志信息。
日志分类模块:kafka 有用慢日志收集,并进行分类解决。
代价估算模块:模仿 MongoDB 内核执行打算过程,进行候选索引代价估算。零碎整体的工作流程如下:每个 MongoDB 节点上布署有 agent 节点,它会实时采集所有有用的日志并存储到 Kafka 里,日志分类解决模块会从 Kafka 里把须要的日志提取进去进行分类,而后把分类好的日志交给索引代价计算模块进行计算,最终失去最优索引。
其中,agent 模块和 kafka 模块的逻辑绝对简略,这里重点介绍日志分类模块和代价估算模块。
4.1. 日志分类模块的实现步骤
第一步:提取无效的慢日志。
并不是所有的慢查问日志都须要解决,只需提取存在索引问题的慢查问,诸如索引不是最优、全表扫描,这类日志才须要提取。如果判断索引不是最优?
答案是比照走索引时候数据扫描的行数与理论返回数据的行数,如果差值较大,就判断这个索引不是最优的,须要进一步优化。
第二步:依据 filter 对 SQL 分类。
同一个库表中会有很多查问,查问条件不尽相同,属于同一类的 SQL 须要满足几个条件,即库、表、命令、查问条件完全相同。前三个条件容易辨别,比方同库同表状况下,查问条件 (包含 find、update、delete 等) 雷同算一类,而查问条件雷同的前提是查问关键字要雷同且操作符属于同一类,同时要疏忽查问字段程序。
日志聚合解决
定期从 DB 中获取分类好的 SQL 信息交给代价估算模块进行解决。
4.2. 索引代价计算模块解决流程
形象语法树生成及合成:从日志分类解决模块中获取对应 SQL,形象语法树,同时进行合成。
依据索引规定生成候选索引:依据最优候选索引规定生成侯选索引的流程,能够参考腾讯云数据库公众号公布的文章:《云上 MongoDB 常见索引问题及最优索引规定大全》一文。
对候选索引进行代价估算:从源集群随机抽样数据,对候选索引进行代价估算,最终得出最优索引。上面重点介绍候选索引代价计算过程。
4.3. 候选索引代价计算
代价计算次要步骤:
随机采样大量数据:从线上实例随机采样大量数据,为了尽量减少对线上集群影响,优先采集暗藏节点,如果没有暗藏节点则采集从节点。同时管制采样数据量和采样频率,尽力缩小对线上集群影响。
获取每个字段区分度:依据采样的数据获取查问条件对应字段的区分度。
依据裁剪后的子树依照索引规定生成候选索引:这里能够参考腾讯云数据库公众号输入的 MongoDB 索引规定大全。
每个候选索引代价计算:对每个候选索引模仿内核执行打算流程确定计算代价老本。
假如有 [{work:1, city:1, province:1}, {city:1, province:1, age:1}]) 这个候选索引,其代价计算过程如下图所示:
下面的候选索引对应的执行打算流程是:如果查问抉择该候选索引执行,其执行打算首先进入 index scan stage,而后进入 OR stage,OR stage 执行实现后就会开始做 fetch 操作,最初就会得出整个流程扫描了多少行数据、失去了多少行数据,以及整个流程的执行工夫。
腾讯云的代价估算是由一个旁路模块实现的,实现难度较大,须要对整个内核执行打算有较透彻的了解。所以对于自研用户,如果研发人力无限,能够采样数据到新的 MongoDB 集群,依据候选索引规定,同时借助内核已有的能力进行字段区分度、候选索引代价计算,最终得出执行这个索引扫描了多少行、返回了多少行、执行了多长时间,最终也能够失去最优索引。
智能索引举荐以后曾经服务化,逐渐会凋谢给用户应用,如果大家有趣味能够去体验。索引举荐基本上能在半小时内发现实例上存在的索引问题,除了举荐最优索引外,还能够把实例上的无用索引和反复索引也找进去,这样能用起码的索引满足用户需要,性能等方面也会更好。
4.4. 腾讯云 MongoDB 索引举荐总结
快:慢查产生半小时左右推出最优索引
准:举荐索引为候选索引中代价计算最小的索引
稳:采样计算过程对云上集群影响较小,索引增加过程减少保护措施,同一实例同一时刻最多同时增加一个索引。
MongoDB 内核 SQL 限流实现
5.1. 为什么要做 SQL 限流?
首先,咱们先思考这样一个问题:为什么要做 SQL 限流?
一方面,当流量过大、负载过高,数据库抖动可能造成雪崩时,就能够限度一下流量,保障一些申请能失常返回。另一方面,有些用户为了节约老本,将多个用户的数据写到了同一个实例不同表中,某一时刻可能呈现用户新上的接口不对或其它异常情况,导致流量十分高,就会影响这个实例上的其余外围业务,这时就能够通过限流对异样或者不太重要的表做限流解决,保障外围的业务流量能失常拜访。此外,还有一些突发扫表,高危操作等都能够通过限流进行限度。
5.2. 内核哪个地位减少限流性能?
那么,咱们在内核哪个中央做了 SQL 限流性能呢?
先捋一下 MongoDB 的整体架构,它是分层的,第一层是网络收发模块,网络收发过后,交由命令解决模块把这些 SQL 解析进去,而后这些 SQL 会进入查问引擎模块、读写模块以及并发管制模块等流程。
5.3. SQL 限流外围实现
咱们整个 SQL 限流模块是加在命令解决模块之后的,加在这里有什么益处呢?因为在这里曾经拿到了具体的 SQL,并且在并发管制之前做到 SQL 限流,防止 SQL 限流外面的操作会影响并发管制和数据库读写访问,避免与上层的并发管制模块产生抵触。
内核 SQL 限流的整体流程如下:
首先,在 DBbrain 界面上能够配置策略规定,比方 SQL 类型、并发数,能够配置定时敞开还是手动敞开,定时敞开是指最多运行多少工夫,手动敞开就是关上后始终执行,除非人为手动敞开进行。
而后,是依据读写 SQL 关键字,配置完规定,就能够对指定库、表或者指定的 SQL 语句做限流。整个流程是首先在 DBbrain 的控制台下发规定,以分片集群为例,就下发给分片集群的 config server,config server 接管到后把这个规定写到 config server 的一个表里,shard server 的每个 mongod 定期从 config server 获取这些规定并加载到本人内存里,所有的 mongod 节点内存里就会有残缺的规定数据存在,当发动一个申请,通过客户端到代理,再到 mongod 节点的时候,进行限流规定匹配,触发限流操作。
至于为什么抉择在 mongod 上做限流,而不是在 mongos 上。次要是因为,mongos 下面的流量管制是由客户端基于 IP 做哈希的,可能导致流量不平均。此外,线上有正本集的集群,也有分片集群,在 mongod 上做能够实现代码对立。在 mongos 上做限流,因为 mongos 之间是无状态的,无奈保障互相的管制达到肯定的级别。最初,瓶颈个别都在 mongod 节点上,所以就抉择在 mongod 下面做限流。
5.4. SQL 限流规定及规定匹配限流流程
上面持续分享腾讯云 MongoDB SQL 限流的限流规定和规定匹配限流流程。
限流规定:
至于 SQL 限流规定次要蕴含哪些信息,次要包含 SQL 类型(比方增删改查)、限流工夫以及并发数,并发数能够限度某类申请同时拜访咱们 DB 的并发量,另外就是关键字,能够匹配库,也能够匹配表,甚至能够匹配具体的 SQL,这样就能够实现指定的库、表和某一类型的 SQL 限 流。
申请匹配规定流程:
当一个申请达到 MongoDB 后,具体的解决流程是,先看这个实例是否启用了 SQL 限流性能,如果已启用,则提取用户申请中的库、表和 SQL 关键字信息,下一步和配置的限流规定做匹配,判断这类 SQL 是否有可用的 ticket。
ticket 代表并发管制中的并发数,如果没有可用的 ticket,比方 ticket 值为 0,就间接限度这个申请,返回客户端异样。如果有可用的 ticket,就把 ticket 值减 1,同时拜访 DB,拜访到 DB 后就将数据返回给客户端,同时开释以后 ticket,前面的申请就能够持续复用,这就是整个限流工作流程。
SQL 限流体验如下:
智能诊断案例分享
(路由问题、排它锁问题)
以下内容是在 MongoDB 社区分享的两例典型案例,如果踩坑结果十分比较严重,因而这里独自一节分享。
6.1. 路由异样诊断优化
mongos 1 触发 chunk [1-50}从分片 2 迁徙到分片 1,整个迁徙过程 mongos 1、分片 2 及分片 1 都能感知到这个事件,因而他们都有最新的路由信息。然而,mongos 2、mongos 3 和分片 0 感知不到这个事件,因而还是老的路由信息,认为 chunk [1-50}还是在分片 2,实际上数据曾经迁徙到了分片 1。
因为客户端读走从节点,mongos 1 收到例如 xx =20 的申请后,查问内存中路由信息,数据在分片 1,因而从分片 1 从节点获取数据,因为 chunk [1-50}对应的数据全在分片 1,因而能够拜访到数据。
因为从节点默认不会做路由版本检测,因而当 mongos 2 或者 mongos 3 拜访 xx =20 的数据,该数据路由记录 chunk [1-50}在分片 2,因为数据曾经从分片 2 迁徙到分片 1,分片 2 实际上曾经没有该数据了,因而拜访不到数据。
优化办法:
暴力优化办法:db.adminCommand({“flushRouterConfig”:1}),强制路由刷新,存在性能抖动。该操作会状况内存缓存的所有路由信息,新申请进来后须要从 config server 获取所有 chunks 信息加载到本地内存,如果 chunks 较多,整个过程 mongos 拜访不可用。
腾讯云优雅优化办法:实时检测每个 mongos shardVersion 主版本号,如果存在差别,则版本较低的 mongos 被动拜访一次每个分片主节点,确保 mongos 从 config server 获取最新增量路由信息。这个过程只会从 config server 获取差别的 chunks 信息,因而影响较小。
6.2. MODE_X 排它锁检测
很多高危操作会增加排它锁,会引起库表维度,甚至是整节点维度阻塞不可用,例如上面这些操作都会增加 MODE_X 独占锁:
①. 表加索引过程中删除索引
②. 前台加索引
③. 表重命名
④. 索引重构
⑤. ……
MODE_X 排他锁检测办法:
定期实时获取 lockInfo,获取其中的排它锁对应 DDL 操作,实时同步用户。
对于作者:杨亚洲
MongoDB 中文社区成员;
现任腾讯云数据库专家工程师;
前滴滴出行技术专家;
前 OPPO 文档数据库研发负责人;
始终专一于分布式缓存、高性能服务器、分布式存储、数据库、中间件等相干研发。