介绍MongoDB是一个开源、分布式、面向文档的菲律宾关系型数据库。它可以运行在Windows、Unix、OSX和Solaris系统上,支持32位和64位应用程序,并提供多种编程语言的驱动程序。MongoDB支持的数据结构非常松散。它是一种类似于JSON的BSON格式。它以键值对的形式存储数据,可以存储复杂的数据类型。基本概念文档(document):文档是MongoDB的核心概念,它是数据的基本单位,类似于关系数据库中的一行。在MongoDB中,文档表示为一组有序的键值对。文档通常用以下样式标记:{"title":"hello!"}{"title":"hello!","re??commend":5}{"title":"hello!","re??commend":5,"author":{"firstname":"paul","lastname":"frank"}}从上面的例子我们可以看出文档的值有不同的数据类型,甚至可以是一个完整的embeddeddocument(***Aexampleauthorisadocument)集合:集合是文档的集合,相当于关系数据库中的数据表。MongoDB数据库不是关系型数据库,没有schema的概念。同一个集合中的文档可以有不同的形式。例如:{"name":"jack","age":19}{"name":"wangjun","age":22,"sex":"1"}可以存在于同一个集合中。数据库(database):多个文档组成一个集合,多个集合组成一个数据库。一个MongoDB实例可以承载多个数据库,每个数据库可以有0个或多个集合。MongoDB的主要目标是结合键值存储(提供高性能和高可扩展性)和传统RDBMS(关系数据库)系统的优点。MongoDB适用于以下场景:网站数据:Mongo非常适合实时插入、更新和查询,具有网站实时数据存储所需的复制性和高扩展性。缓存:由于其高性能,Mongo也适合作为信息基础设施的缓存层。系统重启后,Mongo构建的持久化缓存可以防止底层数据源过载。大容量、低价值的数据:使用传统的关系数据库存储一些数据可能成本更高。在此之前,很多程序员往往会选择传统的文件进行存储。可扩展性高的场景:Mongo非常适合由几十台或上百台服务器组成的数据库。对象和JSON数据的存储:Mongo的BSON数据格式非常适合文档格式的存储和查询。当然,MongoDB也有不适合的场景:高度事务性的系统:比如银行或者会计系统。传统的关系型数据库还是更适合需要大量事务的应用。传统商业智能应用:针对特定问题的BI数据库可以提供高度优化的查询方式。对于这样的应用,数据仓库可能是更合适的选择(比如Hadoop套件中的Hive)。需要SQL的问题。集群策略在商业环境中,MongoDB通常以集群的形式来实现高可用。MongoDB的集群环境搭建非常简单。以下是介绍。主从模式在我们使用MySQL数据库的时候被广泛使用。采用双机备份后,主节点挂掉,从节点可以接替主节点继续服务。所以这种模式比单节点可靠得多。下面我们一步步看一下如何搭建MongoDB主从复制节点:1、准备两台机器10.43.159.56和10.43.159.58。10.43.159.56作为主节点,10.43.159.58作为从节点。2、单独下载MongoDB安装包。在10.43.159.56创建文件夹/data/MongoDBtest/master,在10.43.159.58创建文件夹/data/MongoDBtest/slave。3、在10.43.159.56启动MongoDB主节点程序。注意下面的“-master”参数,表示master节点:mongod-dbpath/data/MongoDBtest/master-master输出日志如下,成功:[initandlisten]MongoDBstarting:pid=18285port=27017dbpath=/data/MongoDBtest/大师大师=14。在10.43.159.58启动MongoDB从节点程序。关键配置:指定主节点ip地址和端口–source10.43.159.56:27017标记从节点–slave参数:mongod–dbpath/data/MongoDBtest/slave–slave–source10.43.159.56:27017输出日志为如下,success:[initandlisten]MongoDBstarting:pid=17888port=27017dbpath=/data/MongoDBtest/slaveslave=1日志显示从节点从主节点同步复制数据:[replslave]repl:fromhost:10.43.159.56:27017这样,主从结构的MongoDB集群就搭建好了,是不是很简单呢?我们来看看这个集群能做什么?先登录从节点shell,执行插入数据:mongo127.0.0.1:27017>db.testdb.insert({"test3":"testval3"});notmaster可以看到MongoDB的从节点可以只能读,不能进行写操作。那么如果主服务器挂了,从服务器能接管吗?可以试试,强行关闭master节点上的MongoDB进程,登录slave节点,再次执行插入数据:>db.testdb.insert({"test3":"testval3"});notmaster就可以了好像slave节点并没有自动接管master节点的工作,只有手动处理,停止slave节点,然后再启动slave节点为主。由于从节点上的数据与主节点相同,此时从节点可以代替主节点工作。属于手动切换。另外,我们可以搭建多个从节点,实现数据库的读写分离。比如主节点负责写,多个从节点负责读。对于移动应用来说,大部分操作都是读操作,可以实现负载分担。那么,这种主从结构的集群能否应对商业环境呢?我们发现还有几个问题亟待解决:主节点宕机时能否自动切换连接?目前需要手动切换。如何解决master节点写入压力过大?每个从节点上的数据都是数据库的完整副本。从节点压力会不会太大?即使对从节点路由实现了路由访问策略,是否可以实现自动扩容呢?解决这些问题取决于下面介绍的副本集模式。副本模式MongoDB官方不推荐使用主从模式。另一种方法是使用副本集模式。那么什么是副本集呢?简单来说,副本集就是一个具有自动故障恢复功能的主从集群,或者说主从模式实际上是一个单副本应用,没有很好的扩展性和容错性。副本集有多个副本来保证容错性。即使一个副本失败,仍然有很多副本。更棒的是,副本集的很多部分都是自动化的,它为你做了很多管理工作。聪明的读者发现,第一个手动切换主从模式的问题就解决了。难怪MongoDB官方强烈推荐这种模式。我们来看一下MongoDB副本集的架构图:从图中我们可以看到,客户端连接的是整个副本集,不管具体的机器是否宕机。主服务器负责读写整个副本集,副本集定期同步数据备份。一旦主节点挂掉,副本节点将选举一个新的主服务器。应用服务器不需要关心这一切。我们看一下Master服务器挂掉后的架构:副本集中的副本节点通过心跳机制检测到Master节点宕机后,会启动集群中Master节点的选举机制,自动进行选举一个新的主服务器。非常酷!让我们快速部署它!官方推荐的副本集机器数至少是3台(官方说副本集的数量是奇数),所以我们也按照这个数量来配置测试。1、准备三台机器10.43.159.56、10.43.159.58、10.43.159.60。10.43.159.56作为副本集的主节点,10.43.159.58和10.43.159.60作为副本集的副本节点。2.在每台机器上创建一个MongoDB副本集测试文件夹。3、下载并安装MongoDB安装包。4.在每台机器上启动MongoDB。给你的replicaset起个名字,比如叫test:/data/MongoDBtest/MongoDB-linux-x86_64-2.4.8/bin/mongod--dbpath/data/MongoDBtest/replset/data--replSettest可以看到从日志中可以看出副本集尚未初始化。5.初始化副本集在三台机器的任意一台上登录MongoDB:/data/MongoDBtest/MongoDB-linux-x86_64-2.4.8/bin/mongo使用admin数据库:useadmin定义副本集配置变量,其中_id:"test"应与上述命令参数"-replSettest"一致:config={_id:"test",members:[...{_id:0,host:"10.43.159.56:27017"},...{_id:1,host:"10.43.159.58:27017"},...{_id:2,host:"10.43.159.60:27017"}]...}初始化副本集配置:rs.initiate(配置);输出成功:{"info":"Confignowsavedlocally.Shouldcomeonlineinaboutaminute.","ok":1}查看日志。副本集启动成功后,56为主节点PRIMARY,58、60为副本节点SECONDARY。注意,这里是三个节点共同选举的主节点,具有一定的随机性。查看集群节点状态:rs.status();整个副本集已经构建成功。是不是超级简单?副本集模式的MongoDB不仅搭建简单,而且功能强大。现在回过头来看看这种模式能不能解决我们留下的问题:主节点挂了能不能自动切换连接?首先测试副本集的数据复制功能是否正常首先在primary节点56上插入数据,然后查看replica节点上的数据,发现日志报错:error:{"$err":"notmasterandslaveOk=false","code":13435}atsrc/mongo/shell/query.js:128这是因为默认只从master节点读写数据,不允许副本读取,如只要副本可以阅读。在replica节点上执行:rs.slaveOk(),然后查询数据,发现已经同步了master节点的数据。然后测试副本集的故障转移功能,首先停止主节点56上的进程。可以看到节点58和60上的日志显示了投票过程。然后执行rs.status()可以看到集群状态已经更新,56不可达,58成为主节点,60还是副本。再次启动56个节点,发现58还是master节点,56成为replica节点。这解决了第一个自动故障转移问题。那么,如何解决master节点读写压力过大呢?一种常见的解决方案是将读取和写入分开。如何分离MongoDB副本集中的读写?看图说话:对于手机APP场景,写操作通常远少于读操作,所以一个master节点负责写,两个replica节点负责读。从哪个节点读取可以由客户端选择。数据读取参数有五种(Primary、PrimaryPreferred、Secondary、SecondaryPreferred、Nearest):Primary:默认参数,只从主节点读取;PrimaryPreferred:Large部分从主节点读取数据,当主节点不可用时只从从节点读取数据。Secondary:只从Secondary节点执行读操作。问题是Secondary节点的数据会比Primary节点的数据“旧”。SecondaryPreferred:先从secondary节点读取,当secondary节点不可用时从primary节点读取数据;最近:无论是主节点还是从节点,都从网络延迟最高的节点读取数据。在一个典型的副本集网络中,除了副本节点,还有其他角色,比如仲裁节点,如下图所示:仲裁节点不存储数据,只负责故障转移组投票,减少了数据复制的压力。此外,还有Secondary-Only、Hidden、Delayed、Non-Voting等角色。Secondary-Only:不能做主节点,只能作为副副本节点,防止一些性能低的节点成为主节点。Hidden:这类节点不能被客户端指定的IP引用,也不能设置为主节点,但可以投票,一般用于数据备份。Delayed:可以指定一个时间延迟从Primary节点同步数据。主要用于备份数据。如果是实时同步,误删除的数据会立即同步到从节点,无法恢复。Non-Voting:没有投票权的Secondary节点,纯备份数据节点。总结和思考,整个MongoDB副本集解决了两个问题:主节点宕机时能否自动切换连接?//使用副本集时,如何解决主节点读写压力过大的问题?//读写分离还有两个问题需要解决:每个slave节点上的数据都是数据库的全量副本,slave节点会不会压力太大?数据压力大到机器无法支撑,能否实现自动扩容?这个可以通过MongoDB的sharding功能来解决,这个我们下回再说。再见!
