知道最近也会听到一个声音,MONGODB 不能在核心的系统使用, 哎, 2021年了,现在有些系统都没有传统数据库的身影,而代替的是通过ES,REDIS ,Aerospike 这样的数据库来成功上位到这个系统的核心数据库, 那么MONGODB 为什么不可以成为项目的核心数据库?
在传统的数据库表的设计中会提到范式,一般应用程序的设计理念中会用到传统数据库,都会提到三范式,三范式中的要求主要是每一列都和主键直接相关,不能间接相关. 或者可以理解为一个项目中的数据库中的表和表之间的关系是通过主外键关系来连接的,不会有两张表包含相同内容的列超过1个.
这也就是传统数据库表中查询会通过JOIN 来进行多个表的数据关系连接并将多个表的数据在一个SELECT语句中被查询出的原因.
其中通过MONGODB 来作为核心库的好处
1 提高读取的性能,通过嵌套的方式的设计方式,将传统数据表中的JOIN 转换为一次读取获得数据的方式,提高数据的查询性能. 并且这样的操作方式将事务原子化.
2 查询数据的多源化,由于反范式,则在设计中可能存在同样的数据存在不同的collection中的情况, 那这样的设计可以在查询的逻辑层面分散某些查询的数据来源.
当然有好处必然有缺点
1 在多个表(colllection) ,存在类似或同样的数据,数据的一致性就成为一个问题,应用程序设计中就需要保证这方面的数据写入的原子性和事务性(目前高版本的已经支持跨collection事务)
2 数据更新在这样的设计下, 数据完全被更新的难度提高了.
在进行MONGODB 应用的承载的设计之初要把握
1 实体:实体可以理解为数据本身表达的意思
2 属性:标明实体中数据本身的分类,属性
3 关系:实体和实体之间的关系
掌握这三者的关系,与后面设计数据存储和查询是有关联的。
掌握这三者的和之间的关系之前是需要详细的了解业务,每种数据库都有他适合的业务的场景,在选择MONGODB来做核心的数据库时,你先要弄清楚你到底要接触的业务是什么。如果是财务之类的数据处理,对关系处理要求比较多的,包含数据汇聚和计算的比较多的,自然选择MONGODB 是不大合适。
第一步,确定业务,什么样的业务合适使用MONGODB 来做核心的数据库
1 日志类型的业务,日志类的数据包含,类似交易流水,业务逻辑处理流程中的记录,这类数据有一个明显的特征,基本在写入后,很少被改变。并且数据变化,扩展可能性大。
2 数据传递的媒介,如机构之间的报文的传递,回执,确认信息,外部数据的承接,这类的信息也有数据的格式不确定性,以及信息量大,并且在传入后也不在改变的特性。
3 信息传入量大,例如物联网,传入的信息量大,并且信息的格式可能会根据传入设备的变化,格式有变化的情况,其实这类信息还是具有数据格式不确定,变化,信息量大,传入信息后不进行改变的特性。
当然还有一些其他常见的场景,例如监控,社交,等。
终上所述,MONGODB 承接的业务有如下特点
并发高,信息量大,格式不固定,格式变动的可能性大,信息传入后变化不大,或基本不改变。基于这样的特点可以在几个方面进行合并MONGODB 本身的特点加以利用可以进行如下设计
架构设计中的读写分离
如果说在传统数据库上进行读写分离问题多,难点多,在MONGODB 上如果你说我还做不了读写分离,那只能说 你的加把劲了。
特性1 例如MONGODB 特有的多点写入确认的特点,在你认为这条信息是需要读写分离的,那完全可以将信息写入的时候,通过W 属性将信息在多个节点同时写入,保证原子性,那读写分离中是能保证你数据的写入和读取是可以保证一致性的。而控制的方法在你写入语句的时候加入 。具体方法参见
https://cloud.tencent.com/developer/article/1793778
在保证了数据的各个节点的一致性后,那么直需要在读取数据的时候,倾向性的去从库读取就可以了。这样在高并发的情况下,大大减少了主库的压力。
应用架构设计中的关系模型设计:
传统数据库中的关系
1 一对多
2 一对一
3 多对多
一对多的案例:
{_id: <objectId>,
人名:张三,
贷款记录:[
{贷款日期:”2018-12-12”,
贷款金额:100000RMB,
还款合同到期日:“2022-12-12”
每月还款额:5000
},
{贷款日期:”2020-03-02”,
贷款金额:50000RMB,
还款合同到期日:“2026-12-12”
每月还款额:2000
}]
}
通过数组 嵌套的方式来完成一对多的信息存储
多对多, 图书与作者的关系,一本书可能有多个作者,而一个作者也可以有多本书
书的记录
{
_id:<objectId>,
书名:XXX,
出版商:xxx,
出版日期:xxxx,
作者:[xxxx,xxxx]}
}
作者的记录
{_id:<objectId>,
作者名:xxx,
作者出生年月:'xxxx-xxxx',
图书:["xxx","xxx","xxx"]
}
多对多的情况下,看查询的所面对的对象,如果查询的是一本书的作者,则从书的角度查询,反之从作者的角度来查询,他写过几本书。都只需要从一个collection中查出,相关的结果,而只从一个collection中查出数据就可以。
这也就与之前传统数据库中的范式冲突,因为数据存在冗余。
但这并不是问题,数据的冗余换来的是查询的性能的优化,高并发的大批量的查询都是可以被支持的。
总结一下, MONGODB设计
1先通过业务来判定,是否应该通过MONGODB来解决问题是否是MONGODB 擅长的领域
2通过技术架构,以及应用中的数据存储设计,将一对一,一对多,多对多的问题解决。
3MONGODB 在频繁更新数据中不适用,但可以换一个想法,不少数据库中UPDATE 被转换为插入的模式,所以MONGODB 的UPDATE操作可以变更为数据版本的更新,在每个document 中增加一个版本的标识,在查询的时候,版本标识最后的信息为有效的,同时在业务低峰期,通过各种方式来清理过期的数据,也可能是一个不错的方法。