高性能MySql学习笔记-第十一章:可拓展的MySQL
1. 什么是可拓展性
- 可拓展性表明当需要增加资源以执行更多工作时系统能够获得划算的等同提升的能力。缺乏扩展能力的系统在达到收益递减的转折点后,将无法进一步增长。通俗来讲,就是增加资源来提升容量的能力。
- 多数系统最终会达到一个最大吞吐量临界点,超过这个点之后增加投入反而会带来负回报 —— 继续增加更多的工作负载,实际上会降低系统的吞吐量。
- 通用可拓展性定理(Universal Scalability Law,USL)描述拓展的偏差受两个因素的影响:无法并行执行的一部分工作、内部节点间或进程间的通信。
2. 拓展MySQL
- 在决定MySQL扩展前,应当尽量先采取优化性能、购买更强性能的硬件等方式获得拓展性,直到达到收益递减点。
- 向上扩展(垂直扩展)的复杂性比向外扩展简单得多。但是如果系统确实有可预见的向上拓展的天花板,就不要无限制地做向上拓展的规划。
向外拓展
-
向外拓展(横向拓展或水平拓展)策略分为三个部分:复制、拆分、以及数据分片。
-
按功能拆分
- 按功能拆分是将独立的服务器或节点分配给不同的应用,这样每个节点只包含它的特定应用所需要的数据。
- 单个应用只能进行垂直拓展,如果单个应用增长非常庞大,仍需采取其他的策略。
-
数据分片
- 目前用于拓展大型MySQL应用的方案中,数据分片是最通用且最成功的方法。它将数据分割成一小片,存储到不同的节点中。
- 如果想拓展写容量,就必须切分数据。如果只有单台主库,那不管有多少备库,写容量都是无法拓展的。
- 如非必要,尽量不分片。但是对于单台服务器而言,数据大小或者写负载变得太大时,分片将是不可避免的。
-
选择分区键(partitioning key)
- 一个好的分区键常常是数据库中一个非常重要的实体的主键。这些键值决定了分片单元。
-
跨分片查询
- 跨分片查询对于应用而言是一条查询,每条查询都会在分片上并行执行。一个设计良好的数据库抽象层能够减轻这个问题。
- 跨分片查询在维护数据一致性上也有一定困难。外键无法在分片间工作,因此需要应用来检查参照一致性,或者只在分片内使用外键。还可以使用XA事务,由于开销太大,现实中使用很少。
-
分配数据、分片和节点
- 应该尽可能地让分片的大小比节点容量小很多,这样就可以在单个节点上存储多个分片。保持分片足够小更容易管理。这使得数据的备份和恢复更加容易。
-
在节点上部署分片
- 倾向于使用每个分片一个数据库的方式,并把分片号写到数据库名和表名中。
-
固定分配
- 固定分配使用的分区函数仅仅依赖分区键的值。如哈希函数和取模运算等。
- 固定分配的主要优点是简单,开销低,甚至可以在应用中直接硬编码。
- 固定分配有一些缺点。比如很难平衡不同分片间的负载、修改分片策略比较困难,因为需要重新分配已有数据。
-
动态分配
- 动态分配增加了分区函数的开销,因为需要额外调用一次外部资源。
- 动态分配的最大好处是可以对数据存储位置做细粒度的控制。这使得均衡分配数据到分片更加容易,并提供一些灵活性。
-
生成全局唯一ID
- 单一数据存储时通常可以使用
AUTO_INCREMENT
列来获取唯一ID。但涉及多台服务器时就不奏效了。有以下一些解决方式: - 使用
auto_increment_increment
和auto_increment_offset
参数控制不同的服务器的自增ID相区别。 - 使用全局分配器来产生唯一ID,但是要注意单点问题。
- 使用UUID()函数生成全局唯一值,但是UUID值不连续,不适合做InnoDB表的主键。
- 单一数据存储时通常可以使用
-
分片工具
- 如果没有任何抽象层,直接让用户访问多个数据源,会大量增加复杂性。最好是将数据源隐藏在抽象层中。这个抽象层主要完成以下任务:
- 连接到正确的分片并执行查询。
- 分布式一致性校验。
- 跨分片的结果集聚合
- 跨分片关联操作
- 锁和事务管理
- 创建新的数据分片并重新平衡分片
- 如果没有任何抽象层,直接让用户访问多个数据源,会大量增加复杂性。最好是将数据源隐藏在抽象层中。这个抽象层主要完成以下任务:
向内拓展
-
处理不断增长的数据和负载最简单的办法是对不再需要的数据进行归档和清晰。设计规定和清理时需要考虑如下几点:
- 对应用的影响。归档系统应该在不影响事务处理的情况下,从一个高负载的OLTP服务器上移除数据。
- 要归档的行。需要清楚了解哪些数据是需要归档的。
- 维护数据一致性。归档系统需要能够保证数据的逻辑一致性。
- 避免数据丢失。
- 解除归档。
-
即使并不真的把老数据转移到别的服务器,许多应用也能收益于活跃数据和非活跃数据的隔离。这有助于高效利用缓存。
3. 负载均衡
- 负载均衡的目的
- 可拓展性。
- 高效性。负载均衡可以更高效地使用资源,因为他可以控制将更多的工作分配给性能更好的服务器。
- 可用性。灵活的负载均衡策略可以时刻保持可用的服务器。
- 透明性。客户端无需关心是否存在负载均衡设置,也无需关系负载均衡后的服务器。
- 一致性。如果应用是有状态的,那么负载均衡器经应该将相关的查询指向同一个服务器,以防止状态丢失。
直接连接
- 直接连接也可以达到负载均衡的一些目的:比如通过复制上的读写分离、修改应用配置、修改DNS名、转移IP地址等。
引入中间件
- 许多负载均衡方案都会引入一个中间件,作为网络通信的代理。它一边接受所有的通信请求,另一边将这些请求派发到指定的服务器上,然后把执行结果发送回请求的机器上。
- 复制均衡算法一般有:随机、轮询、分配最少连接数、分配最快响应、哈希、权重等。
- 在新增服务器时,应当注意“冷启动”对用户请求的影响。