NoSQL入门
(原创:黑小子-余)
1、NoSQL是什么
NoSql(NoSQL=Not Only SQL),意即“不仅仅是SQL”,泛指菲关系型数据库。传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。
(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
2、为什么要用NoSQL
在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付。在那个时候,更多的都是静态网页,动态交互类型的网站不多。
后来,随着访问量的上升,几乎大部分使用MySQL架构的网站在数据库上都开始出现了性能问题,web程序不再仅仅专注在功能上,同时也在追求性能。程序员们开始大量的使用缓存技术来缓解数据库的压力,优化数据库的结构和索引。开始比较流行的是通过文件缓存来缓解数据库压力,但是当访问量继续增大的时候,多台web机器通过文件缓存不能共享,大量的小文件缓存也带了了比较高的IO压力。在这个时候,Memcached(分布式缓存)就自然的成为一个非常时尚的技术产品。
(1)Memcached(缓存)+MySQL+垂直拆分
Memcached作为一个独立的分布式的缓存服务器,为多个web服务器提供了一个共享的高性能缓存服务,在Memcached服务器上,又发展了根据hash算法来进行多台Memcached缓存服务的扩展,然后又出现了一致性hash(Hash算法也被称为散列算法,Hash算法虽然被称为算法,但实际上它更像是一种思想。Hash算法没有一个固定的公式,只要符合散列思想的算法都可以被称为是Hash算法)来解决增加或减少缓存服务器导致重新hash带来的大量缓存失效的弊端。
(2)Mysql主从读写分离
由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可扩展性。Mysql的(主)master-slave(从)模式成为这个时候的网站标配了。
(3)分表分库+水平拆分+mysql集群
在Memcached的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM。
MyISAM:默认表类型,属于索引组织表;它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合。
InnoDB:有两种存储方式,共享表空间存储和多表空间存储,两种存储方式的表结构和myisam一样,以表名开头,扩展名是.frm。支持事务安全的引擎,支持外键、行锁、事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS(Queries Per Second意思是“每秒查询率”)较高的情况,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
同时,开始流行使用分表分库来缓解写压力和数据增长的扩展问题。这个时候,分表分库成了一个热门技术,是面试的热门问题也是业界讨论的热门技术问题。也就在这个时候,MySQL推出了还不太稳定的表分区,这也给技术实力一般的公司带来了希望。虽然MySQL推出了MySQL Cluster(集群),但性能也不能很好满足互联网的要求,只是在高可靠性上提供了非常大的保证。
(4)MySQL的扩展性瓶颈
MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。
(5)为什么使用NoSQL ?
今天我们可以通过第三方平台(如:Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。
3、NoSQL能干什么
易扩展:NoSQL能干什么?简单来说:它的特点就是去掉关系数据库的关系型提醒。数据之间无关系,这样就非常容易扩展,也无形之间,在架构的层面上带来了可扩展的能力。
大数据量高性能:.NoSql数据库都具有非常高的读写性能,尤其在大数据下,同样表现优秀。这得益于它的无关系行、数据库结构简单。
一般MySQL使用Query Cache(查询缓存),每次表的更新Cache就失效,是一种大粒度的Cache。在针对web2.0的交互频繁的应用,Cache性能不高,而NoSQL的Cache是记录级的。是一种细粒度的Cache,所以NoSQL在这个层面上来说就要性能高很多了。
多样灵活的数据模型:NoSql无需事先为要存储的数据建立字段,随时可以存储自定义,也就是创建自己的数据格式。而在关系数据库中,增、删字段是一件非常麻烦的事情,如果是非常大的数据量的表,增加一个字段那你就会想死。
(1)传统RDBMS VS NoSql:
RDBMS(传统的关系型数据库):高度组织化结构化数据结构化查询语言(SQL)、数据和关系都存储在单独的表中、数据操纵语言,数据定义语言、严格的一致性。
ACID原则:A(Atomicity)原子性、C (Consistency)一致性、I (Isonlation)隔离性、D (Durability)持久性
NoSQl(非关系型数据库):代表着不仅仅是SQL、没有声明性查询语言、没有预定义的模式、键-值对存储,列查询,文档存储,图形数据库、最终一致性,而非ACID属性、高性能,高可用和高可伸缩性,
CAP原则:(又称CAP定理)指的是在一个分布式系统中,
一致性(Consistency),数据一致更新,所有数据变动都是同步的。
可用性(Availability),好的响应性能。
分区容错性(Partition tolerance),可靠性。这三个要素最多只能同时实现两点,要么AP,要么CP,要么AC,但是不存在CAP,也就是不能三者兼顾,就像“鱼和熊掌两者不可兼得”。
4、分类
(1)键值(Key-Value)存储数据库
这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。Key/value模型对于IT系统来说的优势在于简单、易部署。但是如果DBA只对部分值进行select或update的时候,Key/value就显得效率低下了。(举例如:Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB)。
(2)列存储数据库
这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。如:Cassandra(开源分布式混合型的非关系的数据库), HBase(分布式的、面向列的开源数据库), Riak(分布式高可用键值对数据库)。
(3)文档型数据库
文档型数据库的灵感是来自于Lotus Notes(是一个世界领先的企业级通讯、协同工作及Internet/Intranet平台)办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB(开源的面向文档的数据库管理系统), MongoDb(分布式文件存储的数据库,介于关系数据库和非关系数据库之间的产品), 国内也有文档型数据库SequoiaDB(金融级分布式关系型数据库),已经开源。
(4)图形(Graph)数据库
图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。如:Neo4J(高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中), InfoGrid(post关系web应用程序的平台), Infinite Graph(图形类数据库)。
5、体系框架
NoSQL框架体系NosoL整体框架分为四层,由下至上分为数据持久层(data persistence)、整体分布层(data distribution model)、数据逻辑模型层(data logical model)、和接口层(interface),层次之间相辅相成,协调工作。
(1)数据持久层:定义了数据的存储形式,主要包括基于内存、基于硬盘、内存和硬盘接口、订制可拔插四种形式。基于内存形式的数据存取速度最快,但可能会造成数据丢失。基于硬盘的数据存储可能保存很久,但存取速度较基于内存形式的慢。内存和硬盘相结合的形式,结合了前两种形式的优点,既保证了速度,又保证了数据不丢失。订制可拔插则保证了数据存取具有较高的灵活性。
(2)数据分布层:定义了数据是如何分布的,相对于关系型数据库,NoSQL可选的机制比较多,主要有三种形式:一是CAP支持,可用于水平扩展。二是多数据中心支持,可以保证在横跨多数据中心是也能够平稳运行。三是动态部署支持,可以在运行着的集群中动态地添加或删除节点。
(3)数据逻辑层:表述了数据的逻辑变现形式,与关系型数据库相比,NoSQL在逻辑表现形式上相当灵活,主要有四种形式:一是键值模型,这种模型在表现形式上比较单一,但却有很强的扩展性。二是列式模型,这种模型相比于键值模型能够支持较为复杂的数据,但扩展性相对较差。三是文档模型,这种模型对于复杂数据的支持和扩展性都有很大优势。四是图模型,这种模型的使用场景不多,通常是基于图数据结构的数据定制的。
(4)接口层:为上层应用提供了方便的数据调用接口,提供的选择远多于关系型数据库。接口层提供了五种选择:Rest,Thrift,Map/Reduce,Get/Put,特定语言API,使得应用程序和数据库的交互更加方便。
小结:NoSQL分层架构并不代表每个产品在每一层只有一种选择。相反,这种分层设计提供了很大的灵活性和兼容性,每种数据库在不同层面可以支持多种特性。
MongoDB(分布式文件存储 的数据库)
着重介绍一下MongoDB,MongoDB:是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似Json的Bjson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,还支持为数据建立索引。它的特点是:高性能、易部署、易使用、存储数据非常方便。
主要功能特性:
(1)面向集合存储,易存储对象类型的数据
“面向集合”( Collenction-oriented),意思是数据被分组,存储在数据集中,被称为一个集合。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库里的表,不同的是它不需要定义任何模式( Schema)。
(2)模式自由
模式自由,意味着对于存储在Mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同结构的文件存储在同一个数据库里,有点类似于“雌雄同体”的感觉。
(3)MongoDB已经在多个站点部署,
主要场景如下:
1、网站实时数据处理。它非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
2、缓存。由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,由它搭建的持久化缓存层可以避免下层的数据源过载。
3、高伸缩性的场景。非常适合由数十或数百台服务器组成的数据库,它的路线图中已经包含对MapReduce引擎的内置支持。
不适用的场景如下:
1、要求高度事务性的系统。
2、传统的商业智能应用。
3、复杂的跨文档(表)级联查询。
Mongodb官网下载地址:https://www.mongodb.com/download-center#community
Windows平台安装教程:https://www.runoob.com/mongodb/mongodb-window-install.html
Linux平台安装教程:https://www.runoob.com/mongodb/mongodb-linux-install.html
Mac OSX 平台安装教程:https://www.runoob.com/mongodb/mongodb-osx-install.html
1、环境配置
(教程网址:https://www.runoob.com/mongodb/mongodb-java.html)
在 Java 程序中如果要使用 MongoDB,你需要确保已经安装了 Java 环境及 MongoDB JDBC 驱动。
(1)首先你必须下载mongo jar包,下载地址:https://mongodb.github.io/mongo-java-driver/, 请确保下载最新版本。
(2)你需要将 mongo-java-driver-3.12.0.jar (找到合适的版本)包含在你的 classpath 中。
(3)国内 mongodb-driver jar 下载地址:http://central.maven.org/maven2/org/mongodb/mongo-java-driver/
(4)连接数据库(java代码示例)
import com.mongodb.MongoClient;import com.mongodb.client.MongoDatabase;
public class MongoDBJDBC{
public static void main( String args[] ){
try{
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("ycs");
System.out.println("Connect to database successfully");
}catch(Exception e){
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
}
}}
2、MongoDB 命令
备注:这里用ycs作为创建的数据库,用aaa作为集合(类似表),bbb作为文档
创建数据库:use DATABASE_NAME #如果数据库不存在,则创建数据库,否则切换到指定数据库
例如:use ycs (>use 数据库名。创建完毕后输入 >db ,就会显示你刚刚创建的实例:ycs)
查看所有数据库:show dbs
插入数据:db.ycs.insert({"name":"黑小子教程"})WriteResult({ "age" : 21 })
注意:MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。
删除数据库:db.dropDatabase()
注意:删除当前数据库,默认为 test,你可以使用 show dbs 或者 db 命令查看当前数据库名,然后命令:use ycs 切换到你要删除的数据库,再执行命令:db.dropDatabase()进行删除。
创建集合:db.createCollection("aaa") # 集合,类似数据库中的表。name: 要创建的集合名称,options:可选参数, 指定有关内存大小及索引的选项。
例如: >use ycs >db.createCollection("aaa")
options 参数:
capped(布尔):(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。注意:当该值为 true 时,必须指定 size 参数。
autoIndexId(布尔):如为 true,自动在 _id 字段创建索引。默认为 false。
Size(数值):(可选)为固定集合指定一个最大值,以千字节计(KB)。如果 capped 为 true,也需要指定该字段。
Max(数值):(可选)指定固定集合中包含文档的最大数量。
查看已有集合: show collections 或 show tables
删除集合:db.collection.drop()
例如: >use ycs >show collections >db.aaa.drop()
插入文档:db.COLLECTION_NAME.insert(document) #使用 insert() 或 save() 方法向集合中插入文档
例如:>db.bbb.insert({title: ‘MongoDB 教程‘,
description: ‘MongoDB 是一个 Nosql 数据库‘,
by: ‘黑小子教程‘,
url: ‘http://www.runoob.com‘,
tags: [‘mongodb‘, ‘database‘, ‘NoSQL‘],
likes: 100})
查看已插入文档:db.bbb.find()
更新文档:db.collection.update( <query>,<update>,
{
upsert: <boolean>, multi: <boolean>, writeConcern: <document>
}) #使用 update() 和 save() 方法来更新集合中的文档
参数说明:
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,抛出异常的级别。
例如:(在上面插入文档示例基础上进行修改)
>db.bbb.update({‘title‘:‘MongoDB 教程‘},{$set:{‘title‘:‘MongoDB‘}}) #如需修改多条:则需要设置 multi 参数为 true。
例如: >db.col.update({‘title‘:‘MongoDB 教程‘},{$set:{‘title‘:‘MongoDB‘}},{multi:true})
查看是否更新文档成功: find()
例如:>db.bbb.find().pretty()
删除文档:remove()
语法:db.bbb.remove(
<query>,
{
justOne: <boolean>,writeConcern: <document>
})
列如:>db.aaa.remove({‘title‘:‘MongoDB 教程‘})
参数说明:
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
查询文档:db.collection.find(query, projection)
参数说明:
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
排序: sort() #语法:>db.COLLECTION_NAME.find().sort({KEY:1})
注意:skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit()。
指定数量的数据记录(分页):limit() #语法: >db.COLLECTION_NAME.find().limit(NUMBER)
注意:limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。
跳过指定数量的数据(筛选):skip() #语法:>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
创建索引:createIndex() #语法:>db.collection.createIndex(keys, options)
注意: Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。
#createIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)。
语法:>db.aaa.createIndex({"title":1,"description":-1})
聚合:aggregate() #主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。
语法:>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
数据备份:mongodump
#语法:>mongodump -h dbhost -d dbname -o dbdirectory
参数说明:
-h : MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d : 需要备份的数据库实例,例如:ycs
-o : 备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
数据恢复:mongorestore
#语法:mongorestore -h <hostname><:port> -d dbname <path>
参数说明:
--host <:port>, -h <:port>:MongoDB所在服务器地址,默认为: localhost:27017
--db , -d :需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
--drop:恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!
<path>:mongorestore 最后的一个参数,设置备份数据所在位置,例如:c:\data\dump\test。你不能同时指定 <path> 和 --dir 选项,--dir也可以设置备份目录。
--dir:指定备份的目录,你不能同时指定 <path> 和 --dir 选项。
监控:mongostat 和 mongotop
在你已经安装部署并允许MongoDB服务后,你必须要了解MongoDB的运行情况,并查看MongoDB的性能。这样在大流量的情况下可以很好的应对并保证MongoDB正常运作。
示例:启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongostat命令,如下所示:
D:\set up\mongodb\bin>mongostat
D:\set up\mongodb\bin>mongotop
MongodDB很强大,这里只诠释了它的背景和用处还有常用的一些操作,还有许多没有功能和用处没有展示出来,可以去官网了解,也根据文中提供的网址去详细了解。如果本文有不合格的地方,可以指正,三人行,必有我师!
qq:2931445528
---------------------------------------------------------END----------------------------------------------------------------
原文地址:https://www.cnblogs.com/ycs0403/p/12116637.html