想要知道有没有那种可以提供杠杆的炒股配资杠杆软件呢?

利用一致性哈希水平拆分MySql单表 (求指教) - CNode技术社区
积分: 2180
这家伙很懒,什么个性签名都没有留下。
写在前面, 打算在公司试行这种方案,求大牛指点一二,看看有无错误和遗漏。
Sharding(切片) 不是一门新技术,而是一个相对简朴的软件理念,就是当我们的数据库单机无法承受高强度的i/o时,我们就考虑利用 sharding 来把这种读写压力分散到各个主机上去。
所以Sharding 不是一个某个特定数据库软件附属的功能,而是在具体技术细节之上的抽象处理,是Horizontal Partitioning 水平扩展(或横向扩展)的解决方案,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,注意这里是突破单点数据库服务器的“I/O”能力。
在MySql 5.1 中增加了对单表的 PARTITION(分区)支持,可以把一张很大的单表通过 partition 分区成很多物理文件,避免每次操作一个大文件,可以对读写新能有所提升,下面是一个 partition 分区的例子。
一张游戏的日志表,有几千万行的数据,记录了接近一年的游戏物品获取日志,如果不对它进行 partition 分区存储,每次统计和分析日志都会消耗大量的时间。然后我们新建一张分区表,把老的日志数据导入到新的数据,统计分析的时间就会节约很多。
CREATE TABLE `xxxxxxxx` (
`crttm` int(11) NOT NULL,
`srvid` int(11) NOT NULL,
`evtid` int(11) NOT NULL,
`aid` int(11) NOT NULL,
`rid` int(11) NOT NULL,
`itmid` int(11) NOT NULL,
`itmnum` int(11) NOT NULL,
`gdtype` int(11) NOT NULL,
`gdnum` int(11) NOT NULL,
`islmt` int(11) NOT NULL,
KEY `crttm` (`crttm`),
KEY `itemid` (`itmid`),
KEY `srvid` (`srvid`),
KEY `gdtype` (`gdtype`)
) ENGINE=myisam DEFAULT CHARSET=utf8
PARTITION BY RANGE (crttm)
PARTITION p201303 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201304 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201305 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201306 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201307 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201308 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201309 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201310 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201311 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201312 VALUES LESS THAN (unix_timestamp('')),
PARTITION p201401 VALUES LESS THAN (unix_timestamp(''))
对于这种业务场景,使用 mysql 的 partition 就已经足够了,但是对于 i/o 非常频繁的大表,单机垂直升级也已经支撑不了,存储已经不是影响其性能的主要原因,这时候就要用到sharding了。
我们一般会将一张大表的唯一键作为 hash 的 key,比如我们想要水平拆分的是一张拥有3千万行数据的用户表,我们可以利用唯一的字段用户id作为拆分的依据,这样就可以依据如下的方式,将用户表水平拆分成3张,下面是伪代码,将老的用户数据导入到新的3个被水平拆分的数据库中。
if userId % 3 == 0:
#insert data in user_table (user_table_0 databaseip: 127.0.0.1)
elif userId % 3 == 1:
#insert data in user_table (user_table_1 databaseip: 127.0.0.2)
#insert data in user_table (user_table_2 databaseip: 127.0.0.3)
我们还会对每一个被拆分的数据库,做一个双主 master 的副本集备份,至于backup,我们则可以使用 percona的cluster来解决。它是比 mysql m/s 或者 m/m 更靠谱的方案。
所以最后拆分的拓扑图大致如下:
随着我们的业务增长,数据涨到5千万了,慢慢的发现3个sharding不能满足我们的需求了,因为服务器紧张,所以这时候BOSS打算再加2个sharding,以后会慢慢加到10个sharding。
所以我们得在之前的3台sharding服务器上分别执行导入数据代码,将数据根据新的hash规则导入到每台sharding服务器上。几乎5千万行数据每行都移动了一遍,如果服务器够牛逼,Mysql每秒的插入性能能高达 2000/s,即使这样整个操作,都要让服务暂停8个小时左右。这时候DBA的脸色已经不好看了,他应该是已经通宵在导数据了。
那有没有一种更好的办法,让添加或者删除 sharding 节点对整个分片系统的数据迁移量降低呢?
我们可以利用一致性哈希算法,把用户id散列到各个 sharding 节点,这样就可以保证添加和删除节点数据迁移影响较小。关于什么是一致性哈性算法,参考我的另一篇博客:
这里介绍一个Node.js模块,hashring,github主页地址如下,上面有demo和api文档:
这是一个使用的demo代码,我翻译了注释,供大家参考:
// 加载模块,返回HashRing的构造函数
var HashRing = require('hashring');
//实例化HashRing,这个例子中,我们把各个服务器均匀的添加了,没有设置权重
// 设置了最大的缓冲区 10000
var ring = new HashRing([
'127.0.0.1',
'127.0.0.2',
'127.0.0.3',
'127.0.0.4'
], 'md5', {
'max cache size': 10000
//我们获取这个字符串的服务器ip
var server = ring.get('foo bar banana'); // returns 127.0.0.x
console.log(server)
// 如果你想把数据冗余的存储在多个服务器上
ring.range('foo bar banana', 2).forEach(function forEach(server) {
console.log(server); // do stuff with your server
// 对环上移除或新增加一台服务器
ring.add('127.0.0.7').remove('127.0.0.1');
var server = ring.get('foo bar banana'); // returns 127.0.0.x
console.log(server)
接下来我们就要验证这种方式的可行性。
第一,假如我们有3万条数据,根据一致性哈希算法存储好了之后,这个算法是否能够较平均的将3万条数据分散到3台sharding服务器上。
第二,当数据量增加到5万,然后我们增加2台sharding服务器后,这个算法移动的数据量和最终每台服务器上的数据分布是如何的。
connHashStep1.js将3万用户数据通过一致性哈希算法存储在3台服务器上
var HashRing = require('hashring');
var ring = new HashRing([
'127.0.0.1',
'127.0.0.2',
'127.0.0.3',
], 'md5', {
'max cache size': 10000
var record = {
'127.0.0.1':0,
'127.0.0.2':0,
'127.0.0.3':0
var userMap = {}
for(var i=1; i&=30000; i++){
var userIdStr = i.toString();
var server = ring.get(userIdStr);
userMap[userIdStr] =
record[server]++;
console.log(record);
第一次利用一致性hash之后,每台服务器存储的用户数据。
{ '127.0.0.1': 9162, '127.0.0.2': 9824, '127.0.0.3': 11014 }
connHashStep2.js将5万用户数据通过一致性哈希算法存储在3台服务器上,然后用户数据5万不改变,新增加2台sharding,查看新的5台sharding的用户数据存储情况以及计算移动的数据条数。
var HashRing = require('hashring');
var ring = new HashRing([
'127.0.0.1',
'127.0.0.2',
'127.0.0.3',
], 'md5', {
'max cache size': 10000
var record = {
'127.0.0.1':0,
'127.0.0.2':0,
'127.0.0.3':0
var userMap = {}
for(var i=1; i&=50000; i++){
var userIdStr = i.toString();
var server = ring.get(userIdStr);
userMap[userIdStr] =
record[server]++;
console.log(record);
//新增加2个sharding节点
var record2 = {
'127.0.0.1':0,
'127.0.0.2':0,
'127.0.0.3':0,
'127.0.0.4':0,
'127.0.0.5':0,
ring.add('127.0.0.4').add('127.0.0.5')
var moveStep = 0;
for(var i=1; i&=50000; i++){
var userIdStr = i.toString();
var server = ring.get(userIdStr);
//当用户的存储server改变,则计算移动
if(userMap[userIdStr] && userMap[userIdStr] != server){
userMap[userIdStr] =
moveStep++;
record2[server]++;
console.log(record2);
console.log('move step:'+moveStep);
5万用户数据,存储在3台服务器上的数目:
{ '127.0.0.1': 15238, '127.0.0.2': 16448, '127.0.0.3': 18314 }
当我们sharding增加到5台,存储在5台服务器上的数目:
{ '127.0.0.1': 8869,
'127.0.0.2': 9972,
'127.0.0.3': 10326,
'127.0.0.4': 10064,
'127.0.0.5': 10769 }
最终我们移动的用户数量:
move step:20833
其实你会发现
20833 = 10064 + 10769
也就是说,我们只是将1-3节点的部分数据移动到了4,5节点,并没有多余的移动一行数据。根据上面的示例,如果是5千万数据,利用一致性哈希的算法,添加2个节点,仅需2-3小时就可以完成。
那么什么时候我们需要利用一致性哈希水平拆分数据库单表呢?
1、当我们拥有一个数据量非常大的单表,比如上亿条数据。
2、不仅数据量巨大,这个单表的访问读写也非常频繁,单机已经无法抗住 I/O 操作。
3、此表无事务性操作,如果涉及分布式事务是相当复杂的事情,在拆分此类表需要异常小心。
4、查询条件单一,对此表的查询更新条件常用的仅有1-2个字段,比如用户表中的用户id或用户名。
最后,这样的拆分也是会带来负面性的,当水平拆分了一个大表,不得不去修改应用程序或者开发db代理层中间件,这样会加大开发周期、难度和系统复杂性。
求大牛指点不足,指出错误~
参考链接:
帮忙顶一下吧
感谢帮顶哦~
不明觉厉!
var ring = new HashRing([
// 重复 5 次
'127.0.0.1', '127.0.0.2', '127.0.0.3',
'127.0.0.1', '127.0.0.2', '127.0.0.3',
'127.0.0.1', '127.0.0.2', '127.0.0.3',
'127.0.0.1', '127.0.0.2', '127.0.0.3',
'127.0.0.1', '127.0.0.2', '127.0.0.3',
], 'md5', {
'max cache size': 10000
这种情况。我也忘记我在测的叫什么,但最终 move step 的步数跟文章中是一样的。
你为什么要重复5次?这里存储的就是模拟数据库ip地址,是为了让用户记录找到存储的 ip 地址,重复的话有什么特别的意思吗?
1:对于数据库一般 sharding 都是根据容量进行预估,也就是说 sharding 到几台数据 node 节点要事先定好,如果以后要进行扩容就进行垂直的伸缩,通过mysql复制迁移。而水平伸缩,即使你使用一致性哈希也是会有一定的迁移代价存在
2:5千万数据量对于mysql还好,如果索引设计使用合理的话,还是高效的,优化下sql说不定比sharding效果好
3:mysql sharding 之后就需要中间件了,主要难点在于多表查询(涉及查询计划的生成与优化)与事务上,不过如果是针对特定业务的话,可以简化
赞,看懂了。
英文的解释更精炼些,但是没图。两个结合起来看更好。
感谢大牛回复
对于1表示赞同,但是有时候预估不准,或者从无到有,迈出第一步的时候就要面对了
对于2,你说的对,不到万不得已无需sharding,5千万只是举例,目前还要根据真实的性能测试数据来说话,对于我们的服务器配置,性能的平衡点在哪里?
对于3,我想问下,中间件是DIY自己搞好?还是用成熟的方案?
如果DIY自己搞的话是让应用程序直接抛SQL语句过来解析返回?还是走restful,只支持特定几个业务查询接口呢?
额,大牛提点建议哦~
疑问与回答
1:你们mysql 存储engine用的是myisam?
这个在大量并发插入性能是差的(在你们场景就是迁移的时候),它是表锁
2:中间件node.js目前没有特别牛逼的,如果不要求中间件通用的话,根据业务来做分库分表在业务层上处理下也可以的,就是比如查询,你可以知道具体查询计划,在业务层处理
写得已经很好了。:)
谢谢你的回答
1、引擎室 innodb,迁移其实可以不停业务的,从备库上做好了,昨晚再切生产,没问题的
2、通用的话感觉难度有点大,而且给其他部门用效率不能保证,还是跟业务走,限定查询条件,订制查询计划,这样我们还能针对性的做缓存等,效率应该比较高一些。这块功能不一定用Node.js做,看测试性能了
再次感谢大牛的指点~
写的足够好了,其实一致性哈希主要就是解决宕机和扩容的问题,点个赞。
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
服务器赞助商为
,存储赞助商为
,由提供应用性能服务。
新手搭建 Node.js 服务器,推荐使用无需备案的966,690 三月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
水平分库分表的关键步骤以及可能遇到的问题
水平分库分表的关键步骤以及可能遇到的问题
日. 估计阅读时间:
不到一分钟
相关厂商内容
相关赞助商
QCon北京-18日,北京&国家会议中心,
其中,Twitter 的Snowflake算法是笔者近几年在分布式系统项目中使用最多的,未发现重复或并发的问题。该算法生成的是64位唯一Id(由41位的timestamp+ 10位自定义的机器码+ 13位累加计数器组成)。这里不做过多介绍,感兴趣的读者可自行查阅相关资料。
常见分片规则和策略
分片字段该如何选择
在开始分片之前,我们首先要确定分片字段(也可称为&片键&)。很多常见的例子和场景中是采用ID或者时间字段进行拆分。这也并不绝对的,我的建议是结合实际业务,通过对系统中执行的sql语句进行统计分析,选择出需要分片的那个表中最频繁被使用,或者最重要的字段来作为分片字段。
常见分片规则
常见的分片策略有随机分片和连续分片这两种,如下图所示:
当需要使用分片字段进行范围查找时,连续分片可以快速定位分片进行高效查询,大多数情况下可以有效避免跨分片查询的问题。后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移。但是,连续分片也有可能存在数据热点的问题,就像图中按时间字段分片的例子,有些节点可能会被频繁查询压力较大,热数据节点就成为了整个集群的瓶颈。而有些节点可能存的是历史数据,很少需要被查询到。
随机分片其实并不是随机的,也遵循一定规则。通常,我们会采用Hash取模的方式进行分片拆分,所以有些时候也被称为离散分片。随机分片的数据相对比较均匀,不容易出现热点和并发访问的瓶颈。但是,后期分片集群扩容起来需要迁移旧的数据。使用一致性Hash算法能够很大程度的避免这个问题,所以很多中间件的分片集群都会采用一致性Hash算法。离散分片也很容易面临跨分片查询的复杂问题。
数据迁移,容量规划,扩容等问题
很少有项目会在初期就开始考虑分片设计的,一般都是在业务高速发展面临性能和存储的瓶颈时才会提前准备。因此,不可避免的就需要考虑历史数据迁移的问题。一般做法就是通过程序先读出历史数据,然后按照指定的分片规则再将数据写入到各个分片节点中。
此外,我们需要根据当前的数据量和QPS等进行容量规划,综合成本因素,推算出大概需要多少分片(一般建议单个分片上的单表数据量不要超过1000W)。
如果是采用随机分片,则需要考虑后期的扩容问题,相对会比较麻烦。如果是采用的范围分片,只需要添加节点就可以自动扩容。
跨分片技术问题
跨分片的排序分页
一般来讲,分页时需要按照指定字段进行排序。当排序字段就是分片字段的时候,我们通过分片规则可以比较容易定位到指定的分片,而当排序字段非分片字段的时候,情况就会变得比较复杂了。为了最终结果的准确性,我们需要在不同的分片节点中将数据进行排序并返回,并将不同分片返回的结果集进行汇总和再次排序,最后再返回给用户。如下图所示:
上面图中所描述的只是最简单的一种情况(取第一页数据),看起来对性能的影响并不大。但是,如果想取出第10页数据,情况又将变得复杂很多,如下图所示:
有些读者可能并不太理解,为什么不能像获取第一页数据那样简单处理(排序取出前10条再合并、排序)。其实并不难理解,因为各分片节点中的数据可能是随机的,为了排序的准确性,必须把所有分片节点的前N页数据都排序好后做合并,最后再进行整体的排序。很显然,这样的操作是比较消耗资源的,用户越往后翻页,系统性能将会越差。
跨分片的函数处理
在使用Max、Min、Sum、Count之类的函数进行统计和计算的时候,需要先在每个分片数据源上执行相应的函数处理,然后再将各个结果集进行二次处理,最终再将处理结果返回。如下图所示:
跨分片join
Join是关系型数据库中最常用的特性,但是在分片集群中,join也变得非常复杂。应该尽量避免跨分片的join查询(这种场景,比上面的跨分片分页更加复杂,而且对性能的影响很大)。通常有以下几种方式来避免:
全局表的概念之前在&垂直分库&时提过。基本思想一致,就是把一些类似数据字典又可能会产生join查询的表信息放到各分片中,从而避免跨分片的join。
在关系型数据库中,表之间往往存在一些关联的关系。如果我们可以先确定好关联关系,并将那些存在关联关系的表记录存放在同一个分片上,那么就能很好的避免跨分片join问题。在一对多关系的情况下,我们通常会选择按照数据较多的那一方进行拆分。如下图所示:
这样一来,Data Node1上面的订单表与订单详细表就可以直接关联,进行局部的join查询了,Data Node2上也一样。基于ER分片的这种方式,能够有效避免大多数业务场景中的跨分片join问题。
随着spark内存计算的兴起,理论上来讲,很多跨数据源的操作问题看起来似乎都能够得到解决。可以将数据丢给spark集群进行内存计算,最后将计算结果返回。
跨分片事务问题
跨分片事务也分布式事务,想要了解分布式事务,就需要了解&XA接口&和&两阶段提交&。值得提到的是,MySQL5.5x和5.6x中的xa支持是存在问题的,会导致主从数据不一致。直到5.7x版本中才得到修复。Java应用程序可以采用Atomikos框架来实现XA事务(J2EE中JTA)。感兴趣的读者可以自行参考《分布式事务一致性解决方案》,链接地址:
q.com/cn/articles/solution-of-distributed-system-transaction-consistency
我们的系统真的需要分库分表吗
读完上面内容,不禁引起有些读者的思考,我们的系统是否需要分库分表吗?
其实这点没有明确的判断标准,比较依赖实际业务情况和经验判断。依照笔者个人的经验,一般MySQL单表1000W左右的数据是没有问题的(前提是应用系统和数据库等层面设计和优化的比较好)。当然,除了考虑当前的数据量和性能情况时,作为架构师,我们需要提前考虑系统半年到一年左右的业务增长情况,对数据库服务器的QPS、连接数、容量等做合理评估和规划,并提前做好相应的准备工作。如果单机无法满足,且很难再从其他方面优化,那么说明是需要考虑分片的。这种情况可以先去掉数据库中自增ID,为分片和后面的数据迁移工作提前做准备。
很多人觉得&分库分表&是宜早不宜迟,应该尽早进行,因为担心越往后公司业务发展越快、系统越来越复杂、系统重构和扩展越困难&这种话听起来是有那么一点道理,但我的观点恰好相反,对于关系型数据库来讲,我认为&能不分片就别分片&,除非是系统真正需要,因为数据库分片并非低成本或者免费的。
这里笔者推荐一个比较靠谱的过渡技术&&表分区&。主流的关系型数据库中基本都支持。不同的分区在逻辑上仍是一张表,但是物理上却是分开的,能在一定程度上提高查询性能,而且对应用程序透明,无需修改任何代码。笔者曾经负责优化过一个系统,主业务表有大约8000W左右的数据,考虑到成本问题,当时就是采用&表分区&来做的,效果比较明显,且系统运行的很稳定。
最后,有很多读者都想了解当前社区中有没有开源免费的分库分表解决方案,毕竟站在巨人的肩膀上能省力很多。当前主要有两类解决方案:
基于应用程序层面的DDAL(分布式数据库访问层)&
比较典型的就是淘宝半开源的TDDL,当当网开源的Sharding-JDBC等。分布式数据访问层无需硬件投入,技术能力较强的大公司通常会选择自研或参照开源框架进行二次开发和定制。对应用程序的侵入性一般较大,会增加技术成本和复杂度。通常仅支持特定编程语言平台(Java平台的居多),或者仅支持特定的数据库和特定数据访问框架技术(一般支持MySQL数据库,JDBC、MyBatis、Hibernate等框架技术)。
数据库中间件,比较典型的像mycat(在阿里开源的cobar基础上做了很多优化和改进,属于后起之秀,也支持很多新特性),基于Go语言实现kingSharding,比较老牌的Atlas(由360开源)等。这些中间件在互联网企业中大量被使用。另外,MySQL 5.x企业版中官方提供的Fabric组件也号称支持分片技术,不过国内使用的企业较少。&
中间件也可以称为&透明网关&,大名鼎鼎的mysql_proxy大概是该领域的鼻祖(由MySQL官方提供,仅限于实现&读写分离&)。中间件一般实现了特定数据库的网络通信协议,模拟一个真实的数据库服务,屏蔽了后端真实的Server,应用程序通常直接连接中间件即可。而在执行SQL操作时,中间件会按照预先定义分片规则,对SQL语句进行解析、路由,并对结果集做二次计算再最终返回。引入数据库中间件的技术成本更低,对应用程序来讲侵入性几乎没有,可以满足大部分的业务。增加了额外的硬件投入和运维成本,同时,中间件自身也存在性能瓶颈和单点故障问题,需要能够保证中间件自身的高可用、可扩展。
总之,不管是使用分布式数据访问层还是数据库中间件,都会带来一定的成本和复杂度,也会有一定的性能影响。所以,还需读者根据实际情况和业务发展需要慎重考虑和选择。
丁浪,技术架构师。关注高并发、高可用的架构设计,对系统服务化、分库分表、性能调优等方面有深入研究和丰富实践经验。热衷于技术研究和分享。
感谢对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至。也欢迎大家通过新浪微博(,),微信(微信号:)关注我们。
Author Contacted
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
InfoQ每周精要
订阅InfoQ每周精要,加入拥有25万多名资深开发者的庞大技术社区。
架构 & 设计
文化 & 方法
<及所有内容,版权所有 &#169;
C4Media Inc.
服务器由 提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司
京ICP备号-7
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
我们发现您在使用ad blocker。
我们理解您使用ad blocker的初衷,但为了保证InfoQ能够继续以免费方式为您服务,我们需要您的支持。InfoQ绝不会在未经您许可的情况下将您的数据提供给第三方。我们仅将其用于向读者发送相关广告内容。请您将InfoQ添加至白名单,感谢您的理解与支持。数据存储演进思路一:单库单表
单库单表是最常见的数据库设计,例如,有一张用户(user)表放在数据库db中,所有的用户都可以在db库中的user表中查到。
数据存储演进思路二:单库多表
随着用户数量的增加,user表的数据量会越来越大,当数据量达到一定程度的时候对user表的查询会渐渐的变慢,从而影响整个DB的性能。如果使用mysql, 还有一个更严重的问题是,当需要添加一列的时候,mysql会锁表,期间所有的读写操作只能等待。
可以通过某种方式将user进行水平的切分,产生两个表结构完全一样的user_0000,user_0001等表,user_0000 &#43; user_0001 &#43; …的数据刚好是一份完整的数据。
数据存储演进思路三:多库多表
&随着数据量增加也许单台DB的存储空间不够,随着查询量的增加单台数据库服务器已经没办法支撑。这个时候可以再对数据库进行水平区分。
Mysql数据库分库分表规则
& & 设计表的时候需要确定此表按照什么样的规则进行分库分表。例如,当有新用户时,程序得确定将此用户信息添加到哪个表中;同理,当登录的时候我们得通过用户的账号找到数据库中对应的记录,所有的这些都需要按照某一规则进行。
& & 通过分库分表规则查找到对应的表和库的过程。如分库分表的规则是user_id mod 4的方式,当用户新注册了一个账号,账号id的123,我们可以通过id mod 4的方式确定此账号应该保存到User_0003表中。当用户123登录的时候,我们通过123 mod 4后确定记录在User_0003中。
下面是分库分表产生的问题,及注意事项
1.&& 分库分表维度的问题
假如用户购买了商品,需要将交易记录保存取来,如果按照用户的纬度分表,则每个用户的交易记录都保存在同一表中,所以很快很方便的查找到某用户的购买情况,但是某商品被购买的情况则很有可能分布在多张表中,查找起来比较麻烦。反之,按照商品维度分表,可以很方便的查找到此商品的购买情况,但要查找到买人的交易记录比较麻烦。
所以常见的解决方式有:
&&&& a.通过扫表的方式解决,此方法基本不可能,效率太低了。
&&&& b.记录两份数据,一份按照用户纬度分表,一份按照商品维度分表。
&&&& c.通过搜索引擎解决,但如果实时性要求很高,又得关系到实时搜索。
2.&& 联合查询的问题
联合查询基本不可能,因为关联的表有可能不在同一数据库中。
3.&& 避免跨库事务
避免在一个事务中修改db0中的表的时候同时修改db1中的表,一个是操作起来更复杂,效率也会有一定影响。
4.&& 尽量把同一组数据放到同一DB服务器上
例如将卖家a的商品和交易信息都放到db0中,当db1挂了的时候,卖家a相关的东西可以正常使用。也就是说避免数据库中的数据依赖另一数据库中的数据。
在实际的应用中,绝大部分情况都是读远大于写。Mysql提供了读写分离的机制,所有的写操作都必须对应到Master,读操作可以在Master和Slave机器上进行,Slave与Master的结构完全一样,一个Master可以有多个Slave,甚至Slave下还可以挂Slave,通过此方式可以有效的提高DB集群的QPS.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
此外,可以看出Master是集群的瓶颈,当写操作过多,会严重影响到Master的稳定性,如果Master挂掉,整个集群都将不能正常工作。
所以,1. 当读压力很大的时候,可以考虑添加Slave机器的分式解决,但是当Slave机器达到一定的数量就得考虑分库了。 2. 当写压力很大的时候,就必须得进行分库操作。
---------------------------------------------
MySQL使用为什么要分库分表?
可以用说用到MySQL的地方,只要数据量一大, 马上就会遇到一个问题,要分库分表.
这里引用一个问题为什么要分库分表呢?MySQL处理不了大的表吗?
其实是可以处理的大表的.我所经历的项目中单表物理上文件大小在80G多,单表记录数在5亿以上,而且这个表
属于一个非常核用的表:朋友关系表.
但这种方式可以说不是一个最佳方式. 因为面临文件系统如Ext3文件系统对大于大文件处理上也有许多问题.
这个层面可以用xfs文件系统进行替换.但MySQL单表太大后有一个问题是不好解决: 表结构调整相关的操作基
本不在可能.所以大项在使用中都会面监着分库分表的应用.
从Innodb本身来讲数据文件的Btree上只有两个锁, 叶子节点锁和子节点锁,可以想而知道,当发生页拆分或是添加
新叶时都会造成表里不能写入数据.
所以分库分表还就是一个比较好的选择了.
那么分库分表多少合适呢?
经测试在单表1000万条记录一下,写入读取性能是比较好的. 这样在留点buffer,那么单表全是数据字型的保持在
800万条记录以下, 有字符型的单表保持在500万以下.
如果按 100库100表来规划,如用户业务:
500万*100*100 = 万 = 5000亿记录.
心里有一个数了,按业务做规划还是比较容易的.
原文地址:91CTO
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:16934次
排名:千里之外
原创:34篇
转载:33篇
(3)(1)(2)(3)(1)(4)(32)(22)

我要回帖

更多关于 杠杆炒股什么意思 的文章

 

随机推荐