MongoDB技术分享:WiredTiger存储引擎

内容来源:2018 年 10 月 27 日,MongoDB中文社区联席主席郭远威在“2018年MongoDB中文社区 广州大会”进行《WiredTiger存储引擎介绍》的演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:2969 | 8分钟阅读

摘要

本次分享的主题是WiredTiger的存储引擎,主要包含四部分内容,首先介绍MongoDB的插件式存储引擎的架构,然后是WiredTiger的事物,第三部分将介绍Checkpoint机制,最后通过一个案例,分析WiredTiger的cache分配和压缩特性。

插件式存储引擎架构

这个图最下层是存储引擎的最底层,中间还有一个内存的存储引擎。这些存储引擎的上面是MongoDB的文档数据模型,因此不管采用什么样的存储引擎,对于上层的应用程序开发者来说都是透明的。最上层是通过MongoDB数据库支撑的各种应用。可以看到总体的架构,实际上与Mysql有点类似,都是插件式的存储引擎架构。

事务特性与快照隔离级别

关系数据库中的事务是有隔离性的,而MongoDb也支持事务,且符合ACID事务的标准特性。通常事物会有写提交、读未提交、快照等隔离级别,MongoDB默认使用的是快照形式的隔离级别,任何事物开始的时候,先会对内存里面所有写操作但是还未完成的事务做一个拍照,然后记录这些写操作未完成事务的一个状态信息。

对于写操作事务,在写入之前先需要判断操是否与之前其他未完成的事务是否有冲突,如果有冲突的话就会执行失败,过一段时间后再重新提交事务,这里关键的在于能够判断写操作是否与其它的事务发生冲突。

MVCC实现事物的冲突检测与并发

多版本并发控制机制的引入,让我们可以检测是否冲突,它实际上是通过记录每一个事物开始的时候所操作的这条记录的版本号来实现的,这种方式在其他数据库里面同样存在。

比如我们有AB这两个写操作的事务。A事务首先从表中读取到要修改的行数据,读取到库存值为100,行记录的版本号为1。B事务也从中读取到要修改的相同行数据,读取值为100,行记录版本号为1。A事务修改库存值都提交,同时行记录版本号加1,大于一开始读取到的版本号1,因此A事务可以提交。但B事务提交时发现此时行记录版本号已经为2,产生了冲突,所以B事务会提交失败。接着B事务会尝试重新提交,在读取的版本号基础上加1,这样就不会再产生冲突,正常提交了。通过这种多版本并发控制的机制就可以防止B事物修改错误的数据。

典型操作事务执行流程

写操作事务开始执行之前,会对所有正在执行的还未提交事务进行快照。然后将本次写操作的动作保存到Operation_array中,可以从中提取出动作进行回滚,其次将修改的数据以日志形式记录下来,记录到日志缓存区域。写操作事务提交,首先会将日志缓冲区中的数据刷到磁盘上,写入到log文件,数据库意外宕机恢复时需要读取这个文件,重演文件里面的动作。

写操作引起的数据变化,首先写入到WiredTiger存储引擎的cache中,cache中的数据以btree的结构组织,btree的叶子节点是真正存放数据的page,当数据发生更改时page就变未“脏页”(在内存中);存储引擎默认从每60s将“脏页”中的数据写到物理磁盘上进行持久化。

引入checkpoint机制后的典型写操作流程

引入checkpoint后整个流程会发生相应的变化,主要是图中圈出来的地方。Checkpoint会产生在两个地方,一个是在默认情况下每60秒刷新磁盘的时候,将内存里面的脏数据刷到磁盘的时间点上,会在对应的数据文件上产生。另外一个时机是开启journal日志功能后,当日志文件达到2gb的时候,也会发生一次checkpoint。

checkpoint有两个重要的作用,一个是恢复数据库的时候,让我们只需要从最新的checkpoint时间点进行恢复,有效的缩减数据库恢复的时间。另一方面由于checkpoint完成以后,就可以认为内存里面在checkpoint时间点之前的数据都已经安全完整的写到磁盘上了,因此可以释放内存“脏页”所占的内存空间,达到节省内存空间的目的。

WiredTiger对内存的使用情况

wiredTiger对内存使用会分为两大部分,一部分是内部内存,另外一部分是文件系统的缓存。内部内存默认值有一个计算公式{ 50% of(RAM-1GB) ,or256MB },索引和集合的内存都被加载到内部内存,索引是被压缩的放在内部内存,集合则没有压缩。wiredTiger会通过文件系统缓存,自动使用其他所有的空闲内存,放在文件系统缓存里面的数据,与磁盘上的数据格式一致,可以有效减少磁盘I/O。

internal Cache的内部结构

在内存中数据是以btree的结构形式进行存储的,任何数据在写之前,都会先读取到internal cache里面。如上图第一步操作是调用块管理器,块管理器会将磁盘上的数据读取到内存。第二步修改数据的的时候,会重新分配一个新的page,在此基础上进行修改,修改完成后,原来page就会变成“脏页”,接着通过wiredTiger的内部机制将这个“脏页”重新通过块管理器刷到磁盘里面。

与internal cache相关的几个数据结构

首先是原始的page,通过列表形式把所有的数据给串起来。如果有修改动作,会再维护一个修改的page,在修改的page里面又会维护两个链表,保存的是链表的头,插入链表和修改链表的时候分别对应着两个数据结构,这样wiredTiger就不会将每一次的修改和插入操作直接写到磁盘上。当修改操作或插入操作累积到一定程度以后,在内存里面会将这些操作进行规整,整理以后,然后同时一次性的写入到的磁盘里面去。

案例:应用程序开发连接池问题

最后我们看一下与应用程序开发者比较相关的连接池的问题。当时我们有很多应用都用到了MongoDB,所有应用都创建了Mongo Client,这些应用经常会做些增删改查的动作,但是由于我们的服务器配置集成人员可能对分片集群的部署不是很熟悉,所以有些参数也没有关注到,导致了大量连接超时的的一个问题。

后续我们对此进行了分析,找到了具体原因。对于MongoDB来说,它的连接分为有两个部分,一个是驱动程序的连接词,另外一个是在服务器上,其中有一个参数决定了该服务器所能支持的最大的并发连接数。如果驱动程序的连接池远大于服务器所能支持的并发连接数,那么即使客户端程序没有出现连接问题,服务端也会出现连接拒绝的错误。为解决这方面的问题,我们可以分别从客户端和服务端的层面修改他们的默认连接池大小。

以上为今天的分享内容,谢谢大家!

原文发布于微信公众号 - IT大咖说(itdakashuo)

原文发表时间:2018-11-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

通过浏览器缓存来bypass nonce script CSP

最近看了去年google团队写的文章CSP Is Dead, Long Live CSP!,对csp有了新的认识,在文章中,google团队提出了nonce...

26310
来自专栏腾讯移动品质中心TMQ的专栏

JAVA代码覆盖率工具JaCoCo-实践篇

上周 JAVA代码覆盖率工具JaCoCo-原理篇 简单介绍了JaCoCo其生成覆盖率的基本原理,这周的实践篇的主要内容就是将原理应用到实践中,本篇内容全部都是具...

8699
来自专栏芋道源码1024

Java 工程师居家必备的 Intellij IDEA Top10 插件

支持lombok的各种注解,从此不用写getter setter这些 可以把注解还原为原本的java代码 非常方便

4925
来自专栏刘明的小酒馆

事务与一致性:刚性or柔性?

在高并发场景下,分布式储存和处理已经是常用手段。但分布式的结构势必会带来“不一致”的麻烦问题,而事务正是解决这一问题而引入的一种概念和方案。我们常把它当做并发操...

89310
来自专栏哈雷彗星撞地球

Mac 下安装node.js

Node.js 是一个用Chrome's V8 JavaScript engine 构建的 JavaScript 运行时框架。Node.js 使用事件驱动、非阻...

2025
来自专栏北京马哥教育

Nginx+FPM结构模型剖析及优化

随着php脚本语言使用的普及,目前webserice服务大部分都在用nginx+(php-fpm)的结构,了解了其工作过程后才可以在各个方面想办法做调整优化和故...

4496
来自专栏谦谦君子修罗刀

程序员面试闪充--版本管理之SVN

在软件开发过程中,通常一个软件项目要靠多人合作完成的。而在此过程中的修修改改一定会存在一些不可避免的问题。可能一不小心就闹出个大乱子呢。 一、源代码管理的问题 ...

2616
来自专栏张戈的专栏

php平滑重启nginx,彻底清除WordPress的静态缓存

每一次分享技术文章,都是基于自己的痛点,基于自己的需求。这次也一样,所以分享具体方法之前,我先说一下我这次的需求与痛点: 一、需求痛点 在博客集成了代码版缓存功...

4219
来自专栏F-Stack的专栏

F-Stack Q&A 第一期

Q1:F-Stack有中断模式吗,有计划支持吗?在计算密集型的应用中,轮询模式会占用更多的CPU资源? A1:F-Stack暂时只支持轮询模式,后续会支持中断+...

7045
来自专栏实用工具入门教程

如何部署 ftp 文件服务

文件传输协议(英文:File Transfer Protocol,缩写:FTP)是用于在网络上进行文件传输的一套标准协议,使用客户/服务器模式。它属于网络传输协...

6823

扫码关注云+社区

领取腾讯云代金券