MongoDB的水平扩展,你做对了吗?

分布式数据库的前世今生

当人们一开始使用数据库系统的时候,所有数据都是跑在一台服务器上,即所谓的单机数据库服务器。在企业级应用中,我们会搭建一台应用程序服务器,一般它会被运行在一台服务器或者工作站上,大多数情况下采用 Linux/Unix/Windows 操作系统,也有人把这样的服务器称之为应用程序服务器。顾名思义,他的作用是处理复杂的业务逻辑。但是一点需要注意的是,在这样的构架中,这台应用程序服务器不会存储任何业务数据,也就是说,他只负责逻辑运算,处理用户请求,真正存放数据的地方是前面提到的那台数据库服务器。应用程序服务器将用户的请求转换成数据库语言(通常是 SQL),运行在数据库中,从而进行数据的增删改查。数据库服务器不会对外直接开放,管理人员也不允许直接在数据库层面操作数据。所有的操作都会经过应用程序服务器来完成。应用程序层、数据库层再加上 UI 层,被称为传统的 Web 三层构架。

Replication

随着数据量的增大,技术的不断进步以及需求的增加,安全性、可靠性、容错性、可恢复性等因素被人们考虑进数据库的设计中。于是出现了分布式数据库系统。以前在存储数据的时候,都是采用单体构架模式,及数据全部存储在一台数据库中,一旦数据库出现问题,所有的应用请求都会受到影响。数据库的恢复也是一个令人头疼的问题。有时一次数据库的全恢复会运行几个小时甚至几天的时间。在互联网应用不断普及的今天,业务需求对构架产生了严峻的挑战。没有哪个互联网应用会允许若干小时的宕机时间。分布式数据库的产生,为我们提供了技术上的解决方案。在部署数据库的时候,不用于以前的单体应用,分布式下数据库部署包括多点部署,一套业务应用数据库被分布在多台数据库服务器上,分主从服务器。主服务器处理日常业务请求,从服务器在运行时不断的对主服务器进行备份,当主服务器出现宕机、或者运行不稳定的情况时,从服务器会立刻替换成主服务器,继续对外提供服务。此时,开发运维人员会对出现问题的服务器进行抢修、恢复,之后再把它投入到生产环境中。这样的构架也被称作为高可用构架,它支持了灾难恢复,为业务世界提供了可靠的支持,也是很多企业级应用采用的主流构架之一。需要指出的是,在这样的主从设计中,从数据库常常被设计成只读,主数据库支持读写操作。一般会有一台主数据库连接若干台从数据库。在互联网产品的应用中,人们大多数情况下会对应用服务器请求读操作,这样应用服务器可以把读操作请求分发到若干个从数据库中,这样就避免了主数据库的并发请求次数过高的问题。至于为什么大多数应用都是读操作,你可以想一下在你使用微信或者微博的时候,你是看别人发布的图片多还是自己发布的时候多。当你不断下滑屏幕,刷新朋友圈,这些都是读请求。只有当评论、点赞、分享的时候才会进行写操作。

我们的世界就是这样,当技术为人们解决了现实问题以后,新的需求会层出不穷。智能手机,互联网 +,创业潮的不断兴起,点燃了这样一个拥有几千年文明历史的民族的激情。各种新点子、新概念不断的涌现,谁的手机里没有安装几十个互联网应用,从订餐,快递,到住房,旅游,再到教育,养老,那一个环节没有互联网的支持,没有技术的成分。我们就是生存在这样一个的平凡而又不乏豪情的社会中。许许多多的需求和数据充斥着我们的构架,挑战着我们的存储。

对此,你可能已经想到,前面提到的分布式数据库多点部署是不是会存在大量的瓶颈。比如,在主从数据库结构中,从数据库的内容基本上可以说是主数据库的一份全拷贝,这样的技术称之为ReplicationReplication在实现主从数据同步时,通常采用Transaction Log的方式,比如,当一条数据插入到主数据库的时候,主数据库会像Trasaction Log中插入一条记录来声明这次数据库写纪录的操作。之后,一个Replication Process会被触发,这个进程会把Transaction Log中的内容同步到从数据库中。整个过程如下图所示:

对于数据库的扩展来说,通常有两种方法,水平扩展和垂直扩展。

  • 垂直扩展:这种扩展方式比较传统,是针对一台服务器进行硬件升级,比如添加强大的 CPU,内存或者添加磁盘空间等等。这种方式的局限性是仅限于单台服务器的扩容,尽可能的增加单台服务器的硬件配置。优点是构架简单,只需要维护单台服务器。
  • 水平扩展:这种方式是目前构架上的主流形式,指的是通过增加服务器数量来对系统扩容。在这样的构架下,单台服务器的配置并不会很高,可能是配置比较低、很廉价的 PC,每台机器承载着系统的一个子集,所有机器服务器组成的集群会比单体服务器提供更强大、高效的系统容载量。这样的问题是系统构架会比单体服务器复杂,搭建、维护都要求更高的技术背景。MongoDB 中的 Sharding 正式为了水平扩展而设计的,下面就来挤开 shard 面纱,探讨一下 shard 中不同分片的技术区别以及对数据库系统的影响。

分片 (Shard)

前面提到的 Replication 结构可以保证数据库中的全部数据都会有多分拷贝,数据库的高可用可以保障。但是新的问题是如果要存储大量的数据,不论主从服务器,都需要存储全部数据,这样检索必然会出现性能问题。可以这样讲,Replication只能算是分布式数据库的第一阶段。主要解决的是数据库高可用,读数据可以水平扩展,部分解决了主数据并发访问量大的问题。但是它并没有解决数据库写操作的分布式需求,此外在数据库查询时也只限制在一台服务器上,并不能支持一次查询多台数据库服务器。我们假设,如果有一种构架,可以实现数据库水平切分,把切分的数据分布存储在不同的服务器上,这样当查询请求发送到数据库时,可以在多台数据库中异步检索符合查询条件的语句,这样不但可以利用多台服务器的 CPU,而且还可以充分利用不同服务器上的 IO,显而易见这样的构架会大大提高查询语句的性能。但是这样的实现却给数据库设计者代码不少麻烦,首先要解决的就是事务(Transaction),我们知道在进行一次数据库写操作的时候,需要定一个事务操作,这样在操作失败的时候可以回滚到原始状态,那当在分布式数据库的情况下,事务需要跨越多个数据库节点以保持数据的完整性,这给开发者带来不少的麻烦。此外,在关系型数据库中存在大量表关联的情况,分布式的查询操作就会牵扯到大量的数据迁移,显然这必将降低数据库性能。但是,在非关系型数据库中,我们弱化甚至去除了事务和多表关联操作,根据 CAP 理论:在分布式数据库环境中,为了保持构架的扩展性,在分区容错性不变的前提下,我们必须从一致性和可用性中取其一,那么,从这一点上来理解“NoSQL 数据库是为了保证 A 与 P,而牺牲 C”的说法,也是可以讲得通的。同时,根据该理论,业界有一种非常流行的认识,那就是:关系型数据库设计选择了一致性与可用性,NoSQL 数据库设计则不同。其中,HBase选择了一致性与分区可容忍性,Cassandra选择了可用性与分区可容忍性。

本文关注于非关系型数据库中分区的技巧和性能,以 MongoDB 为例进行说明,在下面的章节中就围绕这一点展开讨论。

MongoDB 分片原理

MongoDB 中通过 Shard 支持服务器水平扩展,通过 Replication 支持高可用(HA)。这两种技术可以分开来使用,但是在大数据库企业级应用中通常人们会把他们结合在一起使用。

MongoDB Sharding

首先我们简要概述一下分片在 MongoDB 中的工作原理。通过分片这个单词我们可以看出,他的意思是将数据库表中的数据按照一定的边界分成若干组,每一组放到一台 MongoDB 服务器上。拿用户数据举例,比如你有一张数据表存放用户基本信息,可能由于你的应用很受欢迎,短时间内就积攒了上亿个用户,这样当你在这张表上进行查询时通常会耗费比较长的时间,这样这个用户表就称为了你的应用程序的性能瓶颈。很显然的做法是对这张用户表进行拆分,假设用户表中有一个age年龄字段,我们先做一个简单的拆分操作,按照用户的年龄段把数据放到不同的服务器上,以 20 为一个单位,20 岁以下的用户放到 server1,20 到 40 岁的用户放到 server2,40-60 岁的用户放到 server3,60 岁以上放到 server4,后面我们会讲这样的拆分是否合理。在这个例子中,用户年龄age就是我们进行Sharding(切分)的Shard Key(关于 Shard Key 的选择后面会详细介绍),拆分出来的server1server2server3server4就是这个集群中的 4 个Shard(分区)服务器。好,Shard 集群已经有了,并且数据已经拆分完好,当用户进行一次查询请求的时候我们如何向这四个 Sh

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值