数据库sharding-基本策略和原理

来源:互联网 发布:博时大数据100好买 编辑:程序博客网 时间:2024/06/06 02:46

1.分库分表(sharding)的原因

    在网站初期,为了节约资源,常常部署单点(单一服务器)mysql作为数据存储。随着网站业务量增大,机器的性能有限,单点mysql的I/O性能瓶颈马上达到高潮。

    为了突破单节点I/O的性能,聪明的架构师开始引入多节点,这就是所谓分库。如果说单节点是单线程串行计算,那么多节点就是多线程并行计算。多节点的mysql服务借鉴了并行的思想,将原本对单点的操作分散到N台机器上,提升的效果明显。

    有可能我们的网站发展很迅速,每天的注册用户很多,然而这些注册用户都是存放在一张user表上的,这张表越来越大,每一次insert操作需要维护的成本也非常高。于是乎,就开始将user表拆分成user_1,user_2...等表,这就是所谓分表。


2.切分(sharding)的主要思想

    顾名思义,切分就是指:按照一定的规则对数据库或者数据表进行分割,然后按照一定的路由策略找到数据所对应的数据库和数据表,进行增删改查(CRUD)操作。

    数据库切分策略=分库+分表+路由

    总体来说:分库分表主要有两种方式:垂直切分与水平切分


3.垂直切分:

    将数据库中关系相近的表分散到不同的数据库中。在实际生产中,常常将耦合低,独立性高,相互影响小的各个模块所用的表分拆到不同的数据库中。以微博举例,用户关系、微博动态、图片服务这些分割开来的业务相互之间独立,就可以将三个业务分布到不同的数据库中。

         

    对单一业务来说,可能一个库还是达不到性能要求,就需要将库再分:

        

    垂直切分的作用:

    1.降低了单点I/O的负载:垂直切分又称为物理上的切分:将一个mysql节点(一台服务器)且分到多mysql节点(多台服务器),数据库操作通过路由规则访问特定的数据库,这样一来每次访问面对的就不是单台服务器,而是N台服务器了,达到了并行处理的效果。


4.水平切分

    将一张数据量比较大的表拆分到不同的数据库中,在实际生产中常使用的有按月按日分表,逻辑分表等

    按月分表:

    

    逻辑分表:

        

    水平切分的作用:

    1.提高单表处理速度:原本所有用户信息的操作都在一张user表上进行,假如user表很大,达到千万行,每次insert带来更新索引的成本或者select查询的成本都很高,速度慢。

    2.提高并发操作效率:写操作会带来行锁甚至表锁,分表有助于提高并发效率。


路由策略:

    分库分表之后,如何找到相应数据所在的位置是我们需要关心的。

    常用的路由策略有:

    1.按号分段:

        user_id为区分,1-1000对应DB1,1001-2000对应DB2依次类推

        优点:可部分迁移

        缺点:数据分布不均

        这里的按号分段,主要问题还在于热点读写明显,写入都会集中在最后一个库,读取也大都会集中在最后一个库,所以最后一个库往往也是瓶颈所在。举个场景:假设已存有10000个uid,并且采用按号分段,1-1000在DB1,归纳推演到9000-10000在DB10。新注册的用户由于较为活跃且uid大于10000,所以DB11的压力会大。


    2.hash取模

        对user_id等字段进行hash值计算后取模。比如应用中分为4个库的话,对hash(user_id)%4为1的对应DB1,为2的对应DB2,为3的对应DB3,为0的对应DB4

        优点:数据分布均匀

        缺点:迁移麻烦,不能按照机器性能分摊数据

两者结合:

    后续数据量极大了之后,往往也是按号分段 + hash取模结合的来做。比如按号分段往往做法就是归档(比如每年归档)。

    结合的方式,比如一种典型的场景是:

    每年产生200亿条数据,系统如果跑个5年,就会有1000亿条数据。为了有效提高数据库性能,现阶段往往都会使用ssd磁盘,但是ssd的容量比起sata的小。如果所有数据放在一起,就比较难调整,其实最老的那900多亿数据基本都不大访问到(读和写),反倒是最近的几十亿可能是较多用到。

如果一刀切的方式,全部用ssd,那么需要机器也不少,如果用sata,又会有性能瓶颈。所以一种做法可能是按年切分,最近1-2年的用ssd,由于访问量大可能也会挂多个slave,比如挂5个slave。更早的数据就使用sata,可能就挂2个slave就够了




常用的设计方案:

    1.提供分库规则和路由规则

    2.引入集群,保证数据的可用性

    3.引入负载均衡

    4.引入集群节点探测

    5.引入读写分离

提供分库规则和路由规则&&引入集群,保证数据的可用性&&引入读写分离

    采用数据库切分方案后,由N台数据库组成了一个完整的DB,某台服务器宕机的话,只会损失1/N量的数据。

    然而大部分时候我们都不能容忍数据的丢失,于是乎引入了集群的概念。也就是在每一个分库的节点引入多台服务器,每台服务器存储的数据都是一样的。   

    

    如图所示,整个DB由3个库组成,分别为DB1,DB2,DB3,每个库为一个集群,包含1个Master和5个Slave,Master负责写,Salve负责读。

    Master和Slaver之间的数据是同步的,如果其中一个slave宕机,其他的slave的数据还在,就不会发生数据丢失的情况。    

    Master和Slaver的问题:

         如果读和写都在一个节点上,由于写操作涉及到锁的问题,都会降低系统的执行效率,采用M/S策略,一方面有效的提高了读的效率,一方面也保证了数据的可用性。不过如何保证M和S之间数据的同步呢,Master旺旺会成为瓶颈所在,写操作需要顺序队列来执行,过载的话Master首先扛不住,然后Slave同步的延迟也比较大,损耗CPU的计算性能。


引入负载均衡&&引入集群节点探测:

    对于整个DB来说,每个分库的压力会有所不同。对于整个分库来说,每个Slave的压力也会有所不同。基于这种需求,我们引入了负载均衡的概念。

    具体的规则如下:负载均衡器会分析当前sql的读写特性,如果是写操作或者是要求实时性很强 的操作的话,直接将查询负载分到Master,如果是读操作则通过负载均衡策略分配一个Slave。我们的负载均衡器的主要研究放向也就是负载分发策略, 通常情况下负载均衡包括随机负载均衡和加权负载均衡。

    然而负载均衡器如何知道每个库的性能呢?有两种方式:

    1.每个分库或者Slave节点定时报告性能情况(主动交代)

    2.负载均衡器轮询每个节点查询性能情况(被动询问)

0 0
原创粉丝点击