集群

在一些大型网站业务场景中,单台数据库服务器所能提供的并发量已经无法满足业务需求,为了满足这种情况,一般而言是通过主从同步的方式来同步数据,在此基础上,通过读写分离来提升数据库的并发和负载能力。

一般可以**采用横向扩展和库表切分的方法实现数据库处理能力的提升**,因为单机的硬件处理能力一定是有上限。由此而生的相关技术有:读写分离和负载均衡

MySQL的主从复制

需要实现集群多台机器共同对外提供服务,需要考虑的是如何实现读操作和写操作的工作划分。首先就需要部署主从复制,只有实现了主从复制,才能在此基础上实现读写分离

MySQL所支持的复制类型

  • 基于语句的复制,MySQL默认采用的是基于语句的复制,效率比较高

  • 基于行的复制,把改变的内容复制过去,而不是把命令复制到从服务器上再次执行一次

  • 混合类型复制,默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制

主从复制的原理

首先启动master,然后启动slave,

在master中执行命令 show master status ,File表示实现复制功能的日志,就是二进制日志binlog。Position表示二进制日志文件的偏移量,偏移量之后的操作都会同步到slave,在偏移量之前的则需要收到导入

mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000004 |     5138 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

针对从库设置主库的配置信息。这里的master_log_file和master_log_pos都来自于master中查询结果

 change master to master_host='localhost', master_port=3306, master_user='root', master_password='123456', master_log_file='mysql- bin.000002',master_log_pos=445;

在这里插入图片描述

master上面的任何修改操作都会记录到二进制日志中,slave上会启动一个IO线程,连接到master上请求读取二进制日志文件,注意这里会有一定的延迟。slave将读取到的二进制日志数据写入到本地的中继日志relay log中。slave会开启一个SQL线程,定时检查relay log的修改,如果发现有更改的内容,则在本机上执行一次修改操作。这样就是实现了将master上的修改同步到slave上的目的

在这里插入图片描述

如果是一主多从时,主库既要负责写又要负责为几个从库提供二进制日志,工作压力有点大。所以在一般的生产环境后可以稍作调整,将二进制日志只发送给某个从节点。这个从节点再开启二进制日志,并将自己的二进制日志再次发送给其它从节点,或者这个从节点不记录,只是负责将二进制日志转发给其它从节点。这样的结构性能会比简单的一主多从的模式性能好很多,而且数据之间的延迟应该会稍好一些。

在这里插入图片描述

一主会有单点故障问题,解决方案为主备模式的主主复制

主从复制的工作过程[重点]

master负责完成写操作,slave负责执行复制操作

1、在每个事务更新数据完成之前,master主机在二进制日志中记录这些改变binlog。再写入二进制日志完成后,master通知存储引擎提交事务

2、从机slave将master的binlog复制到其中的中继日志relaylog。首先slave启动一个工作线程IO线程,IO线程在master上打开一个普通的连接,然后开始binlog dump process。binlog dump process从master的二进制日志中读取操作事件,如果已经跟上了master,它会休眠并等待master产生新的事件。IO线程将事件写入中继日志relay log

3、SQL从线程从中继日志读取事件,重放其中的事件而更新slave中的数据,使slave种的数据和master中的一致

注意:master的并行更新在slave种是串行执行的

在这里插入图片描述

主从节点配置

般常见的主从集群会采用3个节点构成,1主多从

实验方式2种:采用centos+虚拟机、windows下通过不同的端口配置1主1从

windows下采用解压版,防止在多次安装的时候告诉已安装mysql不允许再次安装

master配置

端口号使用3306

mysql的安装路径下,名称为my.ini

# 开启二进制日志 
log-bin=mysql-bin 
# 设置日志的过期时间,避免占满磁盘 
expire-logs-days=7 
# binlog-ignore-db不使用主从复制的数据库 
binlog-do-db可以设置需要进行主从复制的数据 库
binlog-ignore-db=mysql 
# 设置3306端口 
port=3306 
# mysql服务器具体的安装路径 
basedir=D:/software/mysql-8.0.15-master 
# mysql的本地数据文件的存储路径 
datadir=D:/software/mysql-8.0.15-master/data 

# 允许最大连接数 
max_connections=200 
# 允许连接失败的次数 
max_connect_errors=10 
# 默认编码字符集 
character-set-server=utf8mb4 
# 默认存储引擎 
default-storage-engine=INNODB 
# 默认使用mysql_native_password插件进行口令认证 
default_authentication_plugin=mysql_native_password 

[mysql] 
# 设置mysql客户端默认字符集 
default-character-set=utf8mb4 

[client] 
# 设置mysql客户端连接服务端时默认使用的端口 
port=3306 
default-character-set=utf8mb4

初始化操作 mysqld --initialize --console

将mysql添加到系统服务中 mysqld --install mymaster

启动master节点的数据库服务 net start mymaster

使用mysql客户端连接数据库修改root的默认口令

slave配置

mysql的安装路径下,名称为my.ini

[mysqld] 
server-id=16 
# 设置3316端口 
port=3316 
# mysql服务器具体的安装路径 
basedir=D:/software/mysql-8.0.15-slave 
# mysql的本地数据文件的存储路径 
datadir=D:/software/mysql-8.0.15-slave/data 

[client] 
# 设置mysql客户端连接服务端时默认使用的端口 
port=3316 
default-character-set=utf8mb4

初始化新的mysql数据库系统 mysqld --initialize --console

安装系统服务 mysqld --install myslave

启动数据库 net start myslave

修改默认口令

查看主库状态 show master status; 主要需要查看记录二进制日志具体名称File和对应的偏移量Posititon

mysql> show master status; 
+------------------+----------+--------------+------------------+------------ -------+ 
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set  | 
+------------------+----------+--------------+------------------+------------ -------+ 
| mysql-bin.000002 | 445      |              | mysql            |                    | 
+------------------+----------+--------------+------------------+------------ -------+ 
1 row in set (0.00 sec)

针对从库设置主库的配置信息

#主库ip
change master to master_host='localhost', 
#master_port:主库端口号
master_port=3306, 
#master_user:主库账号
master_user='root', 
#master_password:主库密码
master_password='123456', 
#master_log_file:对应主库状态中的file
master_log_file='mysql- bin.000002',
#master_log_pos:对应主库状态中的position
master_log_pos=445;

启动从库 start slave;

查看从库状态 show slave status;

主库进行插入修改数据的时候从库就可以自动进行复制

MySQL读写分离

读写分离实际上就是在主从复制的基础上,只在主服务器上执行写操作,只在从服务器上执行读操作。

基本原理就是让主数据库处理事务性操作,而从数据库处理select查询,数据库的主从复制用来将事务性操作导致的数据变更同步到集群中的从数据库上

在这里插入图片描述

典型的实现方式就是基于中间代理层的实现:代理一般位于客户端和服务器之间,代理服务器接收到客户端请求后通过判断所执行的操作后转发到对应的后端数据库服务器上

读写分离的原因

数据库写入效率要低于读取效率,一般系统中数据读取频率高于写入频率,单个数据库实例在写入的时候会影响读取性能,这是做读写分离的原因。

读写分离实现

Mysql读写分离可以基于第三方插件,例如Mycat或者基于程序读写分离(应用内部路由)

应用内路由

基于spring的AOP实现。

用aop来拦截spring项目的dao层方法,根据方法名称就可以判断要执行的sql类型(即是read还是write类型),进而动态切换主从数据源。

在这里插入图片描述

基于jdbc驱动方式

使用mysql驱动mysql-connector-java的Connector/J的可以实现读写分离。即在jdbc的url中配置jdbc:mysql:replication://master,slave1,slave2,slave3/test

java程序通过在连接MySQL的jdbc中配置主库与从库等地址,jdbc会自动将读请求发送给从库,将写请求发送给主库,此外,mysql的jdbc驱动还能够实现多个从库的负载均衡。

Mycat中间件方式

Mycat可以实现对业务数据库的分库分表、读写分离,能够很方便的构建一个以Mycat为核心的数据库集群架构,以企业级方案解决数据库出现的性能问题

Mycat能够将mysql数据组成一个分布式的集群,可以把物理上多个独立的mysql数据库,搞成一个逻辑上的整体,使开发者感受不到的物理上的独立。这些物理上独立的mysql数据库按照配置不同各自完成各自的工作。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐