我参与MongoDB已经有一段时间了。我从代码中了解它,并且一直在审查4.3开发版本中的更改,以及最近的4.4版本候选版本rc0 – rc7。
有数千个github提交,但是在人类范围内,您会说已经修补了100到200个问题。
从上面的内容,我总结了从v4.2升级到v4.4时将对MongoDB DBA或应用程序程序员产生影响的更改。
首先:回顾2019年的v4.2版本
去年的发行量很大。大部分代码权重都集中在一件事上–分布式事务–但是还有其他值得注意的新功能。
用户可见的功能:
- 分布式交易
- 通配符索引
- 聚合管道取得中等进展
- $ currentOp添加了idleSessions,idleCursors等(最终)变得全面
- MMAP存储引擎已删除
驱动因素:
- 字段级加密(测试版)
- (仅限MongoDB Atlas)通过Lucene进行全文索引
内部:
- FlowControl(主节点上的节流阀)
- 改进索引构建
- 改善了初始同步
- 配置文件REST / EXEC指令
- 从mongos节点清除了最后一个均衡器管理任务
现在:2020年发布的MongoDB v4.4-rc *'Beta’版本
用户可见的更改
- 对冲读取
- fineCollectionShardKey(=添加更多字段,仅后缀结尾)
- 1个新的聚合阶段:$ unionWith
- 聚合管道MapReduce:$ accumulator,$ function
- AWS IAM基于角色的身份验证(仅限企业?)
- 只读交易
- 复合哈希分片键
管理和内部改进
- 可恢复的初始同步
- initialSyncSourceReadPreference
- 预热:
通过使用镜像读取操作创建辅助节点
mongos节点的路由表,碎片连接 - 最小Oplog窗口设置
- 索引在副本集中同时构建并一起提交
- “ logv2”结构化文本和json日志记录
- 后台验证命令
- WiredTiger级别的备份改进
比较发布
我对以上内容的个人总结是:
4.2极大的优势
- 分片通用数据库中的事务是头条新闻
- (驱动程序端)字段级加密
4.4天生温和
- 进行调整以改善冷启动或临时中断时的延迟
- 聚合管道功能增加约5%,+ MapReduce重构
“那么您是说…4.4是维护版本?”
是。但我爱它!
我对软件行业的普遍观察是,那些导致管理员(而不是开发人员)浪费时间的错误会在公司首先尝试扩大其市场份额时永久推迟。
v4.4消除了这些错误的一些长期未解决的示例。技术债务的回报远不止新功能的增加。
我一直希望MongoDB从v3.4开始做一个主要维护的主要版本。
愿望实现了!
4.4中修复的旧问题
可恢复的初始同步
以前未解决的问题场景:
您的旧弱服务器需要替换为更好的服务器,因为它无法处理最近的高负载。您通常只会复制并降级,但这会失败,因为主数据库花费的时间太长,无法将数据提供给初始同步的新节点。
我知道两个最常见的问题,无法进行初始同步:
- 在克隆步骤完成时退出oplog
在v3.4中已修复。(操作日志不断获取到目的地) - 花费很长时间可能会发生临时网络错误,从而使正在进行的初始同步无效。
由于可恢复的初始同步,现在已在v4.4中修复。
initialSyncSourceReadPreference
以前未解决的问题场景:
主节点过载,但辅助节点性能更好(例如,因为它们没有读取负载)。添加新节点失败,因为主节点无法提供足够的数据来进行初始同步。
可用性错误:您无法在初始同步之前或期间更改同步源。(通常选择主要的。)
现在感谢SERVER-38731:
–setParameter initialSyncSourceReadPreference = <主机:端口>
最小Oplog窗口配置设置
先前的风险情景:
假设您通常每小时可以获得500MB的更新。您配置的20GB oplog大小(以字节为单位)始终大于24小时窗口。但是随后需求上升;现在获得100倍的更新。Oplog窗口变为<30分钟。
这段时间突然增加了写负载,这是一个危险的时间。在重新启动之前,您可能不做任何维护操作就无法退出操作日志。您可能会被要求“做某事,做任何事!” 处理高负载事件。例如。仅在风险更大时才被迫进行大规模升级等。
从v3.6开始,您可以动态调整oplog(replSetResizeOplog)的大小,因此您可以快速添加所需的额外Oplog窗口时间。但是,如果可以自动发生,那就太好了-毕竟问题可能出在正常工作时间之外。
解决方案:新的storage.oplogMinRetention Hours配置选项。
“ logv2”结构化文本和json记录
场景:
- 您从事支持MongoDB的工作
- 一个神秘问题需要处理上百条日志行
- MongoDB日志文件是半结构化的=语法上不可靠
造成此问题的主要原因是命令详细信息是由最小的BSON字符串格式化程序打印的。可读,但解析不可靠。
没有日志诊断工具可以永久解决此问题。这些日志永远无法支持可靠的自动化服务。
但是现在,(新)systemLog.logFormat选项默认为“ json”。因此,尽管您可以使日志输出看起来像旧格式:
2020-05-14T01:32:32.969+09:00 I COMMAND [conn6] command test.foo command test.foo command: find { find: “foo”, filter: { $oid: “5ebc21120070b8d72d002586” …
默认情况下,现在改为:
{“t”:{“$date”:”2020-05-14T01:32:32.969+09:00″},”s”:”I”, “c”:”COMMAND”, “id”:51803, “ctx”:”conn6″,”msg”:”Slow query”,”attr”:{“type”:”command”,”ns”:”test.foo”, “appName”:”MongoDB Shell”, “command”: {“find”:”foo”,”filter”: {“_id”: {“$oid”:”5ebc21120070b8d72d002586″}},”lsid”:{“id”:{“$uuid”:”e442fa30-ba0c-4cf1-b208-c812…..
这是完全合法的JSON!吸引了我很多。Shell脚本编写者提示:您应该尝试使用jq命令行工具。这是“ jq”的输出。
{
"t": { "$date": "2020-05-14T01:32:32.969+09:00" },
"s": "I",
"c": "COMMAND",
"id": 51803,
"ctx": "conn6",
"msg": "Slow query",
"attr": {
"type": "command",
"ns": "test.foo",
"appName": "MongoDB Shell",
"command": {
"find": "foo",
"filter": {
"_id": {
"$oid": "5ebc21120070b8d72d002586"
}
},
....
旧问题赋予新生命
MapReduce大约在十年前风靡一时,MongoDB拥有内置的v1.8 MapReduce框架(甚至更早版本中也具有向前不兼容的功能)。
我很惊讶它没有被删除(即4.2)。我不喜欢的原因:
- 将科学怪人放在主要QueryEngine代码的一侧。科技债务。
- MongoDB的MapReduce意味着在服务器端运行Javascript。速度慢了很多,安全漏洞打开似乎只是时间问题。
- 几乎没有人使用过它。(我的偏见是我的历史涉及大型部署。也许在小型数据库用户中它比较受欢迎。)
需要某种解决标准CRUD命令无法满足的需求的方法,但是通过聚合管道可以更好地实现这一点。它从v2.2开始就存在,并且在我看来是v3.2或v3.4完全成熟。
似乎使用慢速,CPU密集型服务器端Javascript的map reduce范例将继续存在。请参阅4.4文档中$ group,$ bucket和$ merge阶段中可以使用的新$ function和$ accumulator运算符。
一方面,在聚合管道框架中比其他任何地方都更好。
但另一方面:使用$ function运算符的聚合阶段将不利于优化–查询计划器设计无法对来自任意javascript代码的文档进行假设。管道可能会将它们视为“阻塞”阶段,这会导致延迟增加。
4.4的新功能
fineCollectionShardKey
到目前为止,更改分片键始终意味着删除集合并重新开始。所有分片节点,configsvr节点和mongos节点上的分片元数据都无法立即更改。当然,也不能根据新分片键的排序和分区将数据立即移动到新分片。
当大多数人意识到他们选择了错误的分片密钥时,这仍然是游戏的状态。在这种情况下,他们发现大部分查询分散在所有分片上,而不是针对性的。或者当他们看到不可分割的巨型块出现时。从我的角度来看,多年来一直在全球范围内为MongoDB提供支持,这个坏消息一天发生了很多。这就是为什么有关MongoDB Sharding的文档,演示文稿和课程都强调从一开始就选择正确的分片键的重要性。
但是-在特殊情况下-您认为可以通过在分片键的末尾添加新字段来保存自己吗?例如。
{“制造商”:1,“ product_serial_no”:1}->
{“制造商”:1,“ product_serial_no”:1,“ reseller_id”:1}
要么
{“作者”:1,“ article_id”:1} –>
{“作者”:1,“ article_id”:1,“草稿版本”:1}
如果是这样,那么您就可以了解v4.4的fineCollectionShardKey。显然,它使用以下逻辑,因此mongos节点和分片节点可以切换,而无需每个人一次同步的步骤。
- 文档保留在已经存在的相同碎片上。
- 最后带有额外字段的新索引可以满足旧索引的所有需求。
镜像读取
您是否还希望将对主节点的读取也转发到随机的辅助节点?结果是否立即丢弃在原处?
即使您的直接回答是“当然不会流血”,真正的答案可能是:是。
简而言之,这样做的结果是,辅助节点上RAM中的WiredTiger缓存将被与主节点所使用的大约相同的文档填充所预热。如果没有镜像读取,则辅助节点的缓存将仅包含通过复制更新的文档。
当选举发生时,成为主节点的未变暖节点将进行磁盘读取,以回答很多查询。我估计用大量所需的活动数据集初始化缓存将需要10秒钟的时间。在那段时间内,底层存储引擎访问内存(对于单个索引查找通常为0.1ms)将阻塞等待磁盘的时间(通常为1〜10ms,具体取决于磁盘类型)。操作等待时间将跳跃一段时间,例如十倍或更差。
如果您对延迟的SLA要求严格,并且注意到选举后SLA已被破坏,那么镜像读取将为您带来成功。
$ unionWith
它是UNION,但适用于MongoDB。关于这个新的聚合管道阶段,几乎没有其他可以添加的内容。我只想指出,它可以使用自己的管道运算符,并且如果要将预先聚合或预先过滤的结果集结合在一起,则需要使用它。
要获得“ UNION DISTINCT”结果,您需要在$ unionWith阶段之后执行$ group阶段。逻辑上确实,您只需要记住没有单关键字的方法即可完成此操作。
对冲读取
如果您希望接受较快交付的陈旧二级读取,而不是首选交付速度较慢的主节点读取,请使用这些。但仅作为后备,当maxTimeMSForHedgedReads(默认值= 150ms)时间范围内没有来自主节点的响应时。
它不能保证所有读取都将在执行时间的硬上限内返回。二级读取也可能很慢。但是,您要购买通常会更好的第二次机会,这将大大改善您的后端延迟。
注意:仅在分片群集中受支持,即使对于非分片副本集似乎可以轻松实现也是如此。
GA发布之前可能使用的通配符
GA版本尚未发布-到目前为止的公告仅表示“今年夏天”。可能有些事情可能会被溜走。
WiredTiger热备份
WiredTiger存储API使创建热备份成为可能–从单个快照时间点开始,每个* .wt文件的副本。这在MongoDB社区版中未公开,但在Percona Server for MongoDB中通过$ createBackup命令提供。这可以保存到文件系统或AWS S3。从4.2开始,MongoDB Enterprise Edition包含$ backupCursor聚合阶段,但是就文档而言,这仍然是隐藏的。
现在,合并到v4.4中的WiredTiger更新包括进一步的增强功能,例如能够在一个快照点和另一个快照点之间进行增量更改。这样就可以从每个分片和配置服务器副本集(通过分布式逻辑时钟同步到同一时间点)创建群集范围的备份。
MongoDB是否会停止混淆API,以便MongoDB Community Edition可以进行热备份?目前,我们必须等到4.4正式发布并且其文档变为“当前”状态而不是“即将到来”状态才能查明。
否则,外部工具Percona Backup for MongoDB似乎是进行一致的群集备份的唯一免费解决方案。
新的存储引擎?
从v4.2左右开始,开发一个看不见的存储引擎是可行的。鉴于常见的MongoDB存储API和与外部库(wiredtiger,rocksdb等)的绑定之间的代码宽度相对较窄,可以很容易地在私有fork中完成工作。
在正常的开放源代码许可下,有两种值得注意的存储引擎候选者:
- 在2020年初,大约一年的社区工作量导致在MongoDB的实验室github中共享了与v4.0兼容的MongoRocks引擎。然后在5月,它进行了增强以支持支持分布式事务所需的额外时间戳。也就是说,必须通过4.2(和4.4)兼容性的关键测试。
- 在异构内存存储引擎是开源最近和私下分享,我相信前几年。(请参阅此博客,了解有关动手操作原型的信息。)
- 另一种可能性是,WiredTiger的抑制的LSM模式将与当前的默认BTree模式一起启用。
但是无论哪种方式,我都不会在今年夏天的v4.4版本中看到这种情况。
文章来源:https://www.percona.com/blog/2020/06/11/mongodb-4-4-coming-out-soon-what-does-the-code-tell-us/




