前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >9月.精华文章推荐

9月.精华文章推荐

作者头像
MongoDB中文社区
发布2018-08-14 16:48:26
6030
发布2018-08-14 16:48:26
举报
文章被收录于专栏:MongoDB中文社区

1.《GDPR: Impact to Your Data Management Landscape:Part 3 》

作者:上海小胖 (Miracle Young)

2.《MongoDB Authentication slow my TPS?》

作者:上海小胖 (Miracle Young)

3. 《MongoDB ServerStatus.global-Lock深入解析》

作者:张友东


《GDPR: Impact to Your Data Management Landscape:Part 3 》

作者:上海小胖 (Miracle Young)

与欧盟的通用数据保护规定的(GDPR)1时间越来越近了。从2018年5月25日起,任何一个未能满足新法规的组织将面临高达全球收入4%的罚款,或者是2000万欧元——无论哪种罚款——任何进一步的数据处理活动都将遭受潜在的叫停风险。因此无论是否加入了欧盟,只要你正在以任何方式处理欧盟公民的数据,就必须服从GDPR的条约。

  也就是说,该规定不应该被视为一些不知名的官文强加的。相反,对于更积极的组织来说,它提供了一个机会来改变他们在数字经济中与客户的关系。

  在接下来的博客系列中,将深入去了解这份规定,了解这份规定对我们而言意味着什么:

  • 第1部分,将提供一个GDPR的入门介绍–这将会覆盖规定的基本原理和关键措施。
  • 第2部分,将探讨GDPR对我们的数据平台意味着什么。
  • 今天的第3部分,我们将讨论MongoDB的产品和服务将如何支持我们的业务。
  • 第4部分,将探讨GDPR将如何帮助客户去实施,并提供了几个案例供研究。

如果你不能等到所有的4个部分内容,就想现在了解全部的话,可以下载完整的GDPR:Impact to Your Data Management Landscape 白皮书。

MongoDB如何帮助满足GDPR要求

虽然GDPR、HIPAA、PCI-DSS等数据保护法规规定了特定区域、行业或应用程序的独特需求,但所有指令都有基本要求,包括:

  • 通过预定义的权限和角色实施限制数据访问
  • 具有防范意外或恶意披露、丢失、破坏或损坏个人资料的措施
  • 需要在访问和处理数据时分离职责
  • 使用数据库记录用户,管理人员和应用程序活动

这些要求通知了MongoDB的安全架构部门,使其提供了实施安全兼容的数据管理平台的最佳实践方式。

使用MongoDB Enterprise Advanced和MongoDB Atlas云数据库服务中提供的高级安全功能,MongoDB具有广泛的功能来实施GDPR要求的数据发现、防御和检测要求。

Discover

个人资料的识别

检查数据库内容有多种方法。最常见的方法是查询数据库并提取所有记录以识别包含用户数据的表和行(MongoDB中称为集合和文档)。然而,这种方法还需要对Schema2进行大量的手动分析,以跟踪哪些数据被存储,同时在数据库本身上施加处理开销。

MongoDB在Compass(MongoDB的GUI)上提供了一个简单的方法。 Compass可以使用户直观地浏览其数据,通过从集合中抽取一组文档,提供其MongoDB架构的图形视图,从而最大限度地减少数据库开销并将结果立即呈现给用户。

使用MongoDB Compass的模式可视化使用户能够快速浏览其模式,以了解每个数据集中的字段的频率、类型和范围。用户不需要熟悉MongoDB查询语言 — 可以通过点击界面构建强大的专业查询,将开发人员和数据库管理员以外的发现和数据丢失防范流程开放到数据保护主管和其他业务用户。

在Compass之上,MongoDB的查询语言和丰富的辅助索引使用户能够以多种方式查询和分析数据。数据可以通过单个键、范围、文本搜索、图形和地理空间查询访问到复杂的聚合,以毫秒为单位返回响应。数据可以动态地丰富诸如用户身份、位置和最后访问时间等元素,以将上下文添加到个人身份信息(PII),提供行为见解和可操作的客户智能。复杂查询本身在数据库中执行,而无需使用额外的分析框架或工具,并避免了在传统企业架构中的操作和分析系统之间移动数据所必需的ETL流程的延迟。

保留个人资料

通过使用特定的TTL(生存时间)索引,管理员可以自动将数据库中的欧盟公民数据过期。 通过根据文档中的日期字段(即,收集或上次访问用户数据的日期)配置所需的保留期限,MongoDB将在达到期限后使用自动后台进程删除文档。例如,数据库每60秒。

与应用程序级别实现到期代码相比,必须定期扫描数据库才能查找需要删除的记录,MongoDB TTL索引显然简化了数据到期策略的实施过程,降低了数据库的开销。

Defend

访问控制

对数据库的访问控制可以分为两个不同的阶段:

  • 验证,旨在确认访问数据库的客户端的身份。
  • 授权,管理客户有权访问数据库后有权执行的操作,例如读取数据,编写数据,执行管理和维护连接活动等等。

MongoDB认证

MongoDB提供多种身份验证方法,允许满足不同环境要求的最合适的方法。可以从数据库本身或通过与外部认证机制的集成来管理身份验证。

MongoDB Atlas通过SCRAM IETF RFC 5802标准强制进行数据库内认证。由于MongoDB Atlas服务在公共云平台上运行,它还实施了额外的安全控制,以减少未经授权访问的风险。默认情况下,Atlas群集将不允许从互联网直接访问。每个Atlas集群都部署在虚拟专用环境中(例如,AWSGCP Virtual Private CloudAzure Virtual Network),该私有环境默认配置为不允许入站访问。此外,IP白名单可用于限制对数据库的网络访问(即,除非已将其IP地址添加到适用的MongoDB Atlas组的白名单中,否则防止应用程序服务器访问数据库)Atlas AWS VPC对等选项允许对等组织的Atlas网络连接到自己的AWS VPC网络,从而确保网络流量不会遍历公共互联网,而是使用内部专用网络。

MongoDB Enterprise Advanced还允许使用SCRAM身份验证,以及LDAPKerberosx.509 PKI证书的其他集成选项。

许多组织广泛使用LDAP来标准化和简化大量用户通过内部系统和应用程序进行管理的方式。在许多情况下,LDAP也被用作用户访问控制的集中权限,以确保内部安全策略符合企业和监管指南。通过LDAP集成,MongoDB Enterprise Advanced可以直接针对现有的LDAP基础设施来认证和授权用户,以利用集中的访问控制体系结构。

MongoDB Enterprise Advanced还支持使用Kerberos服务进行身份验证。通过LDAPKerberosMongoDB Enterprise Advanced提供对使用Microsoft Active Directory的身份验证的支持。 Active Directory域控制器验证在Windows网络中运行的MongoDB用户和服务器,再次利用集中式访问控制。

通过支持x.509证书,MongoDB还可以与证书颁发机构(CA)集成,支持用户和节点间加密认证,从而减少密码或密钥文件中的风险。

查看Authentication部分的文档,了解有关MongoDB Enterprise Advanced可用的不同机制的更多信息。

MongoDB授权

对普通用户和数据库管理员权限的十多个预定义角色提供了基于角色的访问控制(RBAC)功能的支持。使用MongoDB Enterprise Advanced,可以通过用户定义的角色进一步定制这些功能,使管理员能够根据客户的相应数据访问和处理需求,为客户端分配细粒度权限。为了简化帐户配置和维护,可以跨团队委派角色,确保在组织内的特定数据处理功能中实施一致的策略。

除了上述认证外,MongoDB Enterprise Advanced还支持通过LDAP进行授权。这将使存储在LDAP服务器中的现有用户权限映射到MongoDB角色,而不会在MongoDB本身中重新创建用户。这种集成通过实施集中式流程来加强和简化访问控制。

查看文档的授权部分,以了解有关MongoDB中基于角色的访问控制的更多信息。

假名和加密

如第2部分所述,数据的假名和加密被设计为在未经授权的一方访问数据的情况下防止任何特定个人的识别。

假名

MongoDB提供多层次的假名。通过Read-only views,MongoDB可以自动过滤特定字段,例如查询数据库时包含公民PII的字段。而不是直接查询集合,客户端可以仅被授予对数据的特定预定义视图的访问权限。对视图授予的权限与授予底层集合的权限分开指定,因此具有不同访问权限的客户端可以被授予不同的数据视图。

Read-only views允许包含或排除字段,屏蔽字段值、过滤、模式转换、分组、排序、限制和连接多个集合中的数据。只读视图对访问数据的应用程序是透明的,不要以任何方式修改底层原始数据。

MongoDB Enterprise Advanced还可以配置日志修改功能,以防止将潜在的敏感信息(如个人标识符)写入数据库的诊断日志。可能需要访问日志以进行数据库性能优化或维护任务的开发人员和DBA仍然可以查看元数据,例如错误或操作代码,行号和源文件名,但无法查看与数据库事件相关的任何个人数据。

加密

加密可以保护传输和未使用的数据,只允许授权的访问。 如果未经授权的用户访问网络、服务器、文件系统或数据库,那么仍然可以使用加密密钥保护数据。

支持传输层安全(TLS)允许客户端通过加密的网络通道连接到MongoDB,从而保护传输中的数据。 此外,MongoDB在持久存储和备份中对静态数据进行加密。

使用MongoDB Atlas托管数据库服务,TLS是默认值,不能禁用。 从客户端到Atlas以及Atlas群集节点之间的流量进行了身份验证和加密。 对于使用公共云提供商的磁盘和卷加密服务的客户而言,Encryption-at-rest是一种可用的无成本选择。

MongoDB Enterprise Advanced还提供加密存储引擎,保护静态数据成为数据库的一个组成部分。通过本地加密磁盘上的数据库文件,管理员可以减少外部加密选项的管理和性能开销,同时提供额外的防御等级。只有那些具有相应数据库凭据的员工可以访问加密的个人数据。访问服务器上的数据库文件不会暴露任何存储的个人信息。

存储引擎使用单独的密钥对每个数据库进行加密。 MongoDB建议定期旋转和更换加密密钥,并通过执行复制集的滚动重新启动,可以在没有数据库停机的情况下旋转密钥。使用Key Management Interoperability Protocol(KMIP)服务时,数据库文件本身不需要重新加密,从而也避免了密钥轮换产生的性能开销。

请参阅文档以了解有关MongoDB加密的更多信息。为了灵活性和灾难恢复,保护服务可用性并从导致数据损坏或丢失的事件中恢复,MongoDB为系统故障提供容错,以及用于灾难恢复的备份和恢复工具。

弹性

使用本地复制,MongoDB在副本集中维护多个数据副本。 复制集是分布在多个节点上以消除单点故障的完全自我修复的集群。 在节点出现故障的情况下,副本故障转移完全自动化,无需管理员手动进行干预来恢复数据库可用性。

MongoDB副本集中的副本数量是可配置的:更大数量的副本将提供增加的数据可用性和防止数据库停机(例如,在多机器故障、机架故障、数据中心故障或网络分区的情况下)。 副本集还提供操作灵活性,提供一种升级硬件和软件的方式,而不需要使数据库脱机。 复制集成员可以在物理数据中心和云区域内部以及跨区域进行部署,从而为区域故障提供弹性。

灾难恢复

数据可能会受到许多不可预见的事件的影响:数据库或其基础架构的故障、用户操作失误、恶意攻击或应用程序错误。通过备份和恢复策略,管理员可以通过快速恢复数据来恢复业务运营,从而使组织能够达到法规和合规性义务。

MongoDB Enterprise AdvancedMongoDB Atlas为管理数据库服务的一部分提供的操作工具可以使得我们持续维护数据库备份。如果MongoDB发生故障,最近的备份只是操作系统的一小部分,最大限度地减少数据丢失。该工具提供了分片集群的时间点恢复和分布式集群的集群范围的快照。可以执行这些操作,而不会中断数据库服务。管理员可以将数据库恢复到所需时间,快速安全的时间。自动化驱动的恢复允许从数据库快照直接重新部署完全配置的集群,只需点击几下,加快服务恢复的时间。

我们可以从Ops Manager文档以及[MongoDB Atlas的文档]https://docs.atlas.mongodb.com/backup-cluster/?_ga=2.72089747.1201570172.1506122581-179102774.1490959329()中了解有关MongoDB Enterprise Advanced的备份和还原的更多信息。

数据主权:欧盟以外的数据传输

为了支持数据主权要求,MongoDB Zones可以精确控制个人数据物理存储在集群中的位置。可以将区域配置为根据用户位置自动“分割”(分区)数据 — 使管理员能够将欧盟公民数据隔离到仅被认定为符合GDPR的地区的实体设施。如果欧盟在特定地区存储数据的政策发生变化,则更新分片键范围可以使数据库自动将个人数据移至替代区域。

除了特定于地理位置的应用程序,区域可以适应一系列部署场景,例如支持用于数据生命周期管理的分层存储部署模式,或通过应用程序功能或客户对数据进行分段。

我们可以从文档中了解有关MongoDB zone sharding的更多信息。

请注意,MongoDB Atlas的服务可以配置到多个受支持的云服务商区域中的任何一个,但必须在该区域内运行。单个群集目前不能跨越多个地区。

Detect

监控

对应用平台中所有组件的主动监控始终是最佳做法。系统性能和可用性取决于在向用户提出问题之前及时发现和解决潜在问题。在内存和CPU利用率方面突然出人意料的高峰,除其他因素外,还有可能是被攻击了,如果管理员实时警报,可以减轻攻击。

MongoDB Enterprise AdvancedMongoDB Atlas管理数据库服务提供的操作工具为数据库操作提供了深入的操作可见性。 MongoDB的操作工具包括图表、自定义仪表板和自动警报功能,跟踪100多个关键数据库和系统健康指标,包括操作计数器、内存、CPU、存储消耗、复制、节点状态、打开的连接、队列等等。这些指标安全地报告给管理界面,在浏览器中进行处理、汇总、提醒和可视化,让管理员轻松跟踪MongoDB的健康状况。还可以将网络度量推送到应用程序性能管理平台(如AppDynamicsNew Relic),以支持全球IT领域的集中可见性。

当关键指标超出范围时,可以生成自定义警报。 这些警报可以通过短信和电子邮件发送,或者集成到现有的事件管理和协作系统中,例如PagerDuty,SlackHipChat等,以主动警告潜在的问题,并帮助防止中断或违规。

操作工具还使管理员能够将升级和修补程序推出到数据库,而无需停机。 使用MongoDB Atlas数据库服务,将自动应用修补程序,从而消除手动操作员干预的开销。

审计

通过维护审计跟踪,可以为访问数据库的每个客户端捕获个人数据和数据库配置的更改,为数据控制器和监管机构提供合规性和法院分析日志。

MongoDB Enterprise Advanced审核框架记录对数据库执行的所有访问和操作,包括:

  • 管理操作,如添加、修改、删除数据库用户,模式操作和备份。
  • 验证和授权活动,包括访问个人数据失败的尝试。
  • 对数据库进行读写操作。

管理员可以构建和过滤针对MongoDB Enterprise Advanced的任何操作的审计跟踪。它们可以根据数据控制器和审计人员规定的要求捕获所有活动,或仅仅是一小部分操作。例如,可以记录和审核访问特定文档的用户的身份,以及在会话期间对数据库进行的任何更改。从MongoDB Enterprise Advanced审核文档中了解更多信息。

MongoDB Atlas托管数据库服务提供了管理操作的审核日志,例如集群的部署和扩展,以及从Atlas组添加或删除用户。还提供了数据库日志访问,可由控制器用于跟踪用户与数据库的连接。

服务帮助团队创建安全的数据库环境

国内生产总值文本明确规定了“绑定公司规则”第47条(第2n条)的培训要求,

> “对持续或定期访问个人数据的人员进行适当的数据保护培训”。

MongoDB提供广泛的培训和咨询服务,帮助客户实施最佳安全措施:

  • MongoDB安全课程是MongoDB University免费为期3周的在线培训课程。
  • MongoDB University还为开发人员和运营团队提供一系列公共和私人培训,涵盖使用和管理MongoDB的最佳实践。
  • MongoDB全球咨询服务提供一系列包括健康检查、生产准备评估和访问专业咨询工程师的一揽子计划。 MongoDB咨询工程师直接与我们的团队合作、指导开发和运营,确保技能传授给员工。

第二部分总结

这是博客系列的第三部分。 在第四部分中,我们将研究GDPR如何帮助客户体验,并提供几个案例研究。

请记住,如果您想立即开始,请下载完整的GDPR:Impact to Your Data Management Landscape white paper today.。

声明

  要了解国内生产总值的规定,作用和责任的全面描述,建议读者参考“欧盟官方公报”(EU(EU)2016/679)(国际劳工组织(EU)2016/679)的案文,并参考法律 律师解释规则如何适用于其组织。 此外,为了有效地实现本博客系列中描述的功能,至关重要的是确保根据MongoDB安全文档中详细说明的说明和说明实现数据库。 读者应考虑聘请MongoDB全球咨询服务部门协助实施。

本文翻译自:https://www.mongodb.com/blog/post/gdpr-impact-to-your-data-management-landscape-part-2


《MongoDB Authentication slow my TPS?》

作者:上海小胖 (Miracle Young)

前言

  故事发生在上一篇 《MongoDB Validator 是否会因性能影响而成为摆设?》, 当我把这篇文章给TJ过目后,TJ直接给我建议了下一篇文章的题目“开启权限认证对性能产生的影响”。原因是自从上次MongoDB比特币勒索事件后,很多人一下意识到对数据库加密的必要,但是同时又担心开启鉴权会影响到MongoDB的性能和吞吐。所以借着上次文档校验测试之积累,这里给大家再来做一次鉴权方面的性能测试。

好了,这只是一个插曲,

接着来简单介绍下官方的Security。

官方的Security 是分好几种的,在这里,我们对使用最广泛的 SCRAM-SHA-1 进行验证。

先来看看官方对 SCRAM-SHA-1 算法的赞美吧: - A tunable work factor (iterationCount), - Per-user random salts rather than server-wide salts, - A cryptographically stronger hash function (SHA-1 rather than MD5), and - Authentication of the server to the client as well as the client to the server.

从3.0后,SCRAM-SHA-1 已成为默认的加密算法。但是如果是从2.6升级到3.0版本的,MongoDB还是支持 MONGODB-CR 算法的,然而官方极力推荐升级算法。具体算法步骤本篇不做过多赘述,可移步官网 https://docs.mongodb.com/manual/release-notes/3.0-scram/

在就着之前发生的暴露在公网的MongoDB未加密而被勒索的事件,安全是必须要做到的。

希望今天这篇文章能够帮助到那些担心有安全问题,但又更担心性能问题的小伙伴们~

调研

为了避免重复造轮子并做好万手准备,先做一番深入的调研,并验证自己对整个过程中可能发生的问题,是一个必须的过程。(再次感谢我的师傅 菠萝同学 教会了我这一点。)

  • 开启无权限认证
  • 添加认证用户
  • 重启数据库,并开启权限认证
  • 确认ycsb 可以通过带验证的 connection uri 连入mongodb

在最后附上了参考API,可供大家了解。

硬件信息

同 《MongoDB Validator 是否会因性能影响而成为摆设?》中的验证过程,这里就简单总结一下:

服务器
  • Product Name: ProLiant DL360 Gen9
  • Storage: RAID10, SSD, 1600GB
  • CPU*2: Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz, (8/8 cores; 16 threads)*2
  • Memory: 64GB*2
数据库
  • 单节点
  • wiredTigerCacheSizeGB=16
  • auth: enabled
  • 其他全部默认

测试

load

CRUD

NORMAL DOC

AUTH DOC

[INSERT], AverageLatency(us)

2049.89474307

2211.32866389

[INSERT], 95thPercentileLatency(us)

39.0

43.0

[READ], AverageLatency(us)

null

null

[READ], 95thPercentileLatency(us)

null

null

[UPDATE], AverageLatency(us)

null

null

[UPDATE], 95thPercentileLatency(us)

null

null

[OVERALL], RunTime(ms)

2088593.0

2242816.0

[OVERALL], Throughput(ops/sec)

47879.122452292046

44586.805159228395

r:0.95, i:0.05

CRUD

NORMAL DOC

AUTH DOC

[INSERT], AverageLatency(us)

105.3323497432522

132.487445717047

[INSERT], 95thPercentileLatency(us)

104.0

103.0

[READ], AverageLatency(us)

1338.8095364613405

1362.5082493133966

[READ], 95thPercentileLatency(us)

4751.0

4939.0

[UPDATE], AverageLatency(us)

null

null

[UPDATE], 95thPercentileLatency(us)

null

null

[OVERALL], RunTime(ms)

643134.0

655232.0

[OVERALL], Throughput(ops/sec)

77744.29590100974

76308.84938464544

r:0.5, u:0.5

CRUD

NORMAL DOC

VALIDATION DOC

[INSERT], AverageLatency(us)

null

null

[INSERT], 95thPercentileLatency(us)

null

null

[READ], AverageLatency(us)

7769.861166389139

7947.372478433602

[READ], 95thPercentileLatency(us)

26927.0

27935.0

[UPDATE], AverageLatency(us)

98.82069331485245

94.62377523853623

[UPDATE], 95thPercentileLatency(us)

70.0

72.0

[OVERALL], RunTime(ms)

1972152.0

2018302.0

[OVERALL], Throughput(ops/sec)

25353.015386237978

24773.299535946553

r:0.7, u:0.2, i:0.1

CRUD

NORMAL DOC

VALIDATION DOC

[INSERT], AverageLatency(us)

128.0571005518589

127.27489749616417

[INSERT], 95thPercentileLatency(us)

145.0

171.0

[READ], AverageLatency(us)

3336.0277518858206

3485.926126834881

[READ], 95thPercentileLatency(us)

13015.0

13615.0

[UPDATE], AverageLatency(us)

117.50030112373882

105.32122833989561

[UPDATE], 95thPercentileLatency(us)

67.0

69.0

[OVERALL], RunTime(ms)

1194793.0

1244313.0

[OVERALL], Throughput(ops/sec)

41848.25321206268

40182.815738483805

r:0.1, u:0.2, i:0.7

CRUD

NORMAL DOC

VALIDATION DOC

[INSERT], AverageLatency(us)

84.9555143143808

102.93271012453623

[INSERT], 95thPercentileLatency(us)

82.0

83.0

[READ], AverageLatency(us)

37026.50496982059

39040.24776869989

[READ], 95thPercentileLatency(us)

114303.0

122623.0

[UPDATE], AverageLatency(us)

62.52783986719247

86.839632400919

[UPDATE], 95thPercentileLatency(us)

52.0

54.0

[OVERALL], RunTime(ms)

1900481.0

2009732.0

[OVERALL], Throughput(ops/sec)

26309.129109946378

24878.93908242492

r:0.1, i:0.9

CRUD

NORMAL DOC

VALIDATION DOC

[INSERT], AverageLatency(us)

42.979859355229316

84.06285323865184

[INSERT], 95thPercentileLatency(us)

51.0

53.0

[READ], AverageLatency(us)

26553.94076526652

26935.384089125255

[READ], 95thPercentileLatency(us)

82623.0

84095.0

[UPDATE], AverageLatency(us)

null

null

[UPDATE], 95thPercentileLatency(us)

null

null

[OVERALL], RunTime(ms)

1359904.0

1396059.0

[OVERALL], Throughput(ops/sec)

36767.30122126268

35815.10523552371

所有压测报告,都会上传至github

https://github.com/MiracleYoung/mongodb_stressing_auth

结论

  • 从以上压测报告,可以看出在开启权限认证的情况下,大并发的情况下对读的延迟影响基本可以忽略不计。
  • 然而无论是从 load,还是从 r:0.1, i:0.9 的压测结果确实可以反映出,在大并发的情况下,开启认证对于写性能是有一定得影响的。
  • 之所以 loadr:0.1, i:0.9 的差异,在我翻看了代码后发现,load 是采用batch commit 的方式,而insert 则是 一条一条提交。因此会有对比差异。

就以上得出的个人结论后,我认为,这些性能的牺牲是可以忽略不计的。毕竟没有影响到 10倍乃至百倍的性能消耗。

数据库,始终是以安全为第一参考要素的!

参考

  • https://github.com/brianfrankcooper/YCSB/tree/master/mongodb
  • https://docs.mongodb.com/manual/reference/connection-string/
  • http://api.mongodb.com/java/current/index.html?com/mongodb/MongoClientURI.html

《MongoDB ServerStatus.global-Lock深入解析》

作者:张友东

MongoDB的用户在遇到性能问题时,经常会关注到 serverStatus.globalLock 指标,但对指标的含义不是很明确,本文会深入解释下 globalLock 指标的含义。

代码语言:javascript
复制
PRIMARY> db.serverStatus().globalLock
{
    "totalTime" : NumberLong("7069085891000"),
    "currentQueue" : {
        "total" : 0,
        "readers" : 0,
        "writers" : 0
    },
    "activeClients" : {
        "total" : 23,
        "readers" : 0,
        "writers" : 0
    }
}

大家可以先看下官方文档 对globalLock的解释 (使用MongoDB遇到问题都请第一时间去查阅官方文档) ,如果中间分析部分的内容读起来有困难,可直接调至最后的总结部分。

globalLock

A document that reports on the database’s lock state.

Generally, the locks document provides more detailed data on lock uses.

globalLock.totalTime

The time, in microseconds, since the database last started and created the globalLock. This is roughly equivalent to total server uptime.

globalLock.currentQueue

A document that provides information concerning the number of operations queued because of a lock.

globalLock.currentQueue.total

The total number of operations queued waiting for the lock (i.e., the sum of globalLock.currentQueue.readers and globalLock.currentQueue.writers).

A consistently small queue, particularly of shorter operations, should cause no concern. The globalLock.activeClients readers and writers information provides contenxt for this data.

globalLock.currentQueue.readers

The number of operations that are currently queued and waiting for the read lock. A consistently small read-queue, particularly of shorter operations, should cause no concern.

globalLock.currentQueue.writers

The number of operations that are currently queued and waiting for the write lock. A consistently small write-queue, particularly of shorter operations, is no cause for concern.

globalLock.activeClients

A document that provides information about the number of connected clients and the read and write operations performed by these clients.

Use this data to provide context for the globalLock.currentQueue data.

globalLock.activeClients.total

The total number of active client connections to the database (i.e., the sum of globalLock.activeClients.readers and globalLock.activeClients.writers).

globalLock.activeClients.readers

The number of the active client connections performing read operations.

globalLock.activeClients.writers

The number of active client connections performing write operations.

Client锁的状态

代码语言:javascript
复制
enum ClientState {  // 枚举常量,标识Client的当前状态
   kInactive, 
   kActiveReader, 
   kActiveWriter, 
   kQueuedReader, 
   kQueuedWriter };

Mongod上每个连接会对应一个Client对象,Client里包含当前锁的状态,初始为 kInactive,根据请求及并发状况的不同,会进入到其他的状态,核心逻辑在 lockGlobalBegin 里实现。

代码语言:javascript
复制
template 
LockResult LockerImpl::lockGlobalBegin(LockMode mode) {
    dassert(isLocked() == (_modeForTicket != MODE_NONE));
    if (_modeForTicket == MODE_NONE) {
        const bool reader = isSharedLockMode(mode);
        auto holder = ticketHolders[mode];
        if (holder) {
            _clientState.store(reader ? kQueuedReader : kQueuedWriter);
            holder->waitForTicket();
        }
        _clientState.store(reader ? kActiveReader : kActiveWriter);
        _modeForTicket = mode;
    }
    const LockResult result = lockBegin(resourceIdGlobal, mode);
    if (result == LOCK_OK)
        return LOCK_OK;

    // Currently, deadlock detection does not happen inline with lock acquisition so the only
    // unsuccessful result that the lock manager would return is LOCK_WAITING.
    invariant(result == LOCK_WAITING);

    return result;
}

而 serverStatus.globalLock 其实根据这个锁的状态进行导出

代码语言:javascript
复制
   ret.append("totalTime", (long long)(1000 * (curTimeMillis64() - _started)));

    {
        BSONObjBuilder currentQueueBuilder(ret.subobjStart("currentQueue"));

        currentQueueBuilder.append("total",
                                   clientStatusCounts[Locker::kQueuedReader] +
                                       clientStatusCounts[Locker::kQueuedWriter]);
        currentQueueBuilder.append("readers", clientStatusCounts[Locker::kQueuedReader]);
        currentQueueBuilder.append("writers", clientStatusCounts[Locker::kQueuedWriter]);
        currentQueueBuilder.done();
    }

    {
        BSONObjBuilder activeClientsBuilder(ret.subobjStart("activeClients"));

        activeClientsBuilder.append("total", clientStatusCounts.sum());
        activeClientsBuilder.append("readers", clientStatusCounts[Locker::kActiveReader]);
        activeClientsBuilder.append("writers", clientStatusCounts[Locker::kActiveWriter]);
        activeClientsBuilder.done();
    }

总结一下

代码语言:javascript
复制
globalLock.totalTime = 进程启动后经历的时间
globalLock.currentQueue.total = 下面2者之和
globalLock.currentQueue.readers = kQueuedReader 状态Client总数
globalLock.currentQueue.writers = kQueuedWriter 状态Client总数
globalLock.activerClients.totol = 下面2者之和 + 系统内部的一些Client(比如同步线程)
globalLock.activerClients.readers = kActiveReader 状态Client总数
globalLock.activerClients.writers = kActiveWriter 状态Client总数

详解 globalLock 状态转换

为了方便后续介绍,先科普一下MongoDB的层次锁模型

锁的模式
代码语言:javascript
复制
/**
 * Lock modes.
 *
 * Compatibility Matrix
 *                                          Granted mode
 *   ---------------.--------------------------------------------------------.
 *   Requested Mode | MODE_NONE  MODE_IS   MODE_IX  MODE_S   MODE_X  |
 *     MODE_IS      |      +        +         +        +        -    |
 *     MODE_IX      |      +        +         +        -        -    |
 *     MODE_S       |      +        +         -        +        -    |
 *     MODE_X       |      +        -         -        -        -    |
 */

MongoDB 加锁时,有四种模式【MODE_IS、MODE_IX、MODE_S、MODE_X】,MODE_S, MODE_X 很容易理解,分别是互斥读锁、互斥写锁,MODE_IS、MODE_IX是为了实现层次锁模型引入的,称为意向读锁、意向写锁,锁之间的竞争情况如上图所示。

MongoDB在加锁时,是一个层次性的管理方式,从 globalLock ==> DBLock ==> CollecitonLock … ,比如我们都知道MongoDB wiredtiger是文档级别锁,那么读写并发时,加锁就类似如下

代码语言:javascript
复制
写操作

1. globalLock  (这一层只关注是读还是写,不关注具体是什么LOCK)
2. DBLock MODE_IX
3. Colleciotn MODE_IX
4. pass request to wiredtiger

读操作
1. globalLock MODE_IS  (这一层只关注是读还是写,不关注具体是什么LOCK)
2. DBLock MODE_IS
3. Colleciton MODE_IS
4. pass request to wiredtiger

根据上图的竞争情况,IS和IX是无需竞争的,所以读写请求可以在没有竞争的情况下,同时传到wiredtiger引擎去处理。

再举个栗子,如果一个前台建索引的操作跟一个读请求并发了

代码语言:javascript
复制
前台建索引操作

1. globalLock MODE_IX (这一层只关注是读还是写,不关注具体是什么LOCK)
2. DBLock MODE_X
3. pass to wiredtiger

读操作
1. globalLock MODE_IS (这一层只关注是读还是写,不关注具体是什么LOCK)
2. DBLock MODE_IS
3. Colleciton MODE_IS
4. pass request to wiredtiger

根据竞争表,MODE_X和MODE_IS是要竞争的,这也就是为什么前台建索引的过程中读是被阻塞的。

我们今天介绍的 globalLock 对应上述的第一步,在globalLock这一层,只关心是读锁、还是写锁,不关心是互斥锁还是意向锁,所以 globalLock 这一层是不存在竞争的。那么 globalLock 里的几个指标到底意味着什么?

从上述的代码可以发现,globalLockBegin里(基本所有的数据库读写请求都要走这个路径)决定了globalLock的状态转换,核心逻辑如下

代码语言:javascript
复制
 template 
LockResult LockerImpl::lockGlobalBegin(LockMode mode) {

   const bool reader = isSharedLockMode(mode);
    auto holder = ticketHolders[mode];
    if (holder) {
          _clientState.store(reader ? kQueuedReader : kQueuedWriter);
                holder->waitForTicket();
       }
   _clientState.store(reader ? kActiveReader : kActiveWriter);

   ....
   const LockResult result = lockBegin(resourceIdGlobal, mode);
    if (result == LOCK_OK)
        return LOCK_OK;
   ...
 }

上述代码里,如果holder不为空,Client会先进去kQueuedReader或kQueuedWriter状态,然后获取一个ticket,获取到后转换为kActiveReader或kActiveWriter状态。这里的ticket是什么东西?

这里的ticket是引擎可以设置的一个限制。正常情况下,如果没有锁竞争,所有的读写请求都会被pass到引擎层,这样就有个问题,你请求到了引擎层面,还是得排队执行,而且不同引擎处理能力肯定也不同,于是引擎层就可以通过设置这个ticket,来限制一下传到引擎层面的最大并发数。比如

  • wiredtiger设置了读写ticket均为128,也就是说wiredtiger引擎层最多支持128的读写并发(这个值经过测试是非常合理的经验值,无需修改)。
  • mmapv1引擎并没有设置ticket的限制,也就是说用mmapv1引擎时,globalLock的currentQueue会一直是0.

globalLock完成后,client就进入了kActiveReader或kActiveWriter中的一种状态,这个就对应了globalLock.activerClients字段里的指标,接下来才开始lockBegin,加DB、Collection等层次锁,更底层的锁竞争会间接影响到globalLock。

总结

serverStatus.globalLock 或者 mongostat (qr|qw ar|aw指标)能查看mongod globalLock的各个指标情况。

  1. Wiredtiger限制传递到引擎层面的最大读写并发数均为128(合理的经验值,通常无需调整),如果超过这个阈值,排队的请求就会体现在globalLock.currentQueue.readers/writers里。
  2. 如果globalLock.currentQueue.readers/writers个值长时间都不为0(此时globalLock.activeClients.readers/writers肯定是持续接近或等于128的),说明你的系统并发太高(或者有长时间占用互斥锁的请求比如前台建索引),可以通过优化单个请求的处理时间(比如建索引来减少COLLSCAN或SORT),或升级后端资源(内存、磁盘IO能力、CPU)来优化。
  3. globalLock.activeClients.readers/writers 持续不为0(但没达到128,此时currentQueue为空),并且你觉得请求处理已经很慢了,这时也可以考虑2中提到的优化方法。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Mongoing中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MongoDB如何帮助满足GDPR要求
  • Discover
    • 个人资料的识别
    • Defend
      • 访问控制
        • MongoDB认证
          • MongoDB授权
          • 假名和加密
            • 假名
              • 加密
                • 弹性
                  • 灾难恢复
                  • 数据主权:欧盟以外的数据传输
                  • Detect
                    • 监控
                      • 审计
                        • 服务器
                        • 数据库
                        • globalLock
                        • globalLock.totalTime
                        • globalLock.currentQueue
                        • globalLock.currentQueue.total
                        • globalLock.currentQueue.readers
                        • globalLock.currentQueue.writers
                        • globalLock.activeClients
                        • globalLock.activeClients.total
                        • globalLock.activeClients.readers
                    • 服务帮助团队创建安全的数据库环境
                    • 第二部分总结
                    • 声明
                    • 调研
                    • 硬件信息
                    • 测试
                    • 结论
                    • 参考
                      • globalLock.activeClients.writers
                        • 锁的模式
                    • Client锁的状态
                    • 详解 globalLock 状态转换
                    • 总结
                    相关产品与服务
                    云数据库 MongoDB
                    腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档