前言
无论是在一个 web 站点还是其他需要数据库的业务系统中,数据库的重要性是毋庸置疑的。但是关系型数据库收到自身设计的限制,本身的性能可能会成为拉低整个平台的瓶颈。而且数据库作为系统重要的一环,必须避免数据库的单点故障。由此 mysql 数据库的集群就显得至关重要。
集群分类及分析
mysql 复制集群总体可以分为如下几类:
- 主从复制集群:主服务器负责数据写入,从服务器负责读操作,这样可以整体降低主服务器的压力,而且可以提高访问性能;
- 双主或多主集群:两台或多台 mysql 服务器同时都提供读写操作;
- 半同步集群:一台服务器和主服务器采用同步写入的方式,当主服务器宕机这台服务器提升为主服务器;
- 级联复制集群:多级复制集群,降低主服务器的压力;
- 循环集群
...
此文主要讨论主从复制集群、双主集群和半同步集群的配置方法。
在一定程度上复制集群确实能够解决 mysql 的性能问题和单点问题,但是却也面临着更多其他问题: - 当 mysql 集群运行一定时间之后可能会面临主从服务器数据不一致,从服务器数据滞后于主服务器的问题,这是由 mysql 复制集群的特点所决定的;
- 双主或多主复制集群,如果两台服务器同时发生基于一个字段的修改,可能会发生数据的重复修改问题,导致数据不一致;
...
mysql 复制集群的原理
mysql 复制集群是基于如下原理进行的:
主服务器所有的操作都写入二进制日志,从服务器开启中继日志和两个线程:
- sql_thread:负责从中继日志读取内容,然后 replay 到数据库中;
- io_thread:负责连接主服务器,把主服务器的二进制日志复制到自己的中继日志;
mysql 复制集群配置方法
主从复制集群
- 此处采用两台 mysql 服务器,一台为主,一台为从;
- 首先配置主服务器:
- 修改/etc/my.cnf.d/server.conf,添加 server_id 和开启 binary-log:如下:
server_id=1 log_bin=master-log
- 登录 mysql,然后添加一个有复制权限的用户,命令如下:
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repladmin'@'192.168.11.%' identified by '1234567a';
- 修改/etc/my.cnf.d/server.conf,添加 server_id 和开启 binary-log:如下:
- 配置从服务器:
-
修改/etc/my.cnf.d/server.conf 文件,添加 server_id,开启 relay-log,如下:
server_id=11 relay_log=slave-log read_only=ON #从服务器只允许读操作,不允许写操作
-
指定主服务器,用户名和从哪个日志开始进行同步:
CHANGE MASTER TO MASTER_HOST='192.168.11.193',MASTER_USER='repladmin',MASTER_PASSWORD='1234567a',MASTER_LOG_FILE='master-log.000003',MASTER_LOG_POS=499; #MASTER_LOG_FILE指的是主服务器的二进制日志,MASTER_LOG_POS指的是从哪里开始进行同步,可以在服务器通过**show master status**进行查看
-
开启 sql_thread 和 io_thread 进行复制,然后查看状态,用如下命令:
start slave; show slave status;
-
状态信息如下:
Slave_IO_State: Waiting for master to send event #当前复制状态# Master_Host: 192.168.11.193 #主服务器ip# Master_User: repladmin #进行复制的用户# Master_Port: 3306 #连接的端口# Connect_Retry: 60 #连接超时等待多久重新连接# Master_Log_File: master-log.000003 #开始同步的二进制日志文件# Read_Master_Log_Pos: 8523 #从二进制文件哪里开始同步# Relay_Log_File: slave-log.000005 #执行sql语句replay的二进制文件# Relay_Log_Pos: 961 #从哪里开始执行# Relay_Master_Log_File: master-log.000003 Slave_IO_Running: Yes #io_thread是否运行# Slave_SQL_Running: Yes #sql_thread是否运行# Replicate_Do_DB: hellodb #这是指定复制过滤器之后的样子,表示金复制hellodb库# Replicate_Ignore_DB: Replicate_Do_Table: hellodb.students #表示只复制students表# Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 #复制过程是否有错误# Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 8523 Relay_Log_Space: 1534 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 #是否启用ssl认证# Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 #从服务器是否落后于主服务器,为0表示不落后# Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1
-
此时在主服务器创建新的库或者表,从服务器即可同步。(此处因为开启了复制过滤器,所以只能复制指定的库和表)
-
双主复制集群配置
双主配置原理为:主服务器和从服务器同时开启二进制日志和中继日志,数据可以写入任何一个服务器,然后都可以同步到另一台服务器,这样两个库就都可以提供读写工作了。
- 主服务器-1 配置
- 主服务器开启二进制日志和中继日志,并且允许读写:
server_id=1 log_bin=master-log relay_log=slave-log
- 创建具有复制权限的用户,此处和主从复制命令一样,不再赘述;
- 主服务器开启二进制日志和中继日志,并且允许读写:
- 主服务器-2 配置方法和主服务器-1 配置方法一模一样
- 此时需要在主服务器-1 和主服务器-2 都执行 CHANGE MASTER 操作,不过主服务器的 ip 需要互相指定为对方,如下:
CHANGE MASTER TO MASTER_HOST='主服务器-2ip地址',MASTER_USER='repladmin',MASTER_PASSWORD='1234567a',MASTER_LOG_FILE='master-log.000003',MASTER_LOG_POS=499; CHANGE MASTER TO MASTER_HOST='主服务器-1ip地址',MASTER_USER='repladmin',MASTER_PASSWORD='1234567a',MASTER_LOG_FILE='master-log.000003',MASTER_LOG_POS=499;
- 两台服务器其都开启同步操作:
start slave;
- 此时往任何一个数据库写入数据都可以同步到另一个库,同时两个库都支持读写操作;
半同步复制集群配置
复制集群默认采用的都是异步方式,即数据写入主服务器则直接返回数据写入成功,而不会等待从服务器写入成功,此种方法可以提高性能,不过可能会导致数据不一致问题。半同步表示让一台服务器和主服务器采用同步写入方式,数据写入到从服务器才返回数据写入成功,这样会损失一定性能,不过当主服务器宕机之后这才从服务器可以立刻接管主服务器,他们的数据都是一致的。
半同步复制集群需要依赖于半同步模块,此模块默认并没有加载,需要手动加载到 mysql 中,模块如下:semisync_master.so、semisync_slave.so。
- 主服务器配置:
- 配置文件配置和创建具有复制权限用户,修改 CHANGE MASTER 的方法和主从复制集群配置方法一样,此处不再赘述;
- 加载半同步模块,命令如下:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; show plugins; #查看mysql加载的所有模块,可以看此模块是否已经加载
- 模块加载之后默认还是不会启动服务,需要手动启动,如下:
SHOW GLOBAL VARIABLES LIKE 'rpl_semi%'; SET GLOBAL rpl_semi_sync_master_enabled=ON;
- 从服务器配置:
- 加载半同步模块,命令如下:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; SET GLOBAL rpl_semi_sync_slave_enabled=ON; START SLAVE;
- 加载半同步模块,命令如下:
- 此时查看主服务器状态如下:
show global status like 'rpl_semi%'; #参数如下,只列出部分: Rpl_semi_sync_master_clients #连接到主服务器的客户端数# Rpl_semi_sync_master_net_avg_wait_time #平均网络等待时间# Rpl_semi_sync_master_net_wait_time #网络总等待时间# Rpl_semi_sync_master_net_waits #网络等待次数# Rpl_semi_sync_master_no_times Rpl_semi_sync_master_no_tx Rpl_semi_sync_master_status ……
- 此时主服务进行任何修改,从服务器都会同步进行所有修改操作,此时表示半同步集群配置成功。
复制过滤器
复制过滤器表示可以指定只复制指定的表或者只复制指定的库,其他的表和库都不进行复制,两种方法可以实现:
- 主服务器实现:主服务器指定只有指定的表或者库的修改信息才传递到从服务器的中继日志,但是主服务器出现问题之后会丢失未复制表和库的数据;
- 从服务器实现:所有二进制日志都传到从服务器的中继日志,但是 sql_thread 只执行指定表和库的修改语句,当主服务器出现故障,则不会丢失数据,所有建议采用从服务器的复制过滤;
-
从服务器配置:
SET GLOBAL replicate_do_db=库名 #指定只复制指定的库# SET GLOBAL Replicate_Ignore_DB=库名 #指定不复制指定的库# SET GLOBAL Replicate_Do_Table=表名 #指定只复制指定表# SET GLOBAL Replicate_Ignore_Table=表名 #指定不复制指定表#
-
当指定了复制过滤器后,通过**SHOW SLAVE STATUS;**命令可以查看到指定的库和表。
建议此配置写入配置文件永久生效。
总结
mysql 的复制集群可以通过以上方法实现,但是此时还缺少一个组件对外提供数据服务接口,此组件一般称为读写分离器或语句路由器,而且主服务器宕机之后需要自动提升从服务器为主服务器,这也需要 mysql 的 MHA 来进行。以上两个组件下一篇博客再讨论。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于