《构建高性能Web站点》笔记:9 数据库的扩展

数据库的扩展问题可以拆为两个子问题
  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区 …
   b. 按区间: [1-1000]放A, [1001-2000]放B ….
   c. 另建一张全表,记录每个user_id所处的区
     

 
   

 

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.