mysql分片
Posted 把书读薄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql分片相关的知识,希望对你有一定的参考价值。
mysql向外扩展(横向扩展或者水平扩展)策略主要有三方面:复制、拆分、数据分片;
水平扩展的最简单的方式就是通过复制将数据分发到多个服务器上,然后将备库用于读查询。复制技术用于以读为主的服务效果最好;但是当数据规模比较大时,复制也有一些问题,例如主从同步间隔时间过长。
数据拆分以及分配方式:
1、按功能拆分
按功能拆分或者职责拆分,就是不同的服务节点执行不同的任务,将独立的服务器或者节点分配给不同的应用,这样每个节点只包含它的特定应用所需的数据。
缺点:如果一个功能区域的数据绑定到单个mysql节点,后续就只能对单个节点进行垂直扩展(扩展硬件类似的方式)。
2、数据分片
对于目前的扩展大型Mysql应用来说,数据分片是最通用且成功的方法,它把数据分割为一个小片或者一块,然后存储到不同的节点上。
数据分片与按照功能划分联合使用时非常有用。大多数分片系统也有一些“全局的”数据不会进行划分(城市列表或者登陆数据等)。全局数据一般存储到单个节点上,并且会保存在NoSql类的内存数据库中以便加速访问。
数据分片一般会对数据增长的非常庞大的数据进行分片。
大多数应用可能存在多个不同的逻辑数据集,并且数据集的处理方式也会不同,可以将不同的数据集存储到不同服务器组上,然后以多种方式就行分片。
可以通过用户Id对数据进行分片。
采用数据分片的应用通常会有一个数据库访问抽象层,用以降低应用与数据库之间的通讯复杂度。
3、选择分区键
数据分片的最大挑战是查找和获取数据:如何查询数据取决于如何进行分片;
分片的目标是针对于那些最重要并且频繁查询的数据减少分片,因为需要避免多个节点之间的交互。
跨多个分片的查询比单个分片的查询性能要差,但是只要不涉及到过多的分片性能不会差太多。
一个好的分区键通常是数据库中一个非常重要的实体主键,例如用于Id或者客户端ID等。
确定分区键的一个比较好的办法是用实体-关系图,看是否可以根据分区键拆分出耦合关系简单的实体-关系图。
选择分区键时尽量避免那些会进行跨分区查询的,但是也要让分片足够小,以避免过大的数据分片导致的问题。分区键要选择可以把数据平均分片到各个分区的键。
4、多个分区键
复杂的数据模型会使数据分片更加复杂。
例如博客应用的数据按照用户ID和文章ID进行分片,因为使用两者查询数据比较平常,针对这种情况建议把用户ID和文章ID一起分片到一个分片中,避免跨分片查询。
5、跨分片查询
大多数应用或多或少会有一些跨分片查询的情况,例如对数据的进行聚合或者关联操作。
跨分片查询可以利用汇总表来执行,可以遍历所有分片来生成汇总表并将结果在每个分片上进行冗余;如果每个分片都冗余汇总表太过浪费,可以把汇总表放到一个单独的数据存储中,这样就只需要一份存储了。
跨分片查询并不是数据分片面临的唯一问题,维护数据一致性同样困难,外键无法在分片间工作,因此需要有应用来检查参考一致性,或者只在分片内使用外键,因为分片的内部一致性可能会很重要。
6、分配数据、分片与节点
分片与节点并不一定要一对一对应,最好是一个节点下存储多个分片;
保持的分片足够小更容易管理,这会是数据的备份和恢复更容易;如果表很小,那么像更改表结构这样的操作会更加容易;
小一点的分片也便于转移,这有助于重新分配容量,平衡各个节点的分片,转移分片的效率一般都不高。通常需要将受影响的分片设置为只读模式,提取数据,然后转移到另一个节点。
7、在节点上部署分片
一般的分为以下几种方式:
- 每个分片使用单一数据库,并且数据库名要相同;这种方式在部署多个应用实例,并且每个应用实例对应一个分片时很有用;
- 将多个分片的表放在一个数据库中,在每个表名上包含分片号,例如:db.book_0023、db.user_0023;这种配置下,单个数据库可以支持多个数据分片;
- 为每个分片使用一个数据库,并在数据库中包含所有应用需要的表。在数据库名中包含分片号,例如:db0023.book、db0023.user;当应用链接到单个数据库并且不再查询中指定数据库名时,这种做法很常见,其优点就是无须为每个分片专门编写查询,也便于对只使用单个数据库的应用进行分片;
- 每个分片使用一个数据库,并在数据库名和表名中包含分片名,例如:db0023.book_0023;
- 在每个节点上运行多个Mysql实例,每个实例上有一个或者多个分片,可以使用上面提到的方式的任意组合来安排分片;
为已有应用增加分片支持的结果往往是一个节点对应一个分片,这种简化的设计可以减少对应用查询的修改。
8、固定分配
将数据分配到分片中由两种主要的方式:固定分配与动态分配;两种方式都需要一个分区函数,使用行的分区键做为输入,返回存储该行的分片;
固定分配使用的分区函数仅仅依赖于分区键的值;哈希函数或者取模运算就是很好的例子;优点是简单、开销低、甚至可以在应用中直接硬编码;
固定分配的缺点:
- 如果分片很大并且数量不多,就很难平衡不同分片的负载;
- 固定分配的方式无法自定义数据放到哪个分片上;
- 修改分片策略通常比较困难,因为需要重新分配已有的数据;
正是由于以上的缺点,我们尽可能选择动态分配的方式;
9、动态分配
使用动态分配可以将每个数据单元映射到一个分片上;
动态分配增加了分区函数的开销,因为需要额外调用一次外部资源,例如目录服务器(存储映射关系的数据存储节点)。
动态分配的最大好处是可以对数据存储位置做细粒度的控制;这使得均衡分配数据到分片更容易,并且提供适应未知改变的灵活性;
动态映射可以在简单的键-分片映射的基础上建立多层次的分片策略;
使用动态分配策略可以生成不均衡的分片,对于不同服务器处理能力的不同,可以定制分配分片数据的大小;
动态分配有助于减轻规模扩大而带来的跨分片查询问题,例如当一个跨分片查询需要跨4个节点时,如果使用固定分配时,任何给定的查询可能需要访问所有分片,但动态分配策略则可能只需要在问其中三个节点上运行同样的查询,当节点规模从4个增长到400个时,动态分配策略的优势就体现出来了,使用动态分配策略依然只访问3个,而固定分配则需要访问所有的节点;
10、混合动态分配与固定分配
可以混合使用动态分配和固定分配。
11、显示分配
第三种策略是在应用插入新的数据时显示的选择目标分片。这种策略在已有的数据上很难做到,所有在为应用增加分片时很少使用,但在某些情况下会很有用;
显示分配的确定是分片方式固定,很难做到分片间的负载均衡;
12、重新均衡分片数据
可以通过分片间移动数据来实现负载均衡。
重新均衡分片数据会影响用户使用,因此应该避免此操作;
一个比较好的方式是使用动态分配策略,并将新数据随机分配到分片中,当一个分片快满时,可以设置一个标志位,告诉应用不要在往里放数据了。
13、生成全局唯一ID
当希望一个现有系统转换为分片数据存储时,经常会需要在多台机器上生成全局唯一主键ID;单一机器使用AUTO_INCREMENT列来获取唯一ID,但是涉及到多台机器时就不奏效了,有以下几种方式生成全局唯一主键ID:
- 使用auto_increment_increment与auto_increment_offset这两个服务器变量可以让mysql以期望的值和偏移量来增加AUTO_INCREMENT列的值,例如,有两台服务,可以配置两台服务器的自增量为2,其中一台服务器的偏移量为1,另一台服务器的偏移量为2,这样一台服务器的ID为偶数,另一台服务器的ID为奇数;
- 全局节点中创建表,在一个全局数据库节点中创建一个包含AUTO_INCREMENT列的表,应用可以通过这个表来生成唯一数字;
- 使用NoSql中自动的递增函数,例如memcache或者redis的自动函数;
- 批量分配数字,应用可以从一个全局节点请求一批数字,用完再申请;
- 使用复合值,可以通过一个复合值来做唯一ID,例如分片号+自增数的组合;
- 使用GUID
以上是关于mysql分片的主要内容,如果未能解决你的问题,请参考以下文章