Mongodb
Mongodb 使用场景
- 应用不需要复杂join以及不需要事务支持
- 应用需求多变,数据模型不固定,或者最终数据需要对多种数据聚合得到
- 应用读写请求QPS在2000~3000或者更高
- 应用需发展迅速,要水平扩展
- 应用要求存储的数据不会丢失
- 应用高可用要求在99.999%
- 应用需要用到大量的地理位置查询,文本查询。
Mongodb 不适用场景
- 高度事务要求:银行,财务
- 涉及到复杂查询,跨多表查询
- 对于数据结构固定,并且Sql查询能高效率解决的情况
Mongodb 使用场景案例
- 游戏:MongoDB存储用户信息,装备,积分,方便查询更新
- 无聊:MongoDB存储订单信息,订单状态不断变,存储所有变更信息
- 社交:MongoDB存储用户信息,朋友圈信息,地理位置索引实现附近的人,地点等
- 视频直播:MongoDB存储用户信息,礼物等
MongoDB索引结构
B树
- B树是多叉平衡查找树,包括以下几个结构特性:
- 左子树数据小于跟数据,右子树数据大于根节点数据
- 左右子树高度差不大于1
- 每个节点可以有N个字节的,N>2
- B树的每个节点都存放 索引 & 数据,数据遍布整个树结构,搜索可能在非叶子结点结束,最好情况是O(1)
对比B+树
- B+ 树是B树的变种,区别在于:
- 叶子结点保存了完整的索引 & 数据,非叶子结点只保存索引值,因此他的查询时间固定为logn
- 叶子结点中有指向下一个叶子结点的指针,叶子结点类似一个双向链表
- 因为叶子结点有完整数据,并且有双链表结构,因此我们在范围查询的时候能有效提升查询效率。
索引类型
- 单字段索引:MongoDB可以在单字段建立索引 并且 添加当前字段所在的索引的一个字段排序顺序,但是单字段索引查找顺序并不重要,因为MongoDB查询时候可以前遍历,也可以后遍历{userId:1}
- 复合索引:MongoDB支持多个字段自定义索引,复合索引字段顺序很重要,例如,{userId:1,score:-1},按照userId顺序的同时按照score的逆序排列
MongoDB复制集
-
复制集功能:
- 主从复制
- 主从互相灾备
- 数据分发+读写分离
- 异地容灾
-
数据复制实现
- 当一个操作,CRUD时候,会先记录oplog
- 从节点通过主节点上tailable游标不断获取最新的oplog,并且将数据更新到slave字节结点上来完成数据一致性保证。
-
选举机制:
- 具有投票权的结点会在结点之间互发心跳(2s一次)
- 当5次心跳时间内没有收到,则判断失联
- 如果失联的是主节点,从节点会发起选举选出新主节点
- 如果失联的是从节点,则不会产生新的选举。
复制集的写策略
writeConcern 策略
- writeConcern决定一个写操作落到多少个节点上才算成功,取值包括:
- 0:发起操作,不关心是否成功
- 1~n:(n为集群最大节点数),写操作需要被复制到指定数量节点才算成功
- majority:写操作需要被复制到大多数节点才算成功
- 发起写操作的程序将阻塞到写操作到指定节点数为止
- 默认是1
开启journal日志
- 类似关系数据库中的事务日志,Journaling能让MongoDB数据库做到crash-safe
- 在MongoDB2.4版本后默认开启,每次启动检查journal日志是否需要恢复
- 由于journal日志写入阻塞,因此会写入性能有影响,对于读没有影响。生产环节下Journaling很有必要。
- 两种配置方式:
- true:写操作落到Journal文件才算成功
- false:写操作到达内存即算成功 (每100ms刷一次日志)
复制集读策略
readPreference读策略
-
readPreference决定使用哪一个节点来满足正在发起的读请求,可选值如下:
- primary:只选主节点,默认值
- primaryPreferred:优选选择主节点,如果不可用则选从节点
- secondary:只选从节点
- secondaryPreferred:优先选从节点,如果从节点不可用则选主
- nearest:选最近的节点。
-
适合场景:
-
如果需要查询时效性,例如insert后立刻查询,选择 primary/primaryPreferred
-
如果实效性不高,则可以从:secondary/sendaryPreferred
-
如果是类似广播发布信息,比如上传图片后,全国各地每个地方都需要读:nearest
readConcern 指定数据读取范围
- readConcern决定节点上数据哪些可以读取,类似关系型水库隔离级别,有如下配置:
- available:所有数据可读
- local:所有当前分片中的数据
- majority: 读取在大多数节点上提交完成的数据
- linearizable:可线性化读取
- snapshot:读取最近快照中的数据
readConcern 中majority的实现方式
- 每个节点上数据维护多个X版本,MVCC机制
- MongoDB通过维护多个快照来链接不同的版本信息
- 每个被大多数节点确认过的版本都将树一个快照
- 快照持续到没有人使用为止才被删除
Mongodb链接参数
- maxPoolSize: 连接池大小,默认100
- Max Wait Time 建议设置,自动杀掉太慢的查询
- Write Concern 建议majority 保证数据安全
- Read Concern 对数据一致性要求高场景适用
MongoDB适用规范
查询
- 每个查询尽量用索引
- 尽量用覆盖索引Covered indexes (可以避免读数据文件)
- 适用projection减少返回到客户端的文档内容(projection用于选择返回字段)
写入
- 在upodate语句里只包括新需要更新的字段
- 尽可能用批量插入来提升写入性能
- 适用TTL自动过期日志类型数据
文档结构
- 字段名字尽可能的简单
- json数据不要用太深的嵌套(超过2层算复杂的)
- 不适用中文,标点符号等非拉丁字母做为字段名
分页问题
- 尽量不展示总页数,特别的数据量大且查询不能完全覆盖索引的情况
- 避免适用skip/limit形式的分页,深分页问题,改用查询条件 + 唯一排序条件