众所周知,数据库很容易成为应用系统的瓶颈。单机数据库的资源和处理能力有限,在高并发的分布式系统中,可采用分库分表突破单机局限。
本文总结了分库分表的相关概念、全局ID的生成策略、分片策略、平滑扩容方案及流行的方案。
一、分库分表概述
在业务量不大时,单库单表即可支撑。当数据量过大存储不下、或者并发量过大负荷不起时,就要考虑分库分表。
1、分库分表相关术语
①垂直分表:竖向切分,不同分表存储不同的字段,可以把不常用或者大容量、或者不同业务的字段拆分出去;
②水平分表(最复杂):横向切分,按照特定分片算法,不同分表存储不同的记录。
2、真的要采用分库分表?
需要注意的是,分库分表会为数据库维护和业务逻辑带来一系列复杂性和性能损耗,除非预估的业务量大到万不得已,切莫过度设计、过早优化。
规划期内的数据量和性能问题,尝试能否用下列方式解决:
如果仍未能奏效,才考虑最复杂的方案:数据表的水平切分。
二、全局ID生成策略
1、自动增长列
解决方案:
设置自增偏移和步长:
- ##假设总共有10个分表
- ##级别可选:SESSION(会话级),GLOBAL(全局)
- SET@@SESSION.auto_increment_offset=1;##起始值,分别取值为1~10
- SET@@SESSION.auto_increment_increment=10;##步长增量
如果采用该方案,在扩容时需要迁移已有数据至新的所属分片。
全局ID映射表:
在全局Redis中为每张数据表创建一个ID的键,记录该表当前***ID;每次申请ID时,都自增1并返回给应用;Redis要定期持久至全局数据库。
2、UUID(128位)
在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成UUID的API。
UUID由4个连字号(-)将32个字节长的字符串分隔后生成的字符串,总共36个字节长。形如:
- 550e8400-e29b-41d4-a716-446655440000。
UUID的计算因子包括:以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。UUID是个标准,其实现有几种,最常用的是微软的GUID(GlobalsUniqueIdentifiers)。
3、COMB(组合)
组合GUID(10字节)和时间(6字节),达到有序的效果,提高索引性能。
4、Snowflake(雪花)算法
Snowflake是Twitter开源的分布式ID生成算法,其结果为long(64bit)的数值。其特性是各节点无需协调、按时间大致有序、且整个集群各节点单不重复。
该数值的默认组成如下(符号位之外的三部分允许个性化调整):
三、分片策略
1、连续分片
根据特定字段(比如用户ID、订单时间)的范围,值在该区间的,划分到特定节点。
2、ID取模分片
3、一致性Hash算法
4、Snowflake分片
四、分库分表引入的问题
1、分布式事务
由于两阶段/三阶段提交对性能损耗大,可改用事务补偿机制。
2、跨节点JOIN
对于单库JOIN,MySQL原生就支持;对于多库,出于性能考虑,不建议使用MySQL自带的JOIN,可以用以下方案避免跨节点JOIN:
3、跨节点聚合
只能在应用程序端完成。但对于分页查询,每次大量聚合后再分页,性能欠佳。
4、节点扩容
节点扩容后,新的分片规则导致数据所属分片有变,因而需要迁移数据。
五、节点扩容方案
1、常规方案
如果增加的节点数和扩容操作没有规划,那么绝大部分数据所属的分片都有变化,需要在分片间迁移:
2、免迁移扩容
采用双倍扩容策略,避免数据迁移。扩容前每个节点的数据,有一半要迁移至一个新增节点中,对应关系比较简单。
具体操作如下(假设已有2个节点A/B,要双倍扩容至A/A2/B/B2这4个节点):
六、分库分表方案
1、代理层方式
部署一台代理服务器伪装成MySQL服务器,代理服务器负责与真实MySQL节点的对接,应用程序只和代理服务器对接。对应用程序是透明的。比如MyCAT,官网,源码。
2、应用层方式
处于业务层和JDBC层中间,是以JAR包方式提供给应用调用,对代码有侵入性。
主要方案有:
Sharding-JDBC定位为轻量Java框架,使用客户端直连数据库,无需额外部署,无其他依赖,DBA也无需改变原有的运维方式。Sharding-JDBC分片策略灵活,可支持等号、between、in等多维度分片,也可支持多分片键。
SQL解析功能完善,支持聚合、分组、排序、limit、or等查询,并支持BindingTable以及笛卡尔积表查询。
Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:
参考
:http://www.informit.com/articles/article.aspx?p=25862
https://github.com/twitter-archive/snowflake/tree/snowflake-2010
https://www.lanindex.com/twitter-snowflake%EF%BC%8C64%E4%BD%8D%E8%87%AA%E5%A2%9Eid%E7%AE%97%E6%B3%95%E8%AF%A6%E8%A7%A3/
一. 安装ElasticSearch 1. 下载window版本 https://www.elastic.co/cn/downloads...
复制代码 代码如下: html, address, blockquote, body, dd, div, dl, dt, fields...
一、数据库瓶颈 不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增...
首先插件配备好了,写一个HTML测试一下 首先创建一个文件夹,创建一个HTML 文件...
jquery是对javascript很好的封装,而且很轻量级,可以近似的将其称其为框架,下...
页面添加水印的方法有很多,以下举例使用class定义的方法进行水印内容渲染: 1、...
文章目录 引言 I、 判断是否插了耳机 引言 I、 判断是否插了耳机 /** 1. AudioTo...
这是asp分页列表生成静态页面得asp小程序脚本 复制代码 代码如下: !--#includefi...
一、实现效果 主要是IO和Sharedpreferences的数据持久化对于后者xml更为方便易实...
//js正则实现用户输入银行卡号的控制及格式化 script language="javascript" typ...