数据库扩展

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

数据库扩展问题当我们对Web计算和存储都进行了不同程度的扩展后,站点的规模不断膨胀,这给数据库带来了巨大的查询压力,尽管前面我们了解了数据库性能优化的一些具体做法,但是,这些显然是不够的,数据库也必须与时俱进,进行扩展。在解决性能问题的同时,数据库的扩展还带来了一些其他的作用,比如增加存储空间、提高可用性等。接下来我们会介绍数据库扩展的一些思路,它们基本上覆盖了大多数扩展方式。解决办法-复制和分离•主从复制•几乎所有的主流数据库产品都支持复制,这是它们进行简单扩展的基本手段,我们以MySQL为例,它支持主从复制,配置•并不复杂,简单地说,你只需要做到以下两点:1\开启主服务器上的二进制日志(log-bin)。2\在主服务器和从服务器上分别进行简单的配置和授权。复制和分离•MySQL的主从复制是依据主服务器的二进制日志进行的,也就是说主服务器日志中记录的操作会在从服务器上进行重放,从而实现复制,所以主服务器必须开启二进制日志,它会自动记录所有对数据库产生更新的操作,也包括潜在的更新操作,比如没有删除任何实际记录的DELETE操作。•显然,这种复制是异步进行的,从服务器定时向主服务器请求最新日志,而主服务器只需要通过一个I/O线程来读取本地二•进制日志,并输送给从服务器即可,所以,复制过程对于主服务器的影响非常有限。但是,当存在多个从服务器同时从一个•主服务器进行复制的时候,主服务器的磁盘压力会有不同程度的增长,这也并不是无法解决的,你可以采用多级复制策略,•就像前面提到的多级分发一样。•在主服务器上对于所有更新操作记录二进制日志,这部分额外开销对性能大概有1%的影响,与复制的意义相比,这几乎是微•不足道的。解决办法-读写分离•一旦我们将数据库复制到更多的服务器上后,关键的问题来了,我们应该怎样合理地给它们分配工作量呢?•这里有一点需要注意,对于所有的更新操作,我们必须让它作用于主服务器上,这样才能保证所有数据库服务器上的数据一致。这也是任何使用单向复制机制的系统必须遵循的更新原则,比如在前面提到的文件分发和同步中,我们也只能对文件源进行更新。•为此,我们采用读写分离(R/WSplitting)的方法将应用程序中对数据库的写操作指向主服务器,而将读操作指向从服务器.读写分离图这样做不仅保证了多台服务器的数据一致性,更重要的是,它符合情理,一般而言,大多数站点的数据库读操作要比写操作更加密集,而且查询条件相对复杂,你可以通过mysql-report来查看SELECT操作的比例,通过前面对数据库性能优化的介绍,我们知道大部分的开销都消耗在这些查询上,而通过读写分离,我们可以将大量的读操作剥离出来,转移到更多的从服务器上实现水平扩展,这是一个非常简单而有效的策略。读写分离缺点•一旦决定采用读写分离,我们必须在应用程序中配置多个数据库连接选项,并且修改数据访问层代码,的确,应用程序知道应该如何区分读写操作,然而,对于将读操作分散到多台从服务器上,应用程序就不那么擅长了,简单的随机分配可能会造成多台从服务器的工作量不均衡,更重要的是,当某台从服务器发生故障后,应用程序并不知道。解决办法-使用数据库反向代理应用程序只需要跟MySQLProxy通信即可,而读写分离的工作都由MySQLProxy来完成,与此同时,MySQLProxy还对多个从服务器实现负载均衡以及可用性检测,这些工作由它来做,的确非常适合。但是,当存在大量的从服务器时,MySQLProxy必然会出现瓶颈效应,不过,即便是到那个时候,主服务器已经无法承受写操作的压力了,结构将不可避免地再次调整,接下来怎么办呢?主从以后还怎么办?对于数据库写操作频繁(write-heavy)的站点来说,仅仅采用主从复制和读写分离可能效果并不明显,假如你的主服务器花费了80%的时间在写数据,那么所有的从服务器也将花费更多的时间来同步数据,可想而知,所有从服务器只能依靠剩余不到20%的时间来处理你的SELECT查询请求,这时候,增加从服务器所获得的回报将越来越少,呈现边际效益递减。另一方面,站点在成长,用户活动越来越频繁,写操作不断增多,主服务器的压力也逐渐接近极限,这时候不论你增加多少台从服务器都无济于事,因为那只是对读操作的分散,并没有对写操作起到任何作用。垂直分区最简单的分离方法当然是将不同的数据库分布到不同的服务器上,你会发现有很多数据库之间并不存在关系,或者不需要进行联合(JOIN)查询,那么为什么不把它们放在不同的服务器上呢?比如我们将用户的博客数据库和好友数据库分别转移到独立的数据库服务器上,这种方式称为垂直分区.可以看到,我们将db_blog和db_friend两个数据库分别转移到了独立的服务器上,而db_main则代表仍然存放在主服务器上的其他一系列数据库,你仍然可以在这里进行必要的联合查询,但是,不论从扩展的角度,还是从查询性能的角度来看,在进行数据库模型设计以及编写应用程序的时候,都应该尽量减少使用联合查询。垂直分区扩展按照这样的思路,一旦我们需要为站点开发新的应用,便可以通过增加新的数据库服务器来实现扩展。同样,我们还可以再次通过主从复制来对db_blog和db_friend两个数据库进行读写分离。这的确是个不错的主意,然而,同样的问题在不久的未来仍然会困扰我们,当db_blog数据库的主服务器再次无法承受写操作压力时,我们又该如何呢?对这个数据库再次进行垂直分区吗?也许你可以将不同的数据表转移到不同的服务器上,但是当数据表也达到写操作极限的时候呢?水平分区•水平分区(Sharding)意味着我们可以将同一数据表中的记录通过特定的算法进行分离,分别保存在不同的数据表中,从而可以部署在不同的数据库服务器上。事实上,很多大规模的站点基本上都经历了从简单主从复制到垂直分区,再到水平分区的步骤,这是一个必然的成长过程。我们来看看如何实现水平分区,值得一提的是,水平分区并不依赖于特定的技术,它更多的是一种逻辑层面的规划,需•要一定的经验和不断的分析。把数据放在不同分区中我们希望将db_blog数据库中的数据拆分到不同的服务器上,并且应用程序能够知道如何找到它们。db_blog数据库中存储了用户发表的博客内容,主要数据都在tbl_posts表中,它的结构如下所示:CREATETABLE`tbl_posts`(`post_id`int(11)NOTNULLauto_increment,`post_title`varchar(64)NOTNULL,`post_content`textNOTNULL,`post_time`int(11)NOTNULLdefault'0',`user_id`int(11)NOTNULL,PRIMARYKEY(`post_id`),KEY`user_id`(`user_id`))其中,user_id代表博客用户的ID,现在我们要将所有用户划分为两部分,为了尽量均衡,我们可以按照user_id的奇偶性质来划分,user_id为奇数和偶数的博客内容分别存储到不同的数据库服务器上.当然也是可以分成10分10分db_blog表结构图分表与分区分表只是单台数据库的优化策略,一旦到了必须考虑扩展的时候,分区便派上用场,不过,已经实现的分表将使得分区更加容易,因为数据已经是分离的,只需要迁移到其他服务器即可。•这时候,分表算法和分区算法可能不一致,比如我们希望将这10个表分布在两台服务器上,那么我们要在应用程序中维护•一份映射关系表,比如将前5个数据表分配到一台数据库服务器,后5个数据表分配到另一台数据库服务器,这时的数据•访问代码如下所示:•?php•$db=newDataAccess($user_id);•$db-selectDb(db_blog);•$tbl_name=getTblName($user_id);•$sql=select*from.$tbl_name.wherepost_id=.$post_id;•$result=$db-query($sql);•?分区算法•哈希算法•范围算法•映射关系我们推荐使用映射关系算法分区算法哈希算法优势刚才我们通过user_id%10来实现分区便是这种算法,它非常容易实现,而且应用程序通过user_id找到分区只需要进行简单的计算,几乎不存在额外开销。相对于其他算法,哈希算法可以为多个分区比较均衡地分配工作量,特别是当记录数量级较多时,各个分区更加趋近于均衡。•哈希算法问题•这种算法对于扩展并不友好,一旦我们需要从10个分区扩展到20个分区,这便涉及所有数据的重新分区,你不得不暂停站点,等待漫长的计算。分区算法•范围算法•指按照分区索引字段的范围进行分区,比如我们可以将user_id为1~10000的记录存储在一个分区中,而将•10001~20000的用户存储在另一个分区中,以此类推。这使得应用程序需要维护一个简单的范围映射表,比如根据user_id来计算所属分区。•显然,它可以带来很好的扩展性,随着用户数量的不断增长,我们可以创建更多的分区。但是,各个分区的工作量会存在较大的差异,比如老用户所在的分区压力相对较大,或者一部分ID比较接近的热点用户导致所在分区压力过大。分区算法•映射关系•将对分区索引字段的每个可能的结果创建一个分区映射关系,这个映射关系将会非常庞大,应用程序已经无法通过•简单的逻辑或者配置文件来维护它,而需要将它也写入数据库,比如当应用程序需要知道user_id为10的用户的博客内容在•哪个分区时,它必须查询数据库获得答案,当然,我们会使用缓存来提高性能。•由于这种方式详细保存了每一个记录的分区对应关系,所以各个分区具有较强的可伸缩性,我们可以灵活地控制它们的规模,•并且轻松地将数据从一个分区迁移到另一个分区,这也使得各个分区可以通过灵活的动态调节来保持平衡。分区反向代理•还记得前面提到的MySQLProxy吗?它帮助应用程序实现了读写分离,而在这里,另一个开源产品SpockProxy也起到了类•似的作用,它可以帮助应用程序实现水平分区的访问调度,这意味着我们不需要在应用程序中维护那些分区对应关系了。•SpockProxy本身的大部分代码正是基于MySQLProxy,同时它也进行了一些改进,在这里,SpockProxy的作用如图所示。分区反向代理结构图MySQLProxy工作机制浅析•MySQLProxy处于客户端应用程序和MySQL服务器之间,通过截断、改变并转发客户端和后端数据库之间的通信来实现其功能,这和WinGate之类的网络代理服务器的基本思想是一样的。代理服务器是和TCP/IP协议打交道,而要理解MySQLProxy的工作机制,同样要清楚MySQL客户端和服务器之间的通信协议,MySQLProtocol包括认证和查询两个基本过程:•认证过程包括:1.客户端向服务器发起连接请求2.服务器向客户端发送握手信息3.客户端向服务器发送认证请求4.服务器向客户端发送认证结果•如果认证通过,则进入查询过程:1.客户端向服务器发起查询请求2.服务器向客户端返回查询结果•MySQLProxy要做的,就是介入协议的各个过程。首先MySQLProxy以服务器的身份接受客户端请求,根据配置对这些请求进行分析处理,然后以客户端的身份转发给相应的后端数据库服务器,再接受服务器的信息,返回给客户端。所以MySQLProxy需要同时实现客户端和服务器的协议。由于要对客户端发送过来的SQL语句进行分析,还需要包含一个SQL解析器。可以说MySQLProxy相当于一个轻量级的MySQL了,实际上,MySQLProxy的adminserver是可以接受SQL来查询状态信息的。•MySQLProxy通过lua脚本来控制连接转发的机制。主要的函数都是配合MySQLProtocol各个过程的,这一点从函数名上就能看出来:connect_server()read_handshake()read_auth()read_auth_result()read_query()read_query_result()

1 / 23
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功