您的位置:首页 > 数据库

关于数据库分表分库的一次分享

2017-12-17 18:40 267 查看
关于数据库分表分库之前也看了不少,目前关于数据库分表分库尚没有统一的规范标准,当你真正拿到需求,需要进行分表分库时,还要具体情况具体分析。在这里主要针对我的一次实践展开说明,为读者提供一点思路。

在进行分表分库策略制定之前,我们先来把需求理明白、数据量预估清楚。

 

需求是这样的,公司最近需要采集一些传感器数据,(至少保存三个月的历史数据,随时查询三个月内的历史数据)每个传感器每30秒上传一次数据,每次传输2-5个数据属性(比如温度、湿度等),每个传输终端大概连接五到十个传感器,而传输终端是可扩展的。一天单个传输终端(按连接10个传感器,每个传感器5个数据属性的满负荷状态计算),共上传数据量为10*5*24*60*2=144000。而传输终端的数量,需求中没有明确提出,但预估应满足至少1000个以上(按1000计算),所以所有数据单表存储的话每天数据增长量为144000*1000=1.44*10^8,而数据存储至少是三个月90天的量,因此该数据表存放数据量为1.44*90*10^8≈1.3*10^8。这个数量级的单表存储量,对于关系型数据库的条件查询效率我们可以想象一下(简单来说就是读操作),那将极低极低,根本不可能满足我们的对rt(response
time)的需求。再想一下写操作,每30秒的写入量为10*5*1000=50000,每秒1667条数据写入,对于正常关系型数据库理论上写入这么多是没问题,但数据库写入

速度跟硬盘的速度,网卡的速度,写入行的数据量,数据在硬盘中的存放位置等等因素都有关系的,至少我所使用的MySQL在个人电脑上的单表写入速度测试远不能满足这个写入量。这还仅仅是写操作,至于读操作,更为频繁,而且加入一定复杂程度的查询条件(一定复杂程度代表着很难利用索引提高查询速度)将导致rt(request time)变得不可接受。在这里加入数据库读写分离策略是必须的,但即使读写分离,上面说的问题还是存在的,因此需要考虑分表分库的策略了。

分表分库不像其它功能实现时,可以找现成的工具完成,必须结合实际业务场景,仔细考量,建立适合应用场景的分表分库策略。这里说说我的分表策略。首先将所有传感器传输的数据脱离原来的数据库,分离出来,并且另建立了三个数据库(01db/02db/03db),用于存放这些数据,而这些数据库里具体有多少表则由传输终端的数量决定,我这里将每个传输终端传输的数据放在一个数据表中(查询数据一般以传输终端为单位),取传输终端的id为表名,并根据表名的hash数值除三取余,根据余数路由至数据库(余数0就在01db创建该表,余数1就在02db创建该表)。在这里为什么要分表呢?因为所有数据都放一张表里,严重影响数据库读写速度,以传输终端为单位,把数据进行分表,有效提高了读写效率。而在这里进行分库的依据是什么呢?是这样的,因为我的传输终端数量是未知的,可能会无限扩展下去,那么总共的表数量也会未知的,我不能保证一个数据库可以存放这个数量的数据表而不影响数据库正常使用。一个数据库在不影响性能的情况下能放多少数据表(记为n),必然跟每个表的数据量有一定关系,每个表数据量都比较大的话,数量n的大小就要打个折扣,在每个表读写都很频繁的情况下,这个数量n就要再打个折扣。因此我暂且将数据库增加了三个,并基本均分了数据量。(当然我应该保障数据库数量的可扩展性,那么在这里我所写的简单根据取余来实现数据表的路由显然就不太合适了,希望您可以在理解这些的基础上,思考出一种更好的路由办法)。

接下来说说具体实现过程(首先说明我所使用的框架spring+springmvc+mybatis),首先在数据库配置文件将我所用到的四个数据库(01db/02db/03db/分离出这部分数据后的原始数据库)的信息都配置进去,并将每个数据库定义一个key值,并完成spring动态数据源AbstractRoutingDataSource的实现,只需要在sql执行之前运用spring
AOP,将所需使用的数据库的key值传入AbstractRoutingDataSource中,spring就能顺利找到正确的数据库,完成sql语句。

 

在这里我主要提供了思路,没有进行代码展示,一是个人认为思路更为重要,二是最近时间有些紧张,没有时间整理代码。在随后的share中,我尽量对这次的share进行一些补充,并把代码附上,供大家指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息