Sharding MySQL Databases across Different Physical Loca
作者:禅与计算机程序设计艺术
1.简介
MySQL是一个非常流行的关系型数据库管理系统(RDBMS),在当今的数据处理环境中扮演着越来越重要的角色。但是由于其依赖于磁盘存储,对于大规模数据量的处理仍然存在许多限制。为了解决这一问题,许多公司都开始探索基于云计算的分布式数据库产品,如谷歌的BigTable和Facebook的CockroachDB等。 无论是在性能、可用性还是成本方面,这些分布式数据库都有自己的优势。但同时也要考虑到分布式数据库的复杂性和部署问题。这篇文章将详细阐述分布式数据库分片(Sharding)在不同物理位置之间如何进行数据复制、负载均衡、故障转移和水平扩展等功能。
2.相关概念和术语
2.1 分布式数据库
分布式数据库系统可以简单地定义为多个不同的计算机系统上运行的相同或类似的数据库。分布式数据库具有以下特征:
- 数据分布在不同的机器上
- 每个节点都包含完整的数据副本
- 通过网络通信进行数据交换
一个典型的分布式数据库通常由多个服务器节点组成,每个节点都保存整个数据库的一部分。这种分布式结构允许数据库水平扩展,并提供可靠性和容错能力,即使其中一些节点出现故障也是如此。例如,如果主节点出现故障,则可以通过其他节点接管,数据库服务得以继续。另外,如果某些节点距离较远,那么通过网络传输数据的速度就会变慢。因此,对于大型数据库来说,分布式数据库是一种高效的解决方案。
2.2 分片
分片是指把单个数据库划分成多个子集,并将相关记录分配给这些子集,从而实现数据库的水平拆分。分片可以提升查询性能、节省磁盘空间、降低热点问题、增加吞吐量等优点。
2.2.1 水平分片
水平分片就是将数据库中的表根据业务规则或数据访问模式进行水平切分。一般情况下,水平分片都是采用哈希函数来对记录进行分配,不同的记录会被映射到相同的分片。因此,相同的数据可能被分配到不同的分片,这就导致了数据分布不均匀的问题。另一方面,由于同一个分片内的数据都是属于同一个业务逻辑的数据集合,因此可以使用标准SQL语句完成各种查询操作。
2.2.2 垂直分片
垂直分片就是按照功能模块,将一个大的表拆分成多个小的表,每个小的表只负责存储特定业务数据。这样做的好处是可以更快的读取指定的数据,并且更方便维护。同时,垂直分片可以有效防止大表数据膨胀,避免由于一次查询操作所带来的大量读写请求而造成数据库性能下降。
2.3 复制
复制是指在两个或多个服务器上保存相同的数据副本。当某个节点发生故障时,备份节点可以代替它承担起复制的任务,确保数据库的高可用性。
2.4 负载均衡
负载均衡是指将用户请求随机分配到各个节点上的数据库集群。它可以改善整体的处理能力,减少单个节点的压力,提高数据库的稳定性。
2.5 故障转移
故障转移是指当某个节点或者连接断开时,可以自动切换到另一个节点,保证服务的连续性。
2.6 容错恢复
容错恢复是指在发生硬件或软件故障时,仍然能够保持服务的正常运行,并自动重新选择失效的节点。
2.7 拓扑结构变化
拓扑结构变化是指当物理资源添加或删除的时候,需要调整分片的分布形式。
2.8 分片策略
分片策略是指确定如何划分数据库表以及如何分配数据到分片。最简单的方式是按照范围进行分片,将数据划分成多块,每块根据范围大小匹配到相应的分片。也可以根据业务相关性进行分片,将相关数据分配到相同的分片。
2.9 跨越分片查询
跨越分片查询意味着查询涉及到的表已经分布在不同分片上,因此需要查询路由器来决定应该从哪个分片获取数据。
3. 分布式数据库在不同的物理位置之间数据复制、负载均衡、故障转移和水平扩展等功能的原理和具体操作步骤以及数学公式讲解
本文将详细描述分布式数据库分片在不同物理位置之间进行数据复制、负载均衡、故障转移和水平扩展等功能的原理和具体操作步骤。首先,我们先介绍一下MySQL的默认设置。然后,分别介绍MySQL的基于GTID的复制和基于mydumper工具的增量备份方案,最后再讨论基于GTID的同步机制、数据库的分片策略等知识。
一、MySQL的默认配置
MySQL的安装包默认的配置文件my.ini文件如下:
[mysqld]# general settingsbasedir=/usr/local/mysqldatadir=/data/mysql_datasocket=/tmp/mysql.sockpid-file=/var/run/mysqld/mysqld.pidtmpdir=/tmp/mysqldlc-messages-dir=/usr/share/mysqlskip-external-locking #锁表key_buffer_size=16Mmax_allowed_packet=16Mthread_stack=192Kthread_cache_size=8query_cache_limit=1Mquery_cache_size=16Msort_buffer_size=4Mjoin_buffer_size=4Mread_rnd_buffer_size=4M# connection and thread handlingback_log=50max_connections=1000table_open_cache=1024thread_concurrency=10# mysql query cachelong_query_time=1slow_query_log=ONslow_query_log_file=/var/log/mysql/mysql-slow.log# log file settingslog_error=/var/log/mysql/error.loggeneral_log=OFF# binary logging optionsserver-id=1 #唯一IDlog-bin=/data/mysql_bin_logs/mysql-bin #日志文件expire_logs_days=10 #过期时间gtid_mode=ONenforce-gtid-consistency=ON #自动验证binlog_format=ROW #日志格式default-storage-engine=InnoDBcharacter-set-server=utf8mb4collation-server=utf8mb4_unicode_ciinit-connect='SET NAMES utf8mb4'
主要关注的是下面几个参数:
- server-id : 服务唯一标识符,在多主机环境中应设置为不同值
- binlog_format = ROW : 设置binlog的格式为ROW模式
- gtid_mode = ON : 支持GTID模式,保证在主从复制和备份恢复等场景下一致性和正确性
- enforce-gtid-consistency = ON : 在主从同步后,强制要求从库必须执行主库的完全事务,用于保证数据一致性和正确性
二、基于GTID的复制
2.1 复制过程
MySQL支持基于GTID的主从复制,这是一种通过在主库上生成全局事务ID (GTID) 来标识事务的机制。从库接收主库发送的GTID,并应用对应的事务。
图1 MySQL复制的流程图
2.2 主库生成全局事务ID
在MySQL5.6版本之前,仅支持基于语句的复制。在这种方式下,主库并不会在事务提交时更新对应的GTID。因此,如果主库的binlog_format为STATEMENT或MIXED类型,主库在提交事务时会忽略对应GTID信息。为了解决这个问题,MySQL5.6引入了新的日志格式ROW。在ROW日志格式下,主库在事务提交时都会写入GTID信息。
通过SHOW MASTER STATUS命令可以查看当前正在执行的事务的GTID。例如:
SHOW MASTER STATUS;+------------------+----------+--------------+------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |+------------------+----------+--------------+------------------+| mysql-bin.000004 | 93 | test | |+------------------+----------+--------------+------------------+1 row in set (0.00 sec)
2.3 从库使用全局事务ID初始化
从库启动时,会连接到主库,并向主库发送以下命令,请求从主库拉取数据:
CHANGE MASTER TO MASTER_HOST='localhost',MASTER_PORT=3306,MASTER_USER='repl',MASTER_PASSWORD='password';START SLAVE;
在主库成功生成并发送GTID之后,从库便会接收到GTID,并尝试从主库拉取事务数据。若从库也启用了GTID协议,并且接收到的GTID能找到对应的事务,则从库会应用该事务。否则,等待下一个事务的GTID信息。
2.4 GTID的作用
- 可以保证主从复制的一致性;
- 可以快速定位出错的事务位置;
- 可以实现在线事务的回滚操作;
- 可以配合binlog_rollback_on_warning参数使用,实现半自动容灾操作。
三、基于mydumper工具的增量备份方案
3.1 mydumper介绍
MyDumper是一个开源的数据库备份工具,可以用来快速生成全库或者部分库的备份。其核心思想是通过扫描表结构和数据文件的元信息,逐行解析数据,生成INSERT INTO... SELECT语句,写入临时文件中,再合并生成最终的文件。因此,MyDumper不需要连接数据库,在很短的时间内就可以完成备份工作。
MyDumper支持多线程备份,可以同时备份多个库,并且支持快照备份,可以生成一个完整的库的备份。而且MyDumper还可以在备份过程中实时显示进度条,查看备份进度。
3.2 MyDumper配置
MyDumper的配置选项很多,这里仅列举几个重要的配置项:
- threads:设置线程数量,默认为4。
- chunk-size:设置每次处理的数据量,默认为1GB,一般设为较大的数量以避免生成过大的临时文件。
- where:设置过滤条件,MyDumper会根据过滤条件查询待备份表,只有符合条件的记录才会被备份。
- no-views:是否备份视图。
- no-triggers:是否备份触发器。
- skip-tz-utc:是否跳过TIME_ZONE='+00:00'参数。
- complete-insert:是否使用complete insert语法。
3.3 MyDumper流程
MyDumper的备份流程包括三个步骤:
- 检查备份目录是否存在。
- 生成备份表的元信息。
- 根据指定的chunk size,逐步读取表的数据,并生成INSERT INTO... SELECT语句,写入临时文件。
四、基于GTID的同步机制
4.1 概念
主从复制需要两台机器,一个是主库,另一个是从库。从库通过从主库接收二进制日志事件,并在本地执行,达到和主库一样的状态。
为了保证主从库的数据一致性,MySQL提供了两种复制方式:
- statement:主库记录的是执行的具体的SQL语句,从库按语句顺序执行;
- row:主库记录的是每一条修改数据的SQL语句,从库直接读取并执行。
在MySQL 5.6版本之后,提供了更加完美的解决方案——基于GTID的复制。
4.2 操作步骤
配置主从库之间的复制;
1> CHANGE MASTER TO master_host="10.0.0.1", master_port=3306, master_user="root", master_password="", master_auto_position=1;2> START SLAVE;
参数说明:
- master_host:主库地址;
- master_port:主库端口;
- master_user:认证用户名;
- master_password:密码;
- master_auto_position:从库是否开启GTID协议,开启的话从库会根据Master发送的GTID日志来驱动复制进度。
查看状态信息;
SHOW SLAVE STATUS\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: localhost Master_User: repl Slave_UUID: b62e4ba8-1e9f-11ea-b33d-0242ac110002 Relay_Log_File: mysql-relay-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replication_Lag: NULL Seconds_Behind_Master: 2
参数说明:
- Slave_IO_State:从库当前执行的状态;
- Master_Host:主库的IP地址;
- Master_User:认证用户名;
- Slave_UUID:从库UUID;
- Relay_Log_File:从库中继日志文件;
- Slave_IO_Running:从库中继日志是否运行中;
- Slave_SQL_Running:从库SQL线程是否运行中;
- Replication_Lag:从库复制延迟;
- Seconds_Behind_Master:从库复制延迟秒数。
停止从库复制并做检查;
STOP SLAVE;FLUSH TABLES WITH READ LOCK; -- 锁住所有表CHECK TABLE tbl_name [FOR UPGRADE]; -- 检查表是否损坏,可选升级模式UNLOCK TABLES; -- 解锁表START SLAVE; -- 重启复制
处理冲突 如果因为主从库延迟引起的复制延迟超过一定值,会报错“Slave SQL thread is stopped due to administrator command”:
ERROR 1193 (HY000): Slave SQL thread is stopped due to administrator command
此时,我们需要重新配置主从库的复制,将delay的值调大一些:
CHANGE MASTER TO master_host="10.0.0.1", master_port=3306, master_user="root", master_password="", master_auto_position=1, master_log_file='mysql-bin.000001',master_log_pos=2393, delay=1000000;START SLAVE;
参数说明:
- master_log_file:指定从哪个日志文件开始复制;
- master_log_pos:指定从日志文件偏移量开始复制;
- delay:延迟秒数。
执行增量备份 创建dump目录,将mysql-bin.*日志文件复制到dump目录,并使用mydumper工具增量备份。
五、数据库的分片策略
5.1 概念
当数据库数据量超过单机数据库的处理能力时,可以通过分片的方式,将数据库分布到多台服务器上去处理。主要原因如下:
- 数据量太大,单机数据库处理不过来;
- 大多数情况下,数据访问的热点并不是集中在所有的服务器上,而是局部区域;
- 有些时候,某些业务访问特别多,单机数据库无法满足需求。
5.2 分片原则
- 数据按照业务规则分片,而不是按照数据库切分。
- 为每个分片分配独立的资源,尽量避免资源竞争。
- 使用软分区的方式,实现动态分片,提升数据库可用性。
- 提供良好的分片管理功能,监控分片状态。
- 测试分片功能,保证功能的完整性。
5.3 数据库分片方案
5.3.1 垂直分片
垂直分片是按照业务模块,将一个大表拆分成多个小的表,每个小的表只负责存储特定业务数据。通过垂直分片,可以优化数据库的查询性能,减少锁竞争,提升数据库整体性能。
图2 垂直分片示意图
5.3.2 水平分片
水平分片又称为分库分表,是指把一个数据库中的表根据业务规则或数据访问模式进行水平切分。一般情况下,水平分片都是采用哈希函数来对记录进行分配,不同的记录会被映射到相同的分片。因此,相同的数据可能被分配到不同的分片,这就导致了数据分布不均匀的问题。另一方面,由于同一个分片内的数据都是属于同一个业务逻辑的数据集合,因此可以使用标准SQL语句完成各种查询操作。
图3 水平分片示意图
5.3.2.1 分库
当数据库的单表数据量过大时,可以通过分库的方法,将表分布到不同的数据库服务器上去。通过将一个数据库分散到多个数据库服务器上,可以有效缓解单库的压力。当然,分库对数据的隔离性也有一定的影响。
5.3.2.2 分表
当数据库的单表数据量过大时,可以通过分表的方法,将一个大表拆分成多个小的表。通过将表分布到不同的数据库服务器上,可以有效缓解单表的压力。除此之外,还可以通过索引来加速查询操作。
5.3.3 混合分片
当数据库需要同时支持垂直分片和水平分片时,可以通过混合分片的方式,将垂直分片和水平分片结合起来。通过这种方法,既可以实现垂直分片和水平分片的效果,又可以避免单点故障。
来源地址:https://blog.csdn.net/universsky2015/article/details/132825126
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341