数据库本身功能非常单一,仅可作为数据的存储介质,但错误的数据库选型带来的代价可能就是项目性能的大幅下降,对于很多企业应用来说这也是致命的伤害,另外,选择不同数据库类型同样会决定系统中其他模块的设计,因此,数据库选型对于整个项目非常重要,我们通常也称这种需求为非功能性需求(NFRs,non-functional requirements),对于数据库,主要需要考虑如下三点因素:
目前,市面上已经有各类存储解决方案了,本文我们就来讨论一下如何在这些方案中选择最适合自己的方案。
淘宝、京东这些大型应用都会提供内容的搜索功能,这样就可以方便用户按照商品类型、品牌对数据进行分类搜索,这种功能通常会使用 Solr 或 Elasticsearch 之类的搜索引擎服务,这类搜索服务通常也会支持模糊搜索,例如会考虑到用户拼写错误的情况,这会很大程度上提升用户体验。
但是,搜索引擎不是是数据库,并不能保证我们的数据不会丢失,因此我们不能使用 Elasticsearch 这类搜索引擎作为数据源,这里就需要我们配合两者使用,将数据库中的内容加载到 Elasticsearch 中来降低搜索延迟,然后在以此为基础提供搜索功能。
时序数据库全称为时间序列数据库(Time series database),是关系型数据库的一种,主要用于处理带时间标签(按照时间的顺序变化,即时间序列化)的数据,带时间标签的数据也称为时间序列数据。
很多项目也会需要一类能够存储巨量数据的数据库,如滴滴需要存储所有订单信息来分析哪个城市、那个时间段为使用率最高,这些系统通常和常规用户可感知的交易不同,可以使用脱机类型的数据仓库。Hadoop 是目前主流的数据仓库解决方案。
原子性,保证所有操作要么全有要么全无。
一致性,保证操作前后数据库状态一致。
隔离性,意味着多个事务单独进行,一个事务将不受另一正在进行的并行事务的影响。这能保证数据库应该能够处理并发事务而不会导致数据不一致的情况。
持久性,保证一旦事务完成,更改将被永久写入磁盘,并且不会因系统故障而丢失。
如果我们的项目需要 ACID,则需要使用关系数据库(RDBMS),如 MySQL,Oracle,Postgres 等,但是,如果不需要 ACID,那么也可以非关系性数据库。
如果我们将滴滴中与打车相关的订单数据存储在 Cassandra 后,司机的 id 可以作为每个列分区的 column key,当我们想要查询特定时间段内该司机的路程,Cassandra 就可以立即帮我们在对应列中查询到这些数据,但这时,当我们想要查询某个日期内乘客的乘车记录,由于客户 ID 并不是分区 column key,因此 Cassandra 就需要查询整个分区,这时 Cassandra 性能就会大打折扣!
这种情况下,我们可以使用不同的分区 key 将相同的数据复制到另一个表或列中,这时,当我们收到有关客户 ID 和日期的查询时,我们可以将其直接定向到分区 kay 为客户 ID 的表中,这就是查询的种类少但数据量大的意思,只要查询的类型相似,Cassandra(和 Hbase)就可以无限扩展,但如果查询的种类非常多的话,我们就必须为每个分区 key 一次又一次地复制,直到达到一定的限制。
我们再以淘宝为例,对于一个商品来说,库存中只有一件,但是很多用户想要买,那么最终应该只能卖给一个用户,这就需要我们的数据库拥有 ACID 性质,因此,需要 MySql 这类关系型数据库,但是淘宝中的商品数据也在不断增加,属性也多种多样,我们也需要使用 Cassandra 这种列存储模型的 NoSQL 数据库。我们应该选择哪一种?在实际项目中,我们通常会混合使用这两种数据库,例如,将尚未交付的订单数据存储在 MySQL 数据库中,一旦订单完成,我们就可以将其移至 Cassandra 进行永久存储。
我们的需求还会变得更复杂,假如我们需要为购买商品的客户构建一个报告系统,淘宝上的商品通常会由不同品牌、不同版本向不同的客户出售,因此,报告也不能针对单个产品,而应针对产品的子集,这类需求可以使用 Cassandra 或 MySQL 实现,但是更好的方案是使用 Mongo DB 这类文档型数据库,我们可以将订单数据的子集保存在 MongoDB 中,这些数据可以告诉我们哪些用户在什么时候,什么日期购买了某种商品的数量。因此,如果我们要查询有多少人在上个月购买了 MacBook,我们可以从 MongoDB 中获得订单 ID,并使用此订单 ID 来从 Cassandra 或 MySQL 中查询其他的数据。
https://www.influxdata.com/time-series-database/