MySQL的主从复制
一、为什么需要主从
当负载过大时,web端可以用nginx负载多个tomcat进行负载均衡。那么当请求动态数据(查询数据库)负载过大,该如何解决呢?
此时,首先在web和数据库中间,添加缓存的方式,解决负载过大的问题。
其次,最终的解决方案,还是需要做mysql的主从。
二、优缺点
优、主从可以做读写分离,从服务器负责读操作,分担读的负载。
缺、从服务器的数据存在延迟,能负载的读,只能是实时性不高的数据,例如:操作日志,统计报表,查询历史数据。。。等实时性不高的数据。
三、原理
1、在主服务器上,开启bin-log文件,记录所有的非读操作sql语句。
2、在主服务器上,线程1负责将非读操作的sql插入bin-log文件中。
3、在从服务器上,线程2负责跟主服务器进行通信,请求bin-log文件内容,写入relay-log文件中。
4、在主服务器上,线程3负责跟从服务器的线程2进行应答,返回bin-log文件对应的内容。
5、在从服务器上,线程4负责将relay-log文件中的内容取出并执行,使从服务器得到与主服务器一样的数据。
四、配置方式
找到主MySQL安装文件夹修改my.Ini文件,添加如下配置:
server-id=1 //给数据库服务的唯一标识,集群内唯一,一般为大家设置服务器Ip的末尾号
log-bin=master-bin //bin-log文件的前缀。
log-bin-index=master-bin.index //bin-log文件的索引,方便查找bin-log文件中的内容。
启动主服务器,执行如下语句:
mysql> SHOW MASTER STATUS;
得到 File 字段的值 master-bin.xxxxx
找到从MySQL安装文件夹修改my.Ini文件,添加如下配置(各项代表的含义,类似主服务器):
server-id=2
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin
启动从服务器,执行如下语句:
change master to master_host='192.168.0.104', //Master 服务器Ip
master_port=3306, //数据库端口号
master_user='root', //链接数据库的用户名
master_password='pwd', //链接数据库的密码
master_log_file='master-bin.xxxxx', //Master服务器产生的日志,即刚刚执行SHOW MASTER STATUS;语句得到的 File字段的值。
master_log_pos=0; //从哪一行开始复制。
到此,主从复制,配置完成。
从服务器可以做负载均衡,用HaProxy来做。即在从服务器与应用程序之间,用HaProxy来做负载均衡,所有的请求通过HaProxy来处理,不再需要应用程序维护从服务器列表,从服务器的多少,对应用来说透明了。
五、主主复制
为何需要双主?
主从复制,解决了性能问题,但是存在单节点问题。
原理:
两个主服务器,互为主从。即主服务器A,B中,A是B的主,B也是A的主。两者相互复制备份。
工作时,只有一台主服务器运行,另一台主服务器做备库,当主服务器故障时,备服务器接替主服务器的工作,成为新的主服务器,提供高可用服务。
配置步骤:
A服务器的配置,my.cnf 配置文件修改如下:
# 服务器的ID,必须唯一,一般设置自己的IP
server_id=1
# 复制过滤:不需要备份的数据库(MySQL库一般不同步)
binlog-ignore-db=mysql
# 开启二进制日志功能,名字可以随便取,最好有含义(比如项目名)
log-bin=edu-mysql-bin
# 为每个 session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
# 主从复制的格式(mixed,statement,row,默认格式是 statement)
binlog_format=mixed
# 二进制日志自动删除/过期的天数。默认值为 0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免 slave 端复制中断。
## 如:1062 错误是指一些主键重复,1032 错误是因为主从数据库数据不一致
slave_skip_errors=1062
# 作为从服务器时的中继日志
relay_log=edu-mysql-relay-bin
# log_slave_updates 表示 slave 将复制事件写进自己的二进制日志
log_slave_updates=1
# 主键自增规则,避免主从同步ID重复的问题,5.7版本开始,已经不需要做此设置,同步的时候,会将自增的id进行同步。
auto_increment_increment=2 # 自增因子(每次加2)
auto_increment_offset=1 # 自增偏移(从1开始),单数B
重启A服务器,将A服务器配置为B的主,并创建数据库同步用户,并授予相应的权限 ,其中的ip为B的ip,用户名和密码是A的。(只允许repl用户从192.168.1.2上登录)
mysql> grant replication slave, replication client on *.* to 'repl'@'192.168.1.2' identified by 'root123456';
将A服务器配置为B服务器的从:
# master_user和master_password:在B上执行grant replication slave...创建的用户和密码
# master_log_file和master_log_pos:在B上运行show master status;命令执行结果对应File和Position字段的值
mysql> change master to master_host='192.168.1.2',master_user='repl', master_password='root123456', master_port=3306, master_log_file='edu-mysql-bin.000001', master_log_pos=439, master_connect_retry=30;
B服务器的配置,my.cnf 配置文件修改如下:
server_id=2
binlog-ignore-db=mysql
log-bin=edu-mysql-bin
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
slave_skip_errors=1062
relay_log=edu-mysql-relay-bin
log_slave_updates=1
#ID自增从2开始,双数。5.7版本开始,已经不需要做此设置,同步的时候,会将自增的id进行同步。
auto_increment_increment=2
auto_increment_offset=2
重启B服务器,将B服务器配置为A的主,并创建数据库同步用户,并授予相应的权限 ,其中的ip为A的ip,用户名和密码是B的。(只允许repl用户从192.168.1.1上登录)
mysql> grant replication slave, replication client on *.* to 'repl'@'192.168.1.1' identified by 'root123456';
将B服务器配置为A服务器的从:
# master_user和master_password:在B上执行grant replication slave...创建的用户和密码
# master_log_file和master_log_pos:在B上运行show master status;命令执行结果对应File和Position字段的值
mysql> change master to master_host='192.168.1.1',master_user='repl', master_password='root123456', master_port=3306, master_log_file='edu-mysql-bin.000001', master_log_pos=439, master_connect_retry=30;
masterA和masterB分别执行如下命令:
mysql> stop slave;
mysql> start slave;
到此,双主,配置完成。为了提供高可用,需要配合 keepalived 进行使用,提供故障切换的功能。