数据库的分库分表

一、数据库分库分表的几种方式

    随着业务的不断增长,数据库中的数据也会越来越多,数据库的压力变得越来越大。我们会发现,在业务繁忙的时候,数据库的性能会直线下降。这时,为了保证良好的性能,不得不想办法来分担数据库的压力。如果是分担数据库的读负载,我们可以采用主从复制的方式,给之前的数据库增加几台具有相同数据的从服务器,这样通过读写分离的方式,我们就可以将主服务器的读负载分担到不同的从服务器中了。

    但是,随着业务的进一步发展,这时单一的主数据库已经负担不了写的负载了。那么,这时我们该怎么办呢?当然,我们可以升级主数据库服务器的硬件,但是硬件的扩充也只能解决一时的问题,更何况MySQL对CPU数量的支持也是有一个限度的,所以升级服务器的硬件并不能完美的解决我们所遇到的问题。那么,我们就只能对原来单一的主数据库服务器进行拆分了。

    1、方式一:把一个实例中的多个数据库拆分到不同的实例

        数据库的分库分表

        优点:

            相对来说,实现数据库的拆分比较简单,特别是如果我们业务应用本身就不存在或不允许跨户查询的情况下,实现这种拆分呢实际上只要重新对不同的数据库连接进行配置就可以了。

        缺点:

            如果我们的写压力集中在一个数据库中的话,比如说我们以前的写压力主要集中在订单数据库中,那么这样拆分后实际上并不能减少MySQL节点一的写负载。

    2、方式二:把一个库中的表分离到不同的数据库中

        一个数据库中往往来说会有很多的表,这些表通常会记录不同的主题中的数据。

        数据库的分库分表        

二、数据库分片的准备

    对一个库中的相关表进行水平拆分到不同实例的数据库中

    数据库的分库分表

    1、如何选择分区键

        分区键决定了我们如何对数据库进行分片,以及分片后如何查询数据。分区键选择的是否合适,直接决定了分区后的性能。对于分区键的选择,我们应该做到如下几点:

            . 分区键要能尽量避免跨分片查询的发生

            . 分区键要能尽量使各个分片中的数据平均

    2、如何存储无需分片的表

        (1) 每个分片中存储一份相同的数据

            这种方法通常用于表本身数据量不大,而且也不会经常被更新的一种字典类表,同时这些表又经常需要和分区表在一起关联查询,所以在每个分片中都存储一份冗余的数据,可以更好的提高数据库的查询效率。

            如果使用这种方式,对于维护每个分片中相同表的数据的一致性就显得非常重要了。我们可以使用多写的方式来维护这些表的数据。也就是说,应用在对这些表更新时,会同时更新所有分片中相同的表,但是由于这种更新一般不会放在一个事物中,所以我们一定要定期的对这些表的数据进行检查,以防止由于这些表数据的不一致而造成业务逻辑的问题。

        (2) 使用额外的节点统一存储

            把所有不需要分片的数据存储在一个公共的位置,这种方法的好处是在整个集群中不存在数据的冗余问题,应用也不用维护多份相同的数据。如果分片的表要和这些表进行关联查询的话,那么只能通过程序分别查询后再进行合并操作了。所以这种方法在查询效率上比上一种方法要差一些。

    3、如何在节点上部署分片    

        (1) 每个分片使用单一数据库,并且数据库名也相同

        (2) 将多个分片表存储在一个数据库中,并在表名上加入分片号后缀

        (3) 在一个节点中部署多个数据库,每个数据库包含一个分片

    4、如何分配分片中的数据

        (1) 按分区键的Hash值取摸来分配分片数据

            优点:

                可以相对平均的在各个分片中分配数据。

            缺点:

                很难人为的控制什么样的数据分配到哪个分片中。

        (2) 按分区键的范围来分配分片数据

            常用于分区键为日期类型、数值类型的情况。

            优点:

                我们可以很清楚的知道数据被分配到哪个分片中。

            缺点:

                很容易产生数据分配不平均、数据的访问量不平均的情况。

        (3) 利用分区键和分片的映射表来分配分片数据

    5、如何生成全局唯一ID

        (1) 使用auto_increment_increment和auto_increment_offset参数

            auto_increment_increment的值需要和分片节点的数量相同,这个参数决定了每一次自增ID增长的步长。也就是说如果我们有6个节点的分配集群,那么auto_increment_increment的值就设置为6,auto_increment_offset设置为1-6不同的值。

            这种方式只适用于一个节点中只保存一套分区表的情况。

        (2) 使用全局节点来生成ID

        (3) 在Redis等缓存服务器中创建全局ID

三、数据库分片演示(上)

四、数据库分片演示(下)

相关文章: