検索
MongoDB 的那些坑(开发者角度)Jun 07, 2016 pm 04:37 PM
mongodb開発者普通レビュー角度

点评 : 本文从普通开发者角度来描述遇到的坑,多数问题是可以避免的,但对于大多数刚接触的开发者还是有一定的借鉴意义。 MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,

点评
本文从普通开发者角度来描述遇到的坑,多数问题是可以避免的,但对于大多数刚接触的开发者还是有一定的借鉴意义。

MongoDB 是目前炙手可热的 NoSQL 文档型数据库,它提供的一些特性很棒:如自动 failover 机制,自动 sharding,无模式 schemaless,大部分情况下性能也很棒。但是薄荷在深入使用 MongoDB 过程中,遇到了不少问题,下面总结几个我们遇到的坑。特别申明:我们目前用的 MongoDB 版本是 2.4.10,曾经升级到 MongoDB 2.6.0 版本,问题依然存在,又回退到 2.4.10 版本。

MongoDB 数据库级锁

坑爹指数:5星(最高5星)

MongoDB的锁机制和一般关系数据库如 MySQL(InnoDB), Oracle 有很大的差异,InnoDB 和 Oracle 能提供行级粒度锁,而 MongoDB 只能提供 库级粒度锁,这意味着当 MongoDB 一个写锁处于占用状态时,其它的读写操作都得干等。

初看起来库级锁在大并发环境下有严重的问题,但是 MongoDB 依然能够保持大并发量和高性能,这是因为 MongoDB 的锁粒度虽然很粗放,但是在锁处理机制和关系数据库锁有很大差异,主要表现在:

MongoDB 没有完整事务支持,操作原子性只到单个 document 级别,所以通常操作粒度比较小;
MongoDB 锁实际占用时间是内存数据计算和变更时间,通常很快;
MongoDB 锁有一种临时放弃机制,当出现需要等待慢速 IO 读写数据时,可以先临时放弃,等 IO 完成之后再重新获取锁。
通常不出问题不等于没有问题,如果数据操作不当,依然会导致长时间占用写锁,比如下面提到的前台建索引操作,当出现这种情况的时候,整个数据库就处于完全阻塞状态,无法进行任何读写操作,情况十分严重。

解决问题的方法,尽量避免长时间占用写锁操作,如果有一些集合操作实在难以避免,可以考虑把这个集合放到一个单独的 MongoDB 库里,因为 MongoDB 不同库锁是相互隔离的,分离集合可以避免某一个集合操作引发全局阻塞问题。

建索引导致数据库阻塞

坑爹指数:3星

上面提到了 MongoDB 库级锁的问题,建索引就是一个容易引起长时间写锁的问题,MongoDB 在前台建索引时需要占用一个写锁(而且不会临时放弃),如果集合的数据量很大,建索引通常要花比较长时间,特别容易引起问题。

解决的方法很简单,MongoDB 提供了两种建索引的访问,一种是 background 方式,不需要长时间占用写锁,另一种是非 background 方式,需要长时间占用锁。使用 background 方式就可以解决问题。
例如,为超大表 posts 建立索引,
千万不用使用

<code>db.posts.ensureIndex({user_id: 1})</code>

而应该使用

<code>db.posts.ensureIndex({user_id: 1}, {background: 1})</code>

不合理使用嵌入 embed document

坑爹指数:5星

embed document 是 MongoDB 相比关系数据库差异明显的一个地方,可以在某一个 document 中嵌入其它子 document,这样可以在父子 document 保持在单一 collection 中,检索修改比较方便。

比如薄荷的应用情景中有一个 Group document,用户申请加入 Group 建模为 GroupRequest document,我们最初的时候使用 embed 方式把 GroupRequest 放置到 Group 中。
Ruby 代码如下所示(使用了 Mongoid ORM):

<code>class Group
  include Mongoid::Document
  ...
  embeds_many :group_requests
  ...
end
class GroupRequest
  include Mongoid::Document
  ...
  embedded_in :group
  ...
end</code>

这个使用方式让我们掉到坑里了,差点就爬不出来,它导致有接近两周的时间系统问题,高峰时段常有几分钟的系统卡顿,最严重一次甚至引起 MongoDB 宕机。

仔细分析后,发现某些活跃的 Group 的 group_requests 增加(当有新申请时)和更改(当通过或拒绝用户申请时)异常频繁,而这些操作经常长时间占用写锁,导致整个数据库阻塞。原因是当有增加 group_request 操作时,Group 预分配的空间不够,需要重新分配空间(内存和硬盘都需要),耗时较长,另外 Group 上建的索引很多,移动 Group 位置导致大量索引更新操作也很耗时,综合起来引起了长时间占用锁问题。

解决问题的方法,说起来也简单,就是把 embed 关联更改成的普通外键关联,就是类似关系数据库的做法,这样 group_request 增加或修改都只发生在 GroupRequest 上,简单快速,避免长时间占用写锁问题。当关联对象的数据不固定或者经常发生变化时,一定要避免使用 embed 关联,不然会死的很惨。

不合理使用 Array 字段

坑爹指数:4星

MongoDB 的 Array 字段是比较独特的一个特性,它可以在单个 document 里存储一些简单的一对多关系。

薄荷有一个应用情景使用遇到严重的性能问题,直接上代码如下所示:

<code>class User
  include Mongoid::Document
  ...
  field :follower_user_ids, type: Array, default: []
  ...
end</code>

User 中通过一个 Array 类型字段 follower_user_ids 保存用户关注的人的 id,用户关注的人从 10个到 3000 个不等,变化是比较频繁的,和上面 embed 引发的问题类似,频繁的 follower_user_ids 增加修改操作导致大量长时间数据库写锁,从而引发 MongoDB 数据库性能急剧下降。

解决问题的方法:我们把 follower_user_ids 转移到了内存数据库 redis 中,避免了频繁更改 MongoDB 中的 User, 从而彻底解决问题。如果不使用 redis,也可以建立一个 UserFollower 集合,使用外键形式关联。

先列举上面几个坑吧,都是害人不浅的陷阱,使用 MongoDB 过程一定要多加注意,避免掉到坑里。

参考资料:
1.MongoDB 锁机制详解
2.MongoDB 建立索引操作文档

来源: http://xiewenwei.github.io/blog/2014/06/22/trap-in-mongodb/

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
mongodb php 扩展没有怎么办mongodb php 扩展没有怎么办Nov 06, 2022 am 09:10 AM

mongodb php扩展没有的解决办法:1、在linux中执行“$ sudo pecl install mongo”命令来安装MongoDB的PHP扩展驱动;2、在window中,下载php mongodb驱动二进制包,然后在“php.ini”文件中配置“extension=php_mongo.dll”即可。

Redis和MongoDB的区别与使用场景Redis和MongoDB的区别与使用场景May 11, 2023 am 08:22 AM

Redis和MongoDB都是流行的开源NoSQL数据库,但它们的设计理念和使用场景有所不同。本文将重点介绍Redis和MongoDB的区别和使用场景。Redis和MongoDB简介Redis是一个高性能的数据存储系统,常被用作缓存和消息中间件。Redis以内存为主要存储介质,但它也支持将数据持久化到磁盘上。Redis是一款键值数据库,它支持多种数据结构(例

Go语言中使用MongoDB:完整指南Go语言中使用MongoDB:完整指南Jun 17, 2023 pm 06:14 PM

MongoDB是一种高性能、开源、文档型的NoSQL数据库,被广泛应用于Web应用、大数据以及云计算领域。而Go语言则是一种快速、开发效率高、代码可维护性强的编程语言。本文将为您完整介绍如何在Go语言中使用MongoDB。一、安装MongoDB在使用MongoDB之前,需要先在您的系统中安装MongoDB。在Linux系统下,可以通过如下命令安装:sudo

php7.0怎么安装mongo扩展php7.0怎么安装mongo扩展Nov 21, 2022 am 10:25 AM

php7.0安装mongo扩展的方法:1、创建mongodb用户组和用户;2、下载mongodb源码包,并将源码包放到“/usr/local/src/”目录下;3、进入“src/”目录;4、解压源码包;5、创建mongodb文件目录;6、将文件复制到“mongodb/”目录;7、创建mongodb配置文件并修改配置即可。

php怎么使用mongodb进行增删查改操作php怎么使用mongodb进行增删查改操作Mar 28, 2023 pm 03:00 PM

MongoDB作为一款流行的NoSQL数据库,已经被广泛应用于各种大型Web应用和企业级应用中。而PHP语言也作为一种流行的Web编程语言,与MongoDB的结合也变得越来越重要。在本文中,我们将会学习如何使用PHP语言操作MongoDB数据库进行增删查改的操作。

SpringBoot中logback日志怎么保存到mongoDBSpringBoot中logback日志怎么保存到mongoDBMay 18, 2023 pm 07:01 PM

自定义Appender非常简单,继承一下AppenderBase类即可。可以看到有个AppenderBase,有个UnsynchronizedAppenderBase,还有个AsyncAppenderBase继承了UnsynchronizedAppenderBase。从名字就能看出来区别,异步的、普通的、不加锁的。我们定义一个MongoDBAppender继承UnsynchronizedAppenderBasepublicclassMongoDBAppenderextendsUnsynchron

Swoole与MongoDB的整合:构建高性能的文档数据库系统Swoole与MongoDB的整合:构建高性能的文档数据库系统Jun 14, 2023 am 11:51 AM

在现代企业应用程序开发中,需要处理海量数据和高并发的访问请求。为了满足这些需求,开发人员需要使用高性能的数据库系统,以确保系统的稳定性和可扩展性。本文将介绍如何使用Swoole和MongoDB构建高性能的文档数据库系统。Swoole是一个基于PHP语言开发的异步网络通信框架,它能够大大提高PHP应用程序的性能和并发能力。MongoDB是一种流行的文档数据库,

SpringBoot怎么整合Mongodb实现增删查改SpringBoot怎么整合Mongodb实现增删查改May 13, 2023 pm 02:07 PM

一、什么是MongoDBMongoDB与我们之前熟知的关系型数据库(MySQL、Oracle)不同,MongoDB是一个文档数据库,它具有所需的可伸缩性和灵活性,以及所需的查询和索引。MongoDB将数据存储在灵活的、类似JSON的文档中,这意味着文档的字段可能因文档而异,数据结构也会随着时间的推移而改变。文档模型映射到应用程序代码中的对象,使数据易于处理。MongoDB是一个以分布式数据库为核心的数据库,因此高可用性、横向扩展和地理分布是内置的,并且易于使用。况且,MongoDB是免费的,开源

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール