数据库的扩展问题可以拆为两个子问题: 1. 高并发时,单台数据库服务器会不堪重负 2. 大数据量时,针对一个大数据集进行数据读写,响应时间会比较长 前端和后端 出于分而治之的理念,可以想到一种理想的方案:把DBMS拆分为数据服务系统和数据存储系统,前者作为用户请求的入口,后者则存储数据,两者的关系类似于web服务器和文件服务器;分离之后,再分别采用针对性的扩展方案,比如说数据服务系统可以像web服务器一样简单地集群,数据存储系统则可以采用类似于分布式文件系统的方案,然后再让“前端”调用“后端”,整体上像一个分布式系统 遗憾的是,传统的DBMS内部似乎并不支持这种分布(TBD)。一个DBMS进程中,一般都既要响应请求,又要存取数据;这种感觉就像,文件只能存放在web服务器里,如果要复制web服务器,就一定要考虑文件怎么处理。 接受“拆不开”这个事实后,再来看目前流行的各种方案。 首先,可以看看如何提高并发能力。 1.搞N个一模一样的数据库服务器,每个服务器分摊一部分用户请求 每台服务器都提供服务,每台服务器上都包含全量数据,这是最直接的方案 问题在于,实时同步各台服务器上的数据本身比较耗费性能:一台服务器上来了新数据,就立即广播出去,然后大家都从它那里复制数据;还没复制完,又有一台服务器广播了一点更新消息。。。如果大家总是忙于跟它人搞双向复制,就没有余力处理用户的请求了 2.服务器之间单向复制数据,并使用单个数据更新源 单向复制比双向复制快的多。一台服务器更新数据后顺便更新一下自己的日志(主服务器),其余服务器只根据这个日志更新自己的数据(从服务器),不再接收用户的数据更新请求。那“从服务器”对高并发又起什么作用呢?他们可以为用户的数据查询请求提供服务。 这就是读写分库,把读和写分摊掉了。 这种方案的问题在于,如果写请求很多,主服务器忙不过来,加再多从服务器也没有用。 3.分摊写请求 主服务器本身可以根据数据更新的目的地的不同,而分拆成不同的结点。 如果一个服务器中有两个库,可以把其中一个库挪到另一台服务器中去(前提是A库和B库基本不join),这样一来,对不同库的数据更新请求就落到了不同的服务器上(当然,读的请求也分摊了)。你也可以把库中不同的表放到不同的服务器上。 这种分法叫垂直分区。 但垂直分区仍有个极限:如果某张表只有一个字段,而且对这张表的请求非常多,你怎么办? 4.再次分摊写请求 可以把1万行的表,拆成10张1000行的子表,放到十台服务器中,这样可以再次分摊请求; 而且理论上说,这种分摊没有极限,数据每增多一点,服务器就多加一台。 这种分法叫做水平分区。其实水平分区不仅可以分摊请求,同时也可以对付大数据集的问题。夸张地说,以前表里有1万行数据,按索引查数据都很慢;现在表里只有1000行数据,全表扫描都无所谓了 大数据量的问题 上面提到的水平分区,已经可以用来对付大数据量的问题。这里就不再提了 最后罗列一下上述各种方案中可以运用的技术或工具 1. 实时、双向同步数据: mysql clustering(TBD) 2. 读写分离: mysql主从复制可以实现读写分离,mysql proxy则可以前置于主从服务器前面,自动决定读、写的归属,为应用程序提供透明的服务 3. 水平分区: 如果要根据user.user_id对user及其相关表分区,对于一个user_id,应该放到哪个区呢? a. 取模: 5,10,15…放A区, 6, 11, 16…放B区 … …
《构建高性能Web站点》笔记:9 数据库的扩展 Read More »