`
zhengdl126
  • 浏览: 2538641 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

分表处理设计思想和实现

阅读更多
一、概述
分表是个目前算是比较炒的比较流行的概念,特别是在大负载的情况下,分表是一个良好分散数据库压力的好方法。
首先要了解为什么要分表,分表的好处是什么。我们先来大概了解以下一个数据库执行SQL的过程:
接收到SQL --> 放入SQL执行队列 --> 使用分析器分解SQL --> 按照分析结果进行数据的提取或者修改 --> 返回处理结果
当然,这个流程图不一定正确,这只是我自己主观意识上这么我认为。那么这个处理过程当中,最容易出现问题的是什么? 就是说,如果前一个SQL没 有执行完毕的话,后面的SQL是不会执行的 ,因为为了保证数据的完整性,必须对数据表文件进行锁定,包括共享锁和独享锁两种锁定。 共享锁是在锁定的期间, 其它线程也可以访问这个数据文件,但是不允许修改操作,相应的,独享锁就是整个文件就是归一个线程所有,其它线程无法访问这个数据文件。一般MySQL中 最快的存储引擎MyISAM,它是基于表锁定的,就是说如果一锁定的话,那么整个数据文件外部都无法访问,必须等前一个操作完成后,才能接收下一个操作, 那么在这个前一个操作没有执行完成,后一个操作等待在队列里无法执行的情况叫做阻塞,一般我们通俗意义上叫做“锁表”。
锁表直接导致的后果是什么?就是大量的SQL无法立即执行,必须等队列前面的SQL全部执行完毕才能继续执行。这个无法执行的SQL就会导致没有结果,或者延迟严重,影响用户体验。
特别是对于一些使用比较频繁的表,比如SNS系统中的用户信息表、论坛系统中的帖子表等等,都是访问量大很大的表,为了保证数据的快速提取返回给用户,必须使用一些处理方式来解决这个问题,这个就是我今天要聊到的分表技术。
分表技术顾名思义,就是把若干个存储相同类型数据的表分成几个表分表存储,在提取数据的时候,不同的用户访问不同的表,互不冲突,减少锁表的几 率。 比如,目前保存用户分表有两个表,一个是user_1表,还有一个是 user_2 表,两个表保存了不同的用户信息,user_1 保存了前10万的用户信息,user_2保存了后10万名用户的信息,现在如果同时查询用户 heiyeluren1 和 heiyeluren2 这个两个用户,那么就是分表从不同的表提取出来,减少锁表的可能。
我下面要讲述的两种分表方法我自己都没有实验过,不保证准确能用,只是提供一个设计思路。下面关于分表的例子我假设是在一个贴吧系统的基础上来进行处理和构建的。(如果没有用过贴吧的用户赶紧Google一下)
二、基于基础表的分表处理
这个基于基础表的分表处理方式大致的思想就是:一个主要表,保存了所有的基本信息,如果某个项目需要找到它所存储的表,那么必须从这个基础表中 查找出对应的表名等项目,好直接访问这个表。如果觉得这个基础表速度不够快,可以完全把整个基础表保存在缓存或者内存中,方便有效的查询。
我们基于贴吧的情况,构建假设如下的3张表:
1. 贴吧版块表: 保存贴吧中版块的信息
2. 贴吧主题表:保存贴吧中版块中的主题信息,用于浏览
3. 贴吧回复表:保存主题的原始内容和回复内容
“贴吧版块表”包含如下字段:
版块 ID       board_id          int(10)
版块名称     board_name      char(50)
子表 ID       table_id            smallint(5)
产生时间     created             datetime
“贴吧主题表”包含如下字段:
主题 ID          topic_id        int(10)
主题名称         topic_name     char(255)
版块 ID          board_id          int(10)
创建时间        created           datetime
“贴吧回复表”的字段如下:
回复 ID        reply_id           int(10)
回复内容       reply_text        text
主题 ID        topic_id           int(10)
版块 ID        board_id         int(10)
创建时间       created            datetime
那么上面保存了我们整个贴吧中的表结构信息,三个表对应的关系是:
版块 --> 多个主题
主题 --> 多个回复
那么就是说,表文件大小的关系是:
版块表文件 < 主题表文件 < 回复表文件
所以基本可以确定需要对主题表和回复表进行分表,已增加我们数据检索查询更改时候的速度和性能。
看了上面的表结构,会明显发现,在“版块表”中保存了一个"table_id"字段,这个字段就是用于保存一个版块对应的主题和回复都是分表保存在什么表里的。
比如我们有一个叫做“PHP”的贴吧,board_id是1,子表ID也是1,那么这条记录就是:
board_id | board_name | table_id | created
1 | PHP | 1 | 2007-01-19 00:30:12
相应的,如果我需要提取“PHP”吧里的所有主题,那么就必须按照表里保存的table_id来组合一个存储了主题的表名称,比如我们主题表的前缀是“topic_”,那么组合出来“PHP”吧对应的主题表应该是:“topic_1”,那么我们执行:
SELECT * FROM topic_1 WHERE board_id = 1 ORDER BY topic_id DESC LIMIT 10
这样就能够获取这个主题下面回复列表,方便我们进行查看,如果需要查看某个主题下面的回复,我们可以继续使用版块表中保存的“table_id”来进行查询。比如我们回复表的前缀是“reply_”,那么就可以组合出“PHP”吧的ID为1的主题的回复:
SELECT * FROM reply_1 WHERE topic_id = 1 ORDER BY reply_id DESC LIMIT 10
这里,我们能够清晰的看到,其实我们这里使用了基础表,基础表就是我们的版块表。那么相应的,肯定会说:基础表的数据量大了以后如何保证它的速度和效率?
当然,我们就必须使得这个基础表保持最好的速度和性能,比如,可以采用MySQL的内存表来存储,或者保存在内存当中,比如Memcache之类的内存缓存等等,可以按照实际情况来进行调整。
一般基于基础表的分表机制在SNS、交友、论坛等Web2.0网站中是个比较不错的解决方案,在这些网站中,完全可以单独使用一个表来来保存基本标识和目标表之间的关系。使用表保存对应关系的好处是以后扩展非常方便,只需要增加一个表记录。
优势 】增加删除节点非常方便,为后期升级维护带来很大便利
劣势 】需要增加表或者对某一个表进行操作,还是无法离开数据库,会产生瓶颈
三、基于 Hash 算法的分表处理
我们知道Hash表就是通过某个特殊的Hash算法计算出的一个值,这个值必须是惟一的,并且能够使用这个计算出来的值查找到需要的值,这个叫做哈希表。
我们在分表里的hash算法跟这个思想类似:通过一个原始目标的ID或者名称通过一定的hash算法计算出数据存储表的表名,然后访问相应的表。
继续拿上面的贴吧来说,每个贴吧有版块名称和版块ID,那么这两项值是固定的,并且是惟一的,那么我们就可以考虑通过对这两项值中的一项进行一些运算得出一个目标表的名称。
现在假如我们针对我们这个贴吧系统,假设系统最大允许1亿条数据,考虑每个表保存100万条记录,那么整个系统就不超过100个表就能够容纳。按照这个标准,我们假设在贴吧的版块ID上进行hash,获得一个key值,这个值就是我们的表名,然后访问相应的表。
我们构造一个简单的hash算法:
function get_hash($id){
     $str = bin2hex($id);
     $hash = substr($str, 0, 4);
     if (strlen($hash)<4){
         $hash = str_pad($hash, 4, "0");
     }
     return $hash;
}
算法大致就是传入一个版块ID值,然后函数返回一个4位的字符串,如果字符串长度不够,使用0进行补全。
比如:get_hash(1) ,输出的结果是“3100”,输入:get_hash(23819) ,得到的结果是:3233,那么我们经过简单的跟表前缀组合,就能够访问这个表了。那么我们需要访问ID为1的内容时候哦,组合的表将是:topic_3100、 reply_3100,那么就可以直接对目标表进行访问了。
当然,使用hash算法后,有部分数据是可能在同一个表的,这一点跟hash表不同,hash表是尽量解决冲突,我们这里不需要,当然同样需要预测和分析表数据可能保存的表名。
如果需要存储的数据更多,同样的,可以对版块的名字进行hash操作,比如也是上面的二进制转换成十六进制,因为汉字比数字和字母要多很多,那么重复几率更小,但是可能组合成的表就更多了,相应就必须考虑一些其它的问题。
归根结底,使用hash方式的话必须选择一个好的hash算法,才能生成更多的表,然数据查询的更迅速。
优点 hash算法直接得出目标表名称,效率很高 】通过
劣势 】扩展性比较差,选择了一个hash算法,定义了多少数据量,以后只能在这个数据量上跑,不能超过过这个数据量,可扩展性稍差
四、其它问题
1. 搜索问题
现在我们已经进行分表了,那么就无法直接对表进行搜索,因为你无法对可能系统中已经存在的几十或者几百个表进行检索,所以搜索必须借助第三方的组件来进行,比如Lucene,Sphinx作为站内搜索引擎是个不错的选择。
2. 表文件问题
我们知道MySQL的MyISAM引擎每个表都会生成三个文件,*.frm、*.MYD、*.MYI 三个文件,分表用来保存表结构、表数据和表索引。Linux下面每个目录下的文件数量最好不要超过1000个,不然检索数据将更慢,那么每个表都会生成三 个文件,相应的如果分表超过300个表,那么将检索非常慢,所以这时候就必须再进行分,比如在进行数据库的分离。
使用基础表,我们可以新增加一个字段,用来保存这个表保存在什么数据。使用Hash的方式,我们必须截取hash值中第几位来作为数据库的名字。这样,完好的解决这个问题。
五、总结
在大负载应用当中,数据库一直是个很重要的瓶颈,必须要突破,本文讲解了两种分表的方式,希望对很多人能够有启发的作用。当然,本文代码和设想没有经过任何代码测试,所以无法保证设计的完全准确实用,具体还是需要读者在使用过程当中认真分析实施。
分享到:
评论

相关推荐

    大数据表的分表处理设计思想和实现(MySQL)

    【大数据表的分表处理设计思想与实现】 在MySQL中,面对海量数据的存储和处理,单个表的规模过大可能会导致查询效率下降,甚至影响系统的稳定性和可用性。为了解决这一问题,分表设计成为了数据库优化的重要手段。...

    数据库分表处理设计思想和实现

    数据库分表处理是一种应对高负载环境下数据库压力的有效策略。在大数据量的情况下,单表操作可能导致锁表、阻塞,严重影响数据库性能和用户体验。为了解决这些问题,分表技术应运而生,通过将数据分散到多个表中,...

    hibernate-分表插件实现思路

    标题中的"hibernate-分表插件实现思路"意味着我们要讨论的是如何利用Hibernate的扩展性,设计一个能够根据特定策略将数据分散到多个物理表中的插件。这个插件的主要目标是提高查询效率,减少单表的压力,并提供一种...

    数据库分库分表思路.docx

    总之,数据库分库分表是应对大数据挑战的重要手段,它通过将数据分散存储,降低了单一数据库的压力,提高了查询效率,但也引入了新的挑战,需要在设计和实现时充分考虑各种因素,以平衡系统性能、开发复杂度和数据...

    Node.js 实现的 MySQL 分表分库中间件,用于海量数据的分布式集群储存管理和高并发访问。.zip

    在Node.js中实现这样的中间件,意味着开发人员可以利用Node.js的灵活性和性能优势,来设计一个高效、可配置的分库分表方案。 TribeDB-master 这个压缩包可能包含了一个名为"TribeDB"的开源项目源代码,该项目可能...

    Mybaits-plus优雅的实现多数据源及分表

    在IT行业中,数据库管理和优化是至关重要的环节,尤其是在大数据量的场景下。本文将深入探讨如何使用...然而,这只是一个基本的思路,实际的实现还需要结合业务特点,进行详细的设计和优化,以确保系统的稳定性和效率。

    数据分库分表之二叉树分库分表

    ### 数据分库分表之二叉树分库分表 #### 一、引言与背景 随着互联网技术的快速发展及用户需求的激增,单一...对于需要处理大量数据的企业而言,合理设计并实施二叉树分库分表方案,能够显著提升系统的性能和稳定性。

    应对sharding-jdbc结合mybatis实现分库分表功能 分表的联合查询采用将mysql的数据同步到elasticsearch进行筛选

    在IT行业中,数据库扩展是解决高并发、大数据量场景下的常见问题。Sharding-JDBC是阿里巴巴开源的一款轻量级的数据库中间件,它允许开发者在...这样的设计思路在大数据量的场景下,能够提高系统的查询效率和整体性能。

    HashFNV算法的-分表代码.rar

    在这个压缩包中的"分表代码"文件,很可能是用某种编程语言(如Java、Python或C++)实现的HashFNV算法和分表逻辑的示例,你可以通过阅读和学习这段代码,了解具体的实现细节,并将其应用于自己的项目中。

    Yii 读写分离 分表分库

    在大型系统中,数据库的读写操作往往成为性能瓶颈,因此,实现读写分离和分库分表是优化数据库性能的重要手段。本文将深入探讨在Yii框架下如何实现这一目标。 一、读写分离 读写分离的基本思想是将数据库的读操作...

    高性能高并发服务器架构大全

     分表处理设计思想和实现 174  Linux系统高负载 MySQL数据库彻底优化(1) 179  大型数据库的设计与编程技巧 本人最近开发一个访问统计系统,日志非常的大,都保存在数据库里面。 我现在按照常规的设计方法...

    数据库分库分表(sharding)的技术

    ### 数据库分库分表(Sharding)技术详解 #### 一、基本概念与原理 **数据库分库分表(Sharding)**是一种常见的数据库优化...但在实施过程中需要注意切分规则的选择和设计,以确保系统的稳定运行和长期可维护性。

    高并发,多子系统 配置化,任务入库定时处理设计思想

    配置化和任务入库定时处理的设计思想则是优化系统架构、提高效率的重要手段。以下将详细阐述这些概念及其应用。 首先,"高并发"是指系统在同一时间能够处理大量用户的请求,这在互联网服务中尤其重要。实现高并发的...

    对分库分表的一些想法

    分库分表是一种常见的数据库水平扩展技术,其核心思想是将一个大表的数据分散到多个数据库或多个表中,以减轻单一数据库的压力,提升数据处理速度。 1. 分库:当单个数据库的负载过高时,可以通过将数据按照某种...

    分库分表数据看板项目实战

    总结起来,"分库分表数据看板项目实战"涵盖了数据库架构设计、分布式中间件使用、数据处理与分析、可视化展示等多个方面,是提升数据库系统性能和运维能力的宝贵实践。通过这个项目,你可以深入了解并掌握分库分表的...

    《PHPer》第二期.rar

    分表处理设计思想和实现.......................................... 31 编写安全的 PHP 代码............................................ 35 变量没有初始化引起安全漏洞.....................................

    分库分表shardingjdbc

    ### 分库分表shardingjdbc知识点详述 ...- **实现原理**:介绍 ShardingSphere 可插拔架构的设计思想和技术实现。 - **使用规范**:如何利用 ShardingSphere 的可插拔特性构建复杂的分布式系统。

    Ibatis之分表分库解决方案

    分库分表是数据库水平扩展的一种方法,它的核心思想是将一个大表分为多个小表,分布在不同的数据库服务器上,以此来分散负载,提升查询效率。Ibatis在实现这一策略时,主要涉及以下几个关键点: 1. **分片规则**:...

Global site tag (gtag.js) - Google Analytics