MongoDB分片,唯一索引与upsert
前言
分片,唯一索引和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)。
参考资料
- Unique Indexes: https://docs.mongochina.com/core/index-unique.html
- Retry full upsert path when duplicate key exception matches exact query predicate: https://jira.mongodb.org/browse/SERVER-37124
MongoDB分片,唯一索引与upsert的更多相关文章
- TokuMX唯一索引不支持dropDups选项
TokuMX v1.5.0的唯一索引(unique index)不支持dropDups选项, 如果源数据包含相同目标key的文档,将无法建立唯一索引. 问题场景: 从MongoDB到TokuMX的数据 ...
- MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划
这篇文章主要介绍了MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划的相关资料,需要的朋友可以参考下 一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存 ...
- MongoDB 创建基础索引、组合索引、唯一索引以及优化
一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存在system.indexes 中,且默认总是为_id创建索引,它的索引使用基本和MySQL 等关系型数据库一样.其实可以这样说说,索引 ...
- MongoDB小结25 - 复合唯一索引
只要满足索引的其中之一不同即可 db.blog.ensureIndex({"username":1,"blogname":1}) 作者和作品名其中之一不同即可创 ...
- MongoDB的复合唯一索引
一 创建 JavaScript Shell db.room.ensureIndex({'floor':1,'num':1}) Spring Data @Data // lombok @Document ...
- mongodb 索引,全文索引与唯一索引
唯一索引创建: db.createIndex({name: 1}, {unique: true})
- MongoDB(课时22 唯一索引)
3.6.1 唯一索引 唯一索引的主要目的是用在某一个字段上,使该字段的内容不重复. 范例:创建唯一索引 db.students.ensureIndex({"name" : 1}, ...
- 4.非关系型数据库(Nosql)之mongodb:普通索引,唯一索引
一:普通索引 1创建一个新的数据库 > use toto; switched to db toto > show dbs; admin (empty) local 0.078GB & ...
- MongoDB 分片管理(不定时更新)
背景: 通过上一篇的 MongoDB 分片的原理.搭建.应用 大致了解了MongoDB分片的安装和一些基本的使用情况,现在来说明下如何管理和优化MongoDB分片的使用. 知识点: 1) 分片的配置和 ...
随机推荐
- A 题解————2019.10.16
[题目描述] 对于给定的一个正整数n, 判断n是否能分成若干个正整数之和 (可以重复) ,其中每个正整数都能表示成两个质数乘积. [输入描述]第一行一个正整数 q,表示询问组数.接下来 q 行,每行一 ...
- 【BZOJ3508】开灯
[BZOJ3508]开灯 题面 bzoj 题解 其实变为目标操作和从目标操作变回来没有区别,我们考虑从目标操作变回来. 区间整体翻转(\(\text{Xor}\;1\))有点难受,我们考虑将这个操作放 ...
- 《深度学习框架PyTorch:入门与实践》读书笔记
https://github.com/chenyuntc/pytorch-book Chapter2 :PyTorch快速入门 + Chapter3: Tensor和Autograd + Chapte ...
- LOJ6625 时间复杂度(min_25筛)
本人在LOJ的第三题(前两题太水不好意思说了QwQ),欢迎大家踩std. 题目链接:LOJ 题目大意:定义函数 $f$:($minp$ 表示最小质因子) $$f(x)=\begin{cases}0&a ...
- Spring Security教程之加点密,加点盐(七)
一.概述 一般用数据库保存用户的密码都是经过加密,甚少使用明文.同时,加密方式一般采用不可逆的加密方法,如MD5.也要避免相同的密码在加密后有相同的密文,如admin用户的密码为admin,加密后变成 ...
- 秘制牛肉Gamma阶段项目展示
秘制牛肉Gamma阶段项目展示 1.团队成员和个人博客 · 左顺:在项目中主要负责后端开发.个人博客 · 袁勤:精通网页项目开发,前端后端都很强,在完成自己后端任务后也会积极帮助其他人的任务.个人博客 ...
- 微信网页授权+获取用户基本信息+强制关注+JSSDK分享参数
网页授权+获取用户基本信息+强制关注+JSSDK分享参数 //支付宝红包口令列表 public function view(){ $openid = ""; Vendor('Wei ...
- 【IntelliJ IDEA学习之六】IntelliJ IDEA 调试
版本:IntelliJIDEA2018.1.4 一.设置热部署1.自动编译 2.配置hotswap 3.开启compiler.automake.allow.when.app.running CTRL ...
- YYCache 的整体架构类图

- 小程序 - 底部导航栏“tabBar”
小程序底部导航 1.app.json页面配置: { "pages": [ "pages/movie/movie", "pages/cinema/cin ...