`
hudeyong926
  • 浏览: 2032881 次
  • 来自: 武汉
社区版块
存档分类
最新评论

mysql 分库分表的方法

阅读更多
为什么要分库分表和读写分离
类似淘宝网这样的网站,海量数据的存储和访问成为了系统设计的瓶颈问题,日益增长的业务数据,无疑对数据库造成了相当大的负载,同时对于系统的稳定性和扩展性提出很高的要求。随着时间和业务的发展,数据库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作的开销也会越来越大;另外,无论怎样升级硬件资源,单台服务器的资源(CPU、磁盘、内存、网络IO、事务数、连接数)总是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。分表、分库和读写分离可以有效地减小单台数据库的压力
1、什么是读写分离
读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
2、为什么要读写分离呢?
因为数据库的“写”(写10000条数据到oracle可能要3分钟)操作是比较耗时的。
但是数据库的“读”(从oracle读10000条数据可能只要5秒钟)。
所以读写分离,解决的是,数据库的写入,影响了查询的效率。
3、什么时候要读写分离?
数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用,利用数据库 主从同步 。可以减少数据库压力,提高性能。当然,数据库也有其它优化方案。memcache 或是 表折分,或是搜索引擎。都是解决方法。
数据库垂直拆分与水平拆分
当我们使用读写分离、缓存后,数据库的压力还是很大的时候,这就需要使用到数据库拆分了。
数据库拆分简单来说,就是指通过某种特定的条件,按照某个维度,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面以达到分散单库(主机)负载的效果。
切分模式: 垂直(纵向)拆分、水平拆分。
数据库的垂直拆分
专库专用:一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:
表的垂直拆分
垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。表的记录并不多,但是字段却很长,表占用空间很大,检索表的时候需要执行大量的IO,严重降低了性能。这时需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。 通常会按照一下原则拆分:
1. 把不常用的字段单独放在附表中;
2. 把text,blob等字段拆分出来放在附表中;
3. 经常组合查询的列放在⼀张表中;
优点:
1. 拆分后业务清晰,拆分规则明确。
2. 系统之间整合或扩展容易。
3. 数据维护简单。
4.解决了表与表之间的io竞争。
缺点:
1. 部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。
2. 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。
3. 事务处理复杂。
 

水平拆分

垂直拆分后遇到单机瓶颈,可以使用水平拆分。相对于垂直拆分的区别是:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式,如图

 
优点:
1. 不存在单库大数据,高并发的性能瓶颈。
2. 对应用透明,应用端改造较少。
3. 按照合理拆分规则拆分,join操作基本避免跨库。
4. 提高了系统的稳定性跟负载能力。
缺点:
1. 拆分规则难以抽象。
2. 分片事务一致性难以解决。
3. 数据多次扩展难度跟维护量极大。
4. 跨库join性能较差。

 

分割策略

取模

此种分割策略比较适合用在数据均分灵活且数据分散的需求

 

范围

id range代表当前记录ID的大小范围,比如:0~9999。

/**
 * 根据UID分表算法
 *
 * @param int $uid //用户ID
 * @param int $bit //表后缀保留几位
 * @param int $seed //向右移动位数
 */
function getTable($uid, $bit = 4, $seed = 20) {
    return "user_" . sprintf("%0{$bit}d", ($uid >> $seed));
}

我们将uid向右移动20位,这样我们就可以把大约前100万的用户数据放在第一个表user_0000,第二个100万的用户数据放在第二个表user_0001中,这样一直下去,如果我们的用户越来越多,直接添加用户表就行了。由于我们保留的表后缀是四位,这里我们可以添加1万张用户表,即user_0000,user_0001 ...... user_9999。一万张表,每张表100万数据,我们可以存100亿条用户记录。当然,如果你的用户数据比这还多,也不要紧,你只要改变保留表后缀来增加可以扩展的表就行了,如如果有1000亿条数据,每个表存100万,那么你需要10万张表,我们只要保留表后缀为6位即可

 

按时间分表

这种分表方式有一定的局限性,当数据有较强的实效性,如微博发送记录、微信消息记录等,这种数据很少有用户会查询几个月前的数据,如就可以按月分表。

insertData($data){
    $table = "table_".date("Ym",time()); //生成当天表名
    insert($data,$table);  // 插入新的表中
}

优点:可部分迁移
缺点:数据分布不均,可能2015年01月的订单有100W,2015年02月的有500W。

 

哈希hash取模

<?php
function get_hash_table($table, $userid)
{
    $str = crc32($userid);
    if ($str < 0) {
        $hash = "0" . substr(abs($str), 0, 1);
    } else {
        $hash = substr($str, 0, 2);
    }
    return $table . "_" . $hash;
}
//echo get_hash_table('message', 'user18991'); //结果为message_10
//echo get_hash_table('message', 'user34523'); //结果为message_13
function calc_hash_db($u, $s = 4) {
    $h = sprintf("%u", crc32($u));
    $h1 = intval(fmod($h, $s));
    return $h1;
}

for ($i = 1; $i < 40; $i++) {
    echo calc_hash_tbl($i);
    echo "<br>";
    echo calc_hash_db($i);
    echo "<br>";
}

function calc_hash_tbl($u, $n = 256, $m = 16) {
    $h = sprintf("%u", crc32($u));
    $h1 = intval($h / $n);
    $h2 = $h1 % $n;
    $h3 = base_convert($h2, 10, $m);
    $h4 = sprintf("%02s", $h3);

    return $h4;
}
#################
function getTable( $uid ){
	$ext = substr ( md5($uid) ,0 ,2 );
	return "user_".$ext;
}
###################
private function getDbNo($email)
{
    $m = md5($email);
    $n = hexdec(substr($m, 0, 16));
    $tableNo = fmod($n, 1000);
    $dbNo = $tableNo % 100;
    return array($dbNo, $tableNo);
}

优点:数据分布均匀
缺点:数据迁移的时候麻烦;不能按照机器性能分摊数据 。

查询切分

将id和库的mapping关系记录在一个单独的库中

 

数据迁移的方式

当一些很久之前的数据,很少再查询。比如员工工资表,我们可以只存今年的工资情况。而历史数据我们可以迁移到一张salary_old表中,保证数据不会丢失。但也可以用来查询。每天定期把今年中的最早一天的记录归入旧表中。这样一方面可以解决性能问题,最多也只需要读2张表就完成了。

按热度拆分

典型的像贴吧这种有高点击率的词条,也有低点击率的词条,如果一个词条一张表,那得多少表啊,所以一般这种情况就会对高点击率的词条生成 一张表,低热度的词条都放在一张大表里,待低热度的词条达到一定的贴数后,比如1W条,再把低热度的表单独拆分成一张表。

 

全局主键避重问题
在分库分表环境中,由于表中数据同时存在不同数据库中,主键值平时使用的自增长将无用武之地,某个分区数据库自生成的ID无法保证全局唯一。因此需要单独设计全局主键,以避免跨库主键重复问题。有一些常见的主键生成策略:
1、利用数据库自增ID:auto_increment_increment auto_increment_offset
优点:最简单
缺点:单点风险、单机性能瓶颈
2、利用数据库集群并设置相应的步长(Flickr方案)
优点:高可用、ID较简洁
缺点:需要单独的数据库集群
3、Twitter snowflake
优点:高性能高可用、易拓展
缺点:需要独立的集群以及ZK
4、一大波GUID、Random算法
优点:简单
缺点:生成ID较长,有重复几率

 

分库分表产生的问题,及注意事项
1. 分库分表维度的问题
假如用户购买了商品,需要将交易记录保存取来,如果按照用户的纬度分表,则每个用户的交易记录都保存在同一表中,所以很快很方便的查找到某用户的购买情况,但是某商品被购买的情况则很有可能分布在多张表中,查找起来比较麻烦。反之,按照商品维度分表,可以很方便的查找到此商品的购买情况,但要查找到买人的交易记录比较麻烦。
所以常见的解决方式有:
     a.通过扫表的方式解决,此方法基本不可能,效率太低了。
     b.记录两份数据,一份按照用户纬度分表,一份按照商品维度分表。
     c.通过搜索引擎解决,但如果实时性要求很高,又得关系到实时搜索。
2. 联合查询的问题
联合查询基本不可能,因为关联的表有可能不在同一数据库中。
3.   避免跨库事务
避免在一个事务中修改db0中的表的时候同时修改db1中的表,一个是操作起来更复杂,效率也会有一定影响。
4.   尽量把同一组数据放到同一DB服务器上
例如将卖家a的商品和交易信息都放到db0中,当db1挂了的时候,卖家a相关的东西可以正常使用。也就是说避免数据库中的数据依赖另一数据库中的数据。

  • 大小: 75.5 KB
  • 大小: 41.7 KB
  • 大小: 64.7 KB
  • 大小: 67.7 KB
  • 大小: 81.5 KB
  • 大小: 66.9 KB
  • 大小: 80.1 KB
  • 大小: 20.9 KB
分享到:
评论

相关推荐

    MySQL 分库分表的实现原理及演示案例

    MySQL分库分表是一种数据库架构优化技术,其目的是为了提高大型数据库系统的性能和可扩展性。在面对大规模数据和高并发访问时,单库单表往往难以满足需求,分库分表就成为了必要之选。分库分表技术可以将数据分散...

    MySQL分库分表技术

    **MySQL分库分表技术** 随着互联网业务的快速发展,数据量呈现爆炸性增长,单个数据库的性能瓶颈问题日益突出。在这种背景下,MySQL的分库分表技术应运而生,旨在解决高并发、大数据量场景下的性能挑战。本篇将深入...

    Python+MySQL分表分库实战

    MySQL分库分表是数据库架构设计中用于处理大规模数据量以及高并发请求的一种技术手段。通过将数据拆分到不同的数据库服务器中,能够有效降低单个数据库的负载,提高系统的扩展性和性能。Python作为一种流行的编程...

    一个MySQL分库分表php类

    一个MySQL分库分表php类。当一个表数据记录过大时就会出现性能瓶颈,而一般对应的解决办法是要么做分区表,要么分表,分区表就不说了,分表又分为垂直分割和水平分割,具体区 别请自行搜索。一般而言,分库分表属于...

    MySQL分库分表课件.zip

    MySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库分表课件.zipMySQL分库...

    MySQL 分库分表的实现原理及演示案例.zip

    在实现MySQL分库分表的过程中,通常会遇到一些挑战,如数据一致性、事务处理、跨库跨表查询等。为了应对这些问题,可以使用以下技术: 1. **ShardingSphere**:Apache ShardingSphere是一个开源的分布式数据库解决...

    php mysql分库分表实例

    MySQL分库分表还有其他考虑因素,如数据一致性、事务处理、跨表查询等。在分库分表后,通常需要避免跨库查询,因为这会导致性能下降。可以通过设计良好的API和业务逻辑,尽量在单个数据库中完成大部分操作。此外,还...

    mysql分库分表分区1

    这里的“mysql分库分表分区1”主要讨论的是 MySQL 中的表分区技术,这是一种将大表物理分割为多个更小、更易管理的部分的方法。下面将详细介绍四种常见的分区类型:RANGE、LIST、HASH 和 KEY。 1. **RANGE分区**: ...

    MySQL分库分表无限扩容后的瓶颈及解决方案.docx

    "MySQL 分库分表无限扩容后的瓶颈及解决方案" MySQL 是一个非常popular 的数据库管理系统,广泛应用于各行各业。随着业务的发展,数据量也在不断增长,数据库的性能和容量也将面临着极大的挑战。这篇文章将讨论 ...

    基于Mycat实现Mysql读写分离以及分库分表.doc

    基于Mycat实现Mysql读写分离以及分库分表详解 本文档详细介绍了基于Mycat实现Mysql读写分离以及分库分表的技术,涵盖了Mycat安装、配置、读写分离、分库分表等多方面的知识点。 一、读写分离 Mycat读写分离是指将...

    19道MySQL分库分表高频题整理(附答案背诵版).md

    1. **全面覆盖**:题集涵盖了MySQL分库分表技术中的核心知识点,包括基本概念、设计原则、实现方法、常见问题及解决方案等。 2. **详尽答案**:每道题目提供详细的答案和解释,帮助学习者理解分库分表的实际应用及...

    去年底写的mysql分库分表中间件heisenberg

    **MySQL分库分表中间件Heisenberg详解** 在数据库设计中,随着业务的发展和数据量的增加,单个数据库往往难以承受高并发和大数据量的处理压力,这时就需要引入分库分表策略来优化系统性能。Heisenberg是一款开源的...

    mysql 分库分表查询工具-shard.zip

    MySQL 分库分表查询工具——Shard 在大型的互联网应用中,数据库的性能瓶颈往往成为系统扩展性的关键因素。为了应对高并发、大数据量的挑战,MySQL 数据库的分库分表策略被广泛采用。分库是将数据分散到多个独立的...

    一个MySQL分库分表php类.zip

    分享一个MySQL分库分表php类。当一个表数据记录过大时就会出现性能瓶颈,而一般对应的解决办法是要么做分区表,要么分表,分区表就不说了,分表又分为垂直分割和水平分割,具体区 别请自行搜索。一般而言,分库分表...

    java mysql 分库分表详解

    在Java和MySQL数据库环境中,分库分表是一种常见的解决大数据量和高并发问题的策略。随着互联网业务的快速发展,单个数据库往往无法满足性能和扩展性的需求,这时就需要采用分库分表技术来优化系统架构。 分库是将...

    Mysql分库分表实例.zip

    为了解决这一问题,"Mysql分库分表实例" 提供了一种解决方案——数据分片技术,即通过分库分表来提升数据库的读写效率。 分库分表是数据库水平扩展的一种策略,它的核心思想是将一个大的数据库拆分成多个小的数据库...

    分库分表 各种mysql中间件 总结(csdn)————程序.pdf

    本篇文章将对各种MySQL中间件进行总结,重点关注如何使用ShardingSphere进行分库分表以及相关的配置。首先,我们需要引入必要的依赖库,包括MySQL的JDBC驱动、ShardingSphere的Spring Boot Starter、阿里巴巴的Druid...

    Python与MySQL分表分库实战

    1. **设计合理的分库分表策略**:根据业务需求和数据分布特点,选择合适的分库分表策略,如哈希分片、范围分片或复合键分片。 2. **数据库连接管理**:Python中,可以使用`with`语句管理数据库连接,确保资源及时...

    Mysql分库分表备份脚本

    Mysql分库分表备份脚本

    Python+MySQL分表分库实战 - v1.0 - 运维生存时间 -(2016).mobi

    Python后端运维工程师的可靠参考书,重点介绍如何优化mysql数据库性能。

Global site tag (gtag.js) - Google Analytics