前言

分片,唯一索引和upsert,表面上看似没有直接联系的几个东西,到底存在怎样的瓜葛呢?

分片

为了保持水平扩展的有效性,分片功能必须保证各个片之间没有直接关联,不需要与其他分片交互就可以独立做出决策。如果不能满足这一点,随着分片数量不断增加,需要交互的分片越来越多,势必会越来越慢,那么就违背了分片的初衷了。比如JOIN就是一种典型的破坏分片独立性的功能。在一个n个分片的集群中,为了得到笛卡尔积,每个分片必须与其他n-1个分片交互来得到结果。虽然不见得是线性的延迟增长(因为n-1个请求可以并行),但是可想而知对资源将是极大的消耗,并且随着分片数量的增长影响会越来越显著,最终会到达“增加一个分片可能对性能完全没有帮助”,或者“增加一个分片反而降低性能”的地步。

唯一索引

唯一索引是另外一个显著破坏分片独立性的特性。前面对JOIN的分析完全适用于唯一索引,并且更糟的情况是唯一索引还有有更进一步的恶劣影响,那就是在写入数据的时候必须占用一个跨分片的全局锁,否则无法保证其唯一性,可想而知对性能有怎样的影响。这也是MongoDB为什么不打算去实现全局唯一索引的原因。

有一种特殊情况却可以改变这种不利状况,那就是唯一索引的键正好是片键的时候。片键一旦确定,文档该去哪个分片就确定了,那么只要保证该键在这一个片上唯一就可以了,不再需要去与其他分片协商。

upsert

从语义上讲,我们使用upsert一般是希望一个键只出现一次的(不然每次insert就好了)。这一点恰恰是唯一索引要干的事情,而唯一索引又存在上面的所说的问题,因此唯一有意义的情况则是upsert使用的条件正好是片键,且片键唯一。
满足了上面这些条件就高枕无忧了吗?并不是。在决定一个键是不是存在,到执行update/insert之间,是存在空隙的。即,检测和执行并不在一个原子操作中,也不可能在一个原子操作中,否则将是一个很大粒度的锁。再说,MongoDB对文档级别并没有真正通过加锁来控制,而是通过“乐观并发控制”(optimistic concurrency control)来进行的。
因此,出于效率考虑,不是原子操作是正确的选择,而解决这个问题也不是特别麻烦的事情,实际上只需要在遇到duplicate key异常的时候重试该操作就可以了,因为重试的时候理论上就应该变成update而不再是insert,自然避免了问题。或者,在4.2中直接实现了这类错误的自动重试(SERVER-37124)。

参考资料

MongoDB分片,唯一索引与upsert的更多相关文章

  1. TokuMX唯一索引不支持dropDups选项

    TokuMX v1.5.0的唯一索引(unique index)不支持dropDups选项, 如果源数据包含相同目标key的文档,将无法建立唯一索引. 问题场景: 从MongoDB到TokuMX的数据 ...

  2. MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划

    这篇文章主要介绍了MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划的相关资料,需要的朋友可以参考下 一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存 ...

  3. MongoDB 创建基础索引、组合索引、唯一索引以及优化

    一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存在system.indexes 中,且默认总是为_id创建索引,它的索引使用基本和MySQL 等关系型数据库一样.其实可以这样说说,索引 ...

  4. MongoDB小结25 - 复合唯一索引

    只要满足索引的其中之一不同即可 db.blog.ensureIndex({"username":1,"blogname":1}) 作者和作品名其中之一不同即可创 ...

  5. MongoDB的复合唯一索引

    一 创建 JavaScript Shell db.room.ensureIndex({'floor':1,'num':1}) Spring Data @Data // lombok @Document ...

  6. mongodb 索引,全文索引与唯一索引

    唯一索引创建: db.createIndex({name: 1}, {unique: true})

  7. MongoDB(课时22 唯一索引)

    3.6.1 唯一索引 唯一索引的主要目的是用在某一个字段上,使该字段的内容不重复. 范例:创建唯一索引 db.students.ensureIndex({"name" : 1}, ...

  8. 4.非关系型数据库(Nosql)之mongodb:普通索引,唯一索引

     一:普通索引 1创建一个新的数据库 > use toto; switched to db toto > show dbs; admin (empty) local 0.078GB & ...

  9. MongoDB 分片管理(不定时更新)

    背景: 通过上一篇的 MongoDB 分片的原理.搭建.应用 大致了解了MongoDB分片的安装和一些基本的使用情况,现在来说明下如何管理和优化MongoDB分片的使用. 知识点: 1) 分片的配置和 ...

随机推荐

  1. [RN] React Native 使用 图片预览和放大 插件 react-native-image-zoom-viewer 过程中,放大报错问题

    React Native 使用 图片预览和放大 插件 react-native-image-zoom-viewer 过程中,放大报错问题 报错如下: Cannot record touch end w ...

  2. BAT脚本入门

    BAT脚本入门 echo:显示命令后的字符 chcp 65001: 就是换成UTF-8代码页 echo off: 此语句后的所有运行命令都不显示命令行语句 @:与echo off相似,但它加在每个命令 ...

  3. docker镜像编码注意事项

    第一步:下面这些话如果你不知道我在说什么,只管粘贴复制然后按回车键等待执行完成就行,一步步来不要着急. 首先安装docker,ubuntu18.04安装docker很简单只需要 一行命令 wget - ...

  4. 一个web请求的全过程

    参考文档:http://www.mamicode.com/info-detail-1357508.html 名词解释DNS: DNS(Domain Name System,域名系统),因特网上作为域名 ...

  5. 软件工程1916|W(福州大学)_助教博客】个人总结作业(第12次)成绩公示

    1.作业链接 个人作业--软件工程实践总结作业 https://edu.cnblogs.com/campus/fzu/SoftwareEngineering1916W/homework/3316 2. ...

  6. kafka topic查看删除

    1,查看kafka topic列表,使用--list参数 >bin/kafka-topics.sh --zookeeper 127.0.0.1:2181 --list __consumer_of ...

  7. ssh服务器安装测试

    ssh服务器搭建 作用:用于远程登录到服务器 (1)服务器端 安装ssh: $ sudo apt-get install openssh-server 查看ssh是否已经安装: $ sudo apti ...

  8. [转帖]深入理解latch: cache buffers chains

    深入理解latch: cache buffers chains http://blog.itpub.net/12679300/viewspace-1244578/ 原创 Oracle 作者:wzq60 ...

  9. Spring Cloud OkHttp设计原理

    Spring Cloud 框架最底层核心的组件就是服务调用方式,一般Spring Cloud框架采用的是HTTP的调用框架,本文将在 Spring Cloud应用场景下,介绍组件OkHttp3的设计原 ...

  10. 63 网络编程(四)——TCP编程

    TCP编程 TCP编程是面向连接的数据传输,所以需要时用IO流来建立连接. 用户输出流到服务器,服务器输入流接收数据. 服务器输出流到用户,用户输入流接收. 基本流程 服务器端 创建服务器端:Serv ...