这篇开始学习非关系型数据库NoSQL。以前一直不明白为什么没有字段的数据库怎么还能够称作数据库,并且还取得这么大的成功。后来学习了他的发展史才明白。借用看到的一句总结
关系型数据库想把一致性、完整性、索引、CRUD都干好,但是NoSQL只关注与性能分布式相关的非功能性的东西。
传统数据库的瓶颈
任何一门新技术的出现都不是偶然,一定是在它本领域的应用中出现了瓶颈,学者们为了解决这种瓶颈,才会导致一门新技术的产生。因此,在介绍noSQL数据库之前,先来看一下传统的关系型数据库出现的问题。
从关系数据库说起
关系型数据库,把所有的数据都通过行和列的二元形式来表示。其中,一行叫一个元祖(记录),一列叫一个属性(字段)。关系型数据库最大的特点就是事务的一致性,传统的关系型数据库的读写操作都是事务的,也就是要遵循ACID(原子性、一致性、隔离性、永久性)。
在关系数据库中,做的最出色的应该就是mySQL了,由于开源、轻量级、易使用等众多优良的特性,MySQL成为了关系数据库中应用最为广泛的数据库。其他数据库,如Oracle、SQLServer、Sybase、Informix、access、DB2等也都是关系型数据库。
但是,随着近年来数据量的激增,以及一些SNS应用的出现,一致性变得不是那么重要了。另外,关系数据库为了维护一致性的巨大代价就是读写性能比较差,而Web2.0的应用对于并发读写的要求极高,因此,迫切需要对它进行改进,增强它在读写方面的性能。
另外,关系型数据库的另外一个特点就是其具有固定的表结构,因此,扩展性较差。当系统升级、功能增加等情况出现时,需要对存有大量数据的数据库进行结构改变,将是一场巨大的灾难。因此,对数据新的结构化存储方式也成为了需要解决的问题。
MemCached
上面说到数据量激增给传统关系型数据库带来的性能方面的压力,为了解决这个方面,人们首先提出了用缓存的方法,将数据库中常用的一些数据转移到缓存中,从而降低对数据库的读写操作。
开始的时候,使用文件缓存的形式来做的,但当访问量继续增加的时候,文件间共享带来的IO也成了一个负担。
后来,MemCached就出现了,成为了一个卓有成效的解决方案。它是一个独立的分布式缓存服务器,为多个Web服务器提供一个共享的高性能缓存服务。它的出现在一定程度上缓解了数据库的读写压力。
分表分库
但是,大量的读写集中在一个数据库上,还是带来很多性能上的问题。分表分库就成了在当时比较有效的解决方法。
分表分库,从字面上理解,就是把原本存储在一个库的数据分别存储在多个库上。把原本存储于一个表的数据分在多张表上。
原因
这么做的原因就是:
- 数据库表并不是可控的,随着时间和业务的发展,库中的表会越来越多,表的容量也会越来越大。相应的,数据操作、增删改查的开销也会越来越大。
- 由于无法进行分布式部署,一台服务器的资源是有限的,最终数据库所能承受的数据量、数据处理能力都将遭受瓶颈。
实施策略
分为垂直切分和水平切分:
切分类型 | 方法 | 适用范围 |
---|---|---|
垂直切分 | 把表按照功能模块、关系密切程度等切分开来,部署到不同的库上(定义数据库workDB、商品数据库payDB、用户数据库userDB、日志数据库logDB等) | 数据库表多、项目的各个业务逻辑划分清晰、低耦合 |
水平切分 | 当一张表的数据量过大时,将该表按照某种规则进行划分,然后存储到多个结构相同的表(userTable0、userTable1) | 数据库表不多,但单表的数据量大、数据热度高 |
存在的问题
事务问题
在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。跨库跨表的join问题
在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。额外的数据管理负担和数据运算压力
额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算,例如,对于一个记录用户成绩的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需一个order by语句就可以搞定,但是在进行分表之后,将需要n个order by语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果。
NoSQL
说了半天终于到我们的主角 NoSQL了。我们先看一下NoSQL的进化史。
NoSQL进化史
- Key-Value时代
- BigTable时代
- Document时代
- 全文搜索时代
- Graph数据库时代
发展阶段 | 特征 | 示例 | 存在的问题 |
---|---|---|---|
Key-Value | 简单强大 | Oracle Coherence, Redis, Kyoto Cabinet | 查找一定范围的key很麻烦 |
Ordered Key-Value | 可以控制数据存储的顺序 | ||
BigTable | map里有map,map里再套map,一层一层套下去,也就是层层嵌套的key- value(value里又是一个key-value),这种数据库的Value主要通过“列族”(column families),列,和时间戳来控制版本。 | Apache HBase, Apache Cassandra | |
Document databases | 允许Value中有主观的模式(scheme),而不是map套map。第二个是索引。 | MongoDB, CouchDB | |
Text Search Engines | 可以提供灵活的可变的数据模式(scheme)以及自动索引,他们之间的不同点主要是,文档数据库用字段名做索引,而全文搜索引擎用字段值做索引。 | Apache Lucene, Apache Solr | |
Graph data models | 允许构建议图结构的数据模型。很多实现允许value可以是一个map或是一个document。 | neo4j, FlockDB |