课程内容:
1、MySQL高可用集群原理
2、动手搭建MySQL主从集群
3、异步复制与半同步复制
4、MySQL其他高可用方案介绍
5、理解分库分表与主从集群
随着现在互联网的应用越来越大,数据库会频繁的成为整个应用的性能瓶颈。我们经常使用的MySQL数据库,也会不断面临数据量太大、数据访问太频繁、数据读写速度太快等一系2iP在增加MQ进行流量削峰等等。但定,o数据库,例如添加Redis缓存,增加MQ进行流量削峰等等。但是,数据库本身如果不能得到提升,这就相当于是水桶理论中的最短板。
而要提升数据库的性能,一种思路,当然是对数据库本身进行优化,例如对MySQL进行优化配置,或者干脆换成ClickHouse这一类的针对大数据的产品。另一方面就是跟微服务架构的思路一样,从单体架构升级到集群架构,这样才能真正全方位解放数据库的性能瓶颈。而我们后续要学习的分库分表就是一种非常常见的数据库集群架构管理方案。
但是就像微服务架构并不是简单的将服务从单机升级为就能一样,分库分表也并不只是字面意义上的将数据分到多个库或者多个表这么简单,他也是基于数据库产品的一系列分布式解决方案。在不同的应用场景下,针对不同的数据库产品,分库分表也有不同的落地方式。而我们后续,会以最为常见的MySQL数据库以及ShardingSphere框架来了解分库分表要如何进行。
既然要解决MySQL数据库的分布式集群化问题,那就不能不先了解MySQL自身提供的主从同步原理。这是构建MySQL集群的基础,也是后续进行分库分表的基础,更是MySQL进行生产环境部署的基础。
其实数据库的主从同步,就是为了要保证多个数据库之间的数据保持一致。最简单的方式就是使用数据库的导入导出工具,定时将主库的数据导出,再导入到从库当中。这是一种很常见,也很简单易行的数据库集群方式。也有很多的工具帮助我们来做这些事情。但是这种方式进行数据同步的实时性比较差。
而如果要保证数据能够实时同步,对于MySQL,通常就要用到他自身提供的一套通过 Binlog日志在多个MySQL服务之间进行同步的集群方案。基于这种集群方案,一方面可以提高数据的安全性,另外也可以以此为基础,提供读写分离、故障转移等其他高级的功能。
即在主库上打开Binlog日志,记录对数据的每一步操作。然后在从库上打开RelayLog日志,用来记录跟主库一样的Binlog日志,并将RelayLog中的操作日志在自己数据库中进行重演。这样就能够更加实时的保证主库与从库的数据一致。
MysQL的Binlog默认是不打开的。
他的实现过程是在从库上启动一系列IO线程,负责与主库建立TCP连接,请求主库在写入Binlog日志时,也往从库传输一份。这时,主库上会有一个IO Dump线程,负责将Binlog日志通过这些TCP连接传输给从库的IO线程。而从库为了保证日志接收的稳定性,并不会立即重演Binlog数据操作,而是先将接收到的Binlog日志写入到自己的RelayLog日志当中。然后再异步的重演RelayLog中的数据操作。
MySQL的BinLog日志能够比较实时的记录主库上的所有日志操作,因此他也被很多其他工具用来实时监控MySQL的数据变化。例如Canal框架,可以模拟一个slave节点,同步MySQL的Binlog,然后将具体的数据操作按照定制的逻辑进行转发。例如转发到Redis实现缓存一致,转发到Kafka实现数据实时流转等。而ClickHouse也支持将自己模拟成一个MySQL的从节点,接收MySQL的Binlog日志,实时同步MySQL的数据。这个功能目前还在实验阶段。
以下实验准备两台服务器,来搭建一个MySQL的主从集群均安装CentOS7操作系统。192.168.232.128将作为MySQL主节点,192.168.232.129将作为MySQL的从节点。
然后在两台服务器上均安装MySQL服务,MySQL版本采用mysql-8.0.20版本。
这里强调下,我们下面的示例是带大家在Linux上搭建MySQL服务。但是在Linux上安装MySQL经常会遇到各种各件的环境问题,这些环境问题大都只能通过百度加经验的方式来解决。大家根据自己的实际情况,如果在Linux上搭建MySQL有困难的话,可以改为用Windows来安装MySQL。Windows上安装MySQL会简单很多,并且也不影响我们后续ShardingSphere的学习。
MySQL的安装有很多种方式,具体可以参考官网手册: https://dev.mysql.com/doc/refman/8.0/en/binary-installation.html
我们这里采用对系统环境依赖最低,出问题的可能性最小的tar包方式来安装。
上传mysql压缩包到worker2机器的root用户工作目录/root下,然后按照下面的指令,解压安装mysql
groupadd mysql
useradd -r -g mysql -s /bin/false mysql #这里是创建一个mysql用户用于承载mysql服务,但是不需要登陆权限
tar -xvf mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz #解压
ln -s mysql-8.0.20-linux-glibc2.12-x86_64 mysql #建立软链接
cd mysql
mkdir mysql-files
chown mysql:mysql mysql-files
chmod 750 mysql-files
bin/mysqld --initialize --user=mysql #初始化mysql数据库文件 注意点1
bin/mysql_ssl_rsa_setup
bin/mysqld_safe --user=mysql
# Next command is optional
cp support-files/mysql.server /etc/init.d/mysql.server
注意点:
1、初始化过程中会初始化一些mysql的数据文件,经常会出现一些文件或者文件夹权限不足的问题。如果有文件权限不足的问题,需要根据他的报错信息,创建对应的文件或者文件夹,并配置对应的文件权限
2、初始化过程如果正常完成,日志中会打印出一个root用户的默认密码。这个密码需要记录下来。
2023-06-30T01:58:51.261843Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: -l?ii&wgo3-F
bin/mysqld --user=mysql
注意点:
1、这个启动过程会独占当前命令行窗口,如果要后台执行可以在后面添加一个&。但是一般第一次启动mysql服务时,经常会出现一些错误,所以建议用独占窗口的模式跟踪下日志。
Linux上安装软件经常会出现各种各样的环境问题,很难全部概括大部分的问题,需要查百度,根据别人的经验来修改。如果安装有困难的同学,可以改为在Windows上安MySQL,整个过程会简单很多不会影响后续ShardingSpehre的学习。
MySQL服务启动完成后,默认是只能从本机登录,远程是无法访问的。所以需要用root用户登录下,配置远程访问的权限。
cd /root/mysql
bin/mysql -uroot -p #然后用之前记录的默认密码登录
注意点:
1、如果遇到ERROR 2002 (HY000): Can’t connect to localMySQL server through socket ‘/tmp/mysql.sock’(2)这个报错信息,可以参照下面的配置,修改下/etc/my.cnf配置文件,来配置下sock连接文件的地址。主要是下面client部分。
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assortedsecurity risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.#If you need to run mysqld under a different user or group,
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
# include all files from the config directory#
!includedir /etc/my.cnf.d
[client]
port=3306
socket=/var/lib/mysql/mysql.sock
登录进去后,需要配置远程登录权限:
alter user 'root'@'localhost' identified by '123456'; #修改root用户的密码
use mysql;
update user set host='%' where user='root';
flush privileges;
这样,Linux机器上的MySQL服务就搭建完成了。可以使用navicat等连接工具远程访问MySQL服务了。
然后如果有同学安装MySQL确实有问题的话,推荐大家可以使用宝塔面板。https://www.bt.cn/。使用这个工具可以图形化安装以及管理MySQL,非常方便。
另外,对于熟悉Docker和K8s的同学,可以用这些虚拟化的方式来搭建,也非常简单高效。
这里需要注意下的是,搭建主从集群的多个服务,有两个必要的条件。
1、MySQL版本必须一致。
2、集群中哥哥服务器的时间需要同步
接下来在这两个MySQL服务基础上,搭建一个主从集群。
首先,配置主节点的mysql配置文件:/etc/my.cnf(没有的话就手动创建一个)
这一步需要对master进行配置,主要是需要打开binlog日志以及指定severld。我们打开MySQL主服务的my.cnf文件,在文件中一行server-id以及一个关闭域名解析的配置。然后重启服务。
[mysqld]
server-id=47
#开启binlog
log_bin=master-bin
log_bin-index=master-bin.index
skip-name-resolve
#设置连接端口
port=3306
#设置mysql的安装目录
basedir=/usr/local/mysql
#设置mysql数据库的数据的存放目录
datadir=/usr/local/mysql/mysql-files
#允许最大连接数
max_connections=200
#允许连接失败的次数。
max_connect_errors=10
#服务端使用的字符集默认为UTF8
character-set-server=utf8
#创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
#默认使用"mysql_native_password"插件认证
#mysql_native_password
default_authentication_plugin=mysql_native_password
配置说明:主要需要修改的是以下几个属性:
server-id:服务节点的唯一标识。需要给集群中的每个服务分配一个单独的ID。
log_bin:打开Binlog日志记录,并指定文件名。
log_bin-index: Binlog日志文件
重启MySQL服务,service mysqld restart
然后,我们需要给root用户分配一个replication slave的权限。
#登录主数据库
mysql -u root -p
GRANT REPLICATION SLAVE ON *.* TO 'root'@'%';
flush privileges;
#查看主节点同步状态:
show master status;
在实际生产环境中,通常不会直接使用root用户,而会创建一个拥有全部权限的用户来负责主从同步。
这个指令集中的File和Position记录的是当前日志的binlog文件以及文件中的索引。
而后面的Binlog_Do_DB和Binlog_lgnore_DB这两个字段是表示需要记录binlog文件的库以及不需要记录binlog文件的库。目前我们没有进行配置,就表示是针对全库记录日志。这两个字段如何进行配置,会在后面进行介绍。
开启binlog后,数据库中的所有操作都会被记录到datadir当中,以一组轮询文件的方式循环记录。而指令查到的File和Position就是当前日志的文件和位置。而在后面配置从服务时,就需要通过这个File和Position通知从服务从哪个地方开始记录binLog。
[mysqld]
#主库和从库需要不一致
server-id=48
#打开MySQ工中继日志
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin
#打开从服务二进制日志
log-bin=mysql-bin
#使得更新的数据写进二进制日志中
log-slave-updates=1
#设置3306端口
port=3306
#设置mysql的安装目录
basedir=/usr/local/mysql
#设置mysql数据库的数据的存放目苹
datadir=/usr/local/mysql/mysql-files
#允许最大连接数
max_connections=200
#允许连接失败的次数。
max_connect_errors=10
#服务端使用的字符集默认为UTF8
character-set-server=utf8
#创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
#默认使用"mysql_native _password"插件认证
#mysql_native _password
default_authentication _plugin=mysql_native_password
配置说明: 主要需要关注的几个属性:
server-id: 服务节点的唯一标识
relay-log: 打开从服务的relay-log日志。
log-bin: 打开从服务的bin-log日志记录。
然后我们启动mysqls的服务,并设置他的主节点同步状态。
下一步,我们来配置从服务mysqls。我们打开mysqls的配置文件my.cnf,修改配置文件:
#登录从服务
mysql -u root -p;
#设置同步主节点:
CHANGE MASTER TO
MASTER_HOST='192.168.232.128',
MASTER_PORT=3306,
MASTER_USER='root',
MASTER_PASSwORD='root',
MASTER_LOG_FILE='master-bin.000004',
MASTER_LOG_POS=156,
GET_MASTER_PUBLIC_KEY=1;
#开启slave
start slave;
#查看主从同步状态
show slave status;
或者用show slave status \G;这样查看比较简洁
注意,CHANGE MASTER指令中需要指定的MASTER_LOG_FILE和MASTER_LOG_POS必须与主服务中查到的保持一致。
并且后续如果要检查主从架构是否成功,也可以通过检查主服务与从服务之间的File和Position这两个属性是否一致来确定。
测试时,我们先用showdatabases,查看下两个MySQL服务中的数据库情况
然后我们在主服务器上创建一个数据库
mysql> create database syncdemo;
Query OK,1 row affected (0.00 sec)
然后我们再用show databases,来看下这个syncdemo的数据库是不是已经同步到了从服务。
接下来我们继续在syncdemo这个数据库中创建一个表,并插入条数据。
mysql> use syncdemo;
Database changed
mysql> create table demoTable(id int not nul1);
Query OK,0 rows affected (0.02 sec)
mysql> insert into demoTable value(l);
Query OK,1 row affected (0.01 sec)
然后我们也同样到主服务与从服务上都来查一下这个demoTable是否同步到了从服务。
MMM(Master-Master replication managerfor Mysql,Mysql主主复制管理器)是一套由Perl语言实现的脚本程序,可以对mysql集群进行监控和故障迁移。他需要两个Master,同一时间只有一个Master对外提供服务可以说是主备模式。
他是通过一个VIP(虚拟IP)的机制来保证集群的高可用。整个集群中,在主节点上会通过一个VIP地址来提供数据读写服务,而当出现故障时VIP就会从原来的主节点漂移到其他节点,由其他节点提供服务。
缺点:
适用场景:
https://www.cnblogs.com/killer21/articles/11918024.html
Master High Availability Manager and Tools for MySQL。是由日本人开发的一个基于Perl脚本写的工具。这个工具专门用于监控主库的状态,当发现master节点故障时,会提升其中拥有新数据的slave节点成为新的master节点,在此期间,MHA会通过其他从节点获取额外的信息来避免数据一致性方面的问题。MHA还提供了mater节点的在线切换功能,即按需切换master-slave节点。MHA能够在30秒内实现故障切换,并能在故障切换过程中,最大程度的保证数据一致性。在淘宝内部,也有一个相似的TMHA产品。
MHA是需要单独部署的,分为Manager节点和Node节点,两种节点。其中Manager节点一般是单独部署的一台机器。而Node节点一般是部署在每台MySQL机器上的。Node节点得通过解析各个MySQL的日志来进行一些操作。
Manager节点会通过探测集群里的Node节点去判断各个Node所在机器上的MySQL运行是否正常,如果发现某个Master故障了,就直接把他的一个Slave提升为Master,然后让其他Slave都挂到新的Master上去,完全透明。
优点:
缺点:
MGR: MySQL Group Replication。是MySQL官方在5.7版本正式推出的一种组复制机制。主要是解决传统异步复制和半同步复制的数据一致性问题。
由若千个节点共同组成一个复制组,一个事务提交后,必须经过超过半数节点的决议并通过后,才可以提交。引入组复制,主要是为了解决传统异步复制和半同步复制可能产生数据不一致的问题。MGR依靠分布式一致性协议(Paxos协议的一个变体),实现了分布式下数据的最终一致性,提供了真正的数据高可用方案(方案落地后是否可靠还有待商榷)。
支持多主模式,但官方推荐单主模式:
优点:
缺点:
使用业务的场景
前面我们做的一大段实验,目的是为了大家能够理解MySQL的主从集群。而主从集群的作用,在我们开发角度更大的是作为读写分离的支持也是我们后面学习ShardingSphere的重点。我们这一部分就来介绍下分库分表。
分库分表就是业务系统将数据写请求分发到master节点,而读请求分发到slave节点的一种方案,可以大大提高整个数据库集群的性能。但是要注意,分库分表的一整套逻辑全部是由客户端自行实现的。而对于MySQL集群数据主从同步是实现读写分离的一个必要前提条件。
分库分表就是为了解孢由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成,将数据大表拆分成若干数据表组成,使得单一数据库、单
数据表的数据量变小,从而达到提升数据库性能的目的。
例如:微服务架构中,每个服务都分配一个独立的数据库,这就是分库。而对一些业务日志表,按月拆分成不同的表,这就是分表。
分库分表包含分库和分表两个部分,而这两个部分可以统称为数据分片,其目的都是将数据拆分成不同的存储单元。另外,从分拆的角度上,可以分为垂直分片和水平分片。
垂直分片: 按照业务来对数据进行分片,又称为纵向分片。他的核心理念就是转库专用。在拆分之前,一个数据库由多个数据表组成,每个表对应不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库或表中,从而将压力分散至不同的数据库或表。例如,下图将用户表和订单表垂直分片到不同的数据库:
垂直分片往往需要对架构和设计进行调整。通常来讲,是来不及应对业务需求快速变化的。而且,他也无法真正的解决单点数据库的性能瓶颈。垂直分片可以缓解数据量和访问量带来的问题,但无法根治。如果垂直分片之后,表中的数据量依然超过单节点所能承载的阈值,则需要水平分片来进一步处理。
常用的分片策略有:
水平分片从理论上突破了单机数据量处理的瓶颈,并且扩展相对自由,是分库分表的标准解决方案。
一般来说,在系统设计阶段就应该根据业务耦合松紧来确定垂直分库,垂直分表方案,在数据量及访问压力不是特别大的情况,首先考虑缓存、读写分离、索引技术等方案。若数据量极大,且持续增长,再考虑水平分库水平分表方案。
扩展问题: 如何设计一个不需要数据迁移的取模分片扩容方案?
之前说过,分库分表其实并不只是字面意义上的拆分数据,他还有一系列的问题需要解决。虽然数据分片解决了性能、可用性以及单点备份恢复等问题,但是分布式的架构在获得收益的同时,也引入了非常多新的问题。而这些,都是一个成熟的分库分表方案需要考虑的问题。
在阿里巴巴公布的开发手册中,建议MySQL单表记录如果达到500W这个级别,或者单表容量达到2GB,一般就建议进行分库分表。而考虑到分库分表需要对数据进行再平衡,所以如果要使用分库分表,就要在系统设计之初就详细考虑好分库分表的方案,这里要分两种情况。
一般对于用户数据这一类后期增长比较缓慢的数据,一般可以按照三年左右的业务量来预估使用人数,按照标准预设好分库分表的方案。
而对于业务数据这一类增长快速且稳定的数据,一般则需要按照预估量的两倍左右预设分库分表方案。并且由于分库分表的后期扩容是非常麻烦的,所以在进行分库分表时,尽量根据情况,多分一些表。最好是计算一下数据增量,永远不用增加更多的表。
另外,在设计分库分表方案时,要尽量兼顾业务场景和数据分布。在支持业务场景的前提下,尽量保证数据能够分得更均匀。
最后,一旦用到了分库分表,就会表现为对数据查询业务的灵活性有一定的影响,例如如果按userld进行分片,那按age来进行查询,就必然会增加很多麻烦。如果再要进行排序、分页、聚合等操作,很容易就扛不住了。这时候,都要尽量在分库分表的同时,再补充设计一个降级方案,例如将数据转存一份到ES,ES可以实现更灵活的大数据聚合查询。
由于分库分表之后,数据被分散在不同的数据库、服务器。因此对数据的操作也就无法通过常规方式完成,并且它还带来了一系列的问题。好在,这些问题不是所有都需要我们在应用层面上解决,市面上有很多中间件可供我们选择,我们来了解一下它。
Sharding-JDBC是当当网研发的开源分布式数据库中间件,他是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar (计划中)这3款相互独立的产品组成。他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。
MyCAT虽然是从阿里的技术体系中出来的,但是跟阿里其实没什么关系。
该网站包含几个重要产品。其中分布式中间件可以认为是MyCAT的一个增强版,专注于MySQL的集群化管理。另外还有数据传输组件和分布式事务框架组件可供选择。