草庐IT

MongoDB写入数据策略

司马辽太杰 2023-03-28 原文
上篇文章介绍了Mongo读取数据的策略(​​MongoDB读数据策略​​),主要是readconcern、readpreference两参数,其中readconcern作用于服务端,决定了什么时候能读取到数据;readpreference在客户端配置,决定读哪个节点的数据。本文将要介绍Mongo的写入策略,在介绍写入策略前,先简单说明MongoDB的Journaling特性。

Journaling介绍

MongoDB也有防carsh能力,和MySQL类似,也是通过预先写日志(WAL)到文件实现,这文件就是Journaling功能。

To provide durability in the event of a failure, MongoDB uses write ahead logging to on-disk journal files.

◀日志文件▶

开启Journaling功能后,Mongo 会在数据库目录下创建 journal目录,用来存放journal日志,以WiredTiger引擎为例,文件格式是WiredTigerLog.<sequence>,其中<sequence>是从0000000001开始的零填充数字。journal日志文件默认大小为100 MB,超过该限制后,将创建一个新的日记文件,并会自动删除旧的日志文件,仅保留从上一个检查点恢复所需的文件。所以journal日志文件一般情况下只会生成两三个,除非每秒有大量的写操作发生。

◀日志记录▶

journal记录有这几个特点:

它包括由初始写入引起的任何内部写入操作。例如,对集合中文档的更新可能会导致对索引的修改;WiredTiger创建单个日志记录,其中包含更新操作及其关联的索引修改。

每个记录都有一个唯一的标识符。

WiredTiger的最小日志记录大小为128字节。

另外,为了提高存储效率,MongoDB牺牲了一些CPU性能,对WiredTiger引擎对日志数据使用压缩存储,默认压缩方式是snappy压缩,也支持其他压缩方式,比如:zstd、zlib等,可以通过下面方式设置。

storage.wiredTiger.engineConfig.journalCompressor

总之,Journaling 是MongoDB中非常重要的一项功能,类似于关系数据库中的事务日志。Journaling能够使MongoDB由于意外故障后快速恢复。在2.0版本后,默认开启了该功能。和MySQL一样,Mongo 实例启动时会检查journal日志文件,确认是否有需要恢复的数据。不过由于提交journal日志会产生写入阻塞,所以它对写入的操作有性能影响,但在生产环境中通常还是开启Journaling的。

数据写入策略

writeconcern 是Mongo针对写操作的参数,表示写请求对 mongod 实例的确认级别,决定数据的持久性。它可以用下面三个选项表示。

{ w: <value>, j: <boolean>, wtimeout: <number> }

◀writeconcern 选项▶

w指定写操作需要应用到多少个数据节点才能返回成功,可以为0、1、2、3或者majority。

  • w: 0 表示客户端不需要收到任何有关写操作,就直接返回成功。
  • w: 1 表示写主成功,就直接返回成功。
  • w: majority 需要收到多数节点(含主节点)关于操作执行成功的确认,具体个数根据复制集配置自动得出。比如,一主两从3节点的集群,则需要2个节点确认写入成功即可。
  • w: N(N > 1)表示N个数据节点确认才返回成功。w 值越大,对客户端来说,数据的安全性保证越强,同时写操作的延迟越大。w 设置的节点数越多,等待的延迟也就越大。如果 w 等于总节点数,那么一旦其中某个节点出现故障就会导致整个写入失败,这也是有风险的。另外,针对Hidden、delayed和priority为0的数据节点,官方也特别做了说明,如下:
NOTE

Hidden, delayed, and priority 0 members can acknowledge w: <number> write operations.

Delayed secondaries can return write acknowledgment no earlier than the configured slaveDelay.

注意:

a、副本集中Hidden、delayed和priority为0的成员,可以确认w: <number>的写操作。

b、延迟节点的返回写ack,不会早于配置的slavedelay值  。

如果集群有 3 三个数据节点,在w: majority模式下 ,只需要写入两个数据节点即可返回,流程如下:

j表示写操作是否要被持久化,只能选填 true 或 false。

  • j:false 表示写操作到cache即算作成功。
  • j:true 表示写操作到文件中才算成功。
从3.2版本后,如果指定j:true,即使 w:0 ,只有在请求的成员数(包括主成员)写入日志后才返回数据。因此,j:true设置保证了MongoDB的数据持久化。

Changed in version 3.2: With j: true, MongoDB returns only after the requested number of members, including the primary, have written to the journal.

另外,仅仅j:true 不保证集群 failover 时发生回滚的写操作。

j: true does not by itself guarantee that the write will not be rolled back due to replica set primary failover.

wtimeout:返回确认的超时时间,单位为毫秒。

如果写入操作超过该值,则返回错误,即使最终写入是成功了,但数据库不会撤销超时写入的数据。如果没有指定 wtimeout 值,则写入操作将无限期阻塞,wtimeout:0 等同于该选项未设置值。同时,这个参数和 WriteConncern 的w值有关,并且只适用于w大于0的情况。比如:w:0,表示可以超时无限大,则不返回错误;w:1,只和主节点确认的超时时间;w:majority,表示需要和多数节点确认超时时间。

◀数据提交策略▶

MongoDB也有和MySQL有类似的提交策略,是由 commitIntervalMs 参数控制,它是日志持久化的间隔时间(以毫秒为单位)。如果想要更好的数据安全,可以设为每毫秒对cache中的数据做硬盘层面的sync;如果需要更好的写入性能,最大可以改为每500毫秒做一次sync。它的取值范围是1 ~ 500毫秒,默认值是100毫秒,不支持in-memory 存储引擎。

总结

MongoDB 写入策略包括以下几个方面:

  • w:指定写入数据后需要在多少个节点上同步写入成功后,才返回确认信息。
  • j:设置 j:true 会将数据写入日志中,可以在节点宕机时恢复数据。但是 j:true 并不保证数据已经写入磁盘文件中。
  • wtimeout:指定写入超时时间。当写入操作达到超时时间时,即使最终成功写入也会返回错误信息。
在实际使用中,可以根据具体的业务需求和系统环境来选择适合的写入策略,以达到最佳的性能和可靠性。例如,在数据一致性要求高的场景中,可以使用 majority 写入确认来保证数据同步的可靠性。而在性能要求高、数据不敏感的场景中,可以使用 w 值较小的写入关注点来提高写入性能。

本文转载自微信公众号「云数据库技术」,可以通过以下二维码关注。转载本文请联系云数据库技术公众号。


有关MongoDB写入数据策略的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  5. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  6. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  7. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  8. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  9. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  10. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

随机推荐