上节说到主从复制的一些问题
咱们再来回忆一下
主从复制,增长了一个数据库副本,从数据库和主数据库的数据最终会是一致的
之因此说是最终一致,由于mysql复制是异步的,正常状况下主从复制数据之间会有一个微小的延迟
经过这个数据库副本看似解决了数据库单点问题,但并不完美
由于这种架构下,若是主服务器宕机,须要手动切换从服务器,业务中断不能忍受,不能知足应用高可用的要求html
若是才能解决当master服务器宕机后,前端应用自动切换连接呢?前端
最简单的方式就是给数据库复制集群上增长一个虚拟ipmysql
虚拟IP(vip):redis
就是一个未分配给真实主机的ip,也就是说对外提供服务器的主机除了有一个真实IP外还有一个虚拟IPsql
而前端应用程序使用虚拟ip来连接数据库服务器,当master宕机后,虚拟ip由masterDB迁移到slaveDB上,这样就不用人为的修改前端应用的配置了数据库
设置虚拟IP有不少种方法缓存
除了脚原本实现这些功能,还能够经过MHA,MMM这样的集群管理工具来实现服务器
此处采用keepalived来配置虚拟ip网络
首先,keepalived能够提供vip,并对主从数据库的健康状态进行监控
当主DB宕机时,迁移VIP到主备数据库服务器上,这样就解决了当masterDB宕机时,要手动修改应用服务器的配置,重新链接到主备服务器上的问题架构
可是目前还存在一个问题,当master恢复后,因为当前的写操做迁移到了从上,因此若是要使用到老的master对新的master(也就是老的slave)进行同步,就不得不从新配置主从复制了,特别是在基于日志点的复制状况下,这时候若是咱们数据库的数据量很是大,在这种状况下,从新初始化数据也是比较耗时的
因此咱们要对主从复制的架构进行一些更改,改变原来的主从复制为主主复制,但必定要保证同一个时间只有一个主提供服务,而另外一个主(也就是主备)是处于只读状态的,只对外提供读服务,而不提供写服务
之前说过InnoDB表的主键最好采用自增ID的列,而在主主复制中,为了不两个主中同时写带来的主键冲突,咱们须要修改自增主键的一些配置,使两个主上的自增主键按照不一样的步长进行增加 ,这只是为了以防万一采起的一个配置,当咱们使用主主复制时,仍是要保证在任意时间,均只有一个主能够对外提供服务 ,而另外一个主只提供只读的服务
master 数据库配置修改
auto_increment_increment = 2 # 控制自增ID增加的步长,默认为1 auto_increment_offset = 1 # 控制自增ID从哪一个值开始
这样修改后,id将会变成1,3,7,9...的形式
主备数据库配置修改
auto_increment_increment = 2 # 控制自增ID增加的步长,默认为1 auto_increment_offset = 2 # 控制自增ID从哪一个值开始
这样修改后,id将会变成2,4,6,8...的形式
Keepalived基于ARRP网络协议,ARRP能够将2台设备虚拟成一个设备,可对外提供一个虚拟IP,也就是咱们架构中的vip,在服务器内部其实是拥有虚拟IP的设备若是正常工做的话就是MASTER设备,同一组内其余服务器不能用这个虚拟IP,状态是属于BACKUP状态,处于BACKUP状态的设备,除了接收MASTER的ARRP状态通告以外,不执行任何对外的服务,当主机失效时,backup将接管原先的master的虚拟IP以及对外提供的各项服务
yum install keepalived -y
在主和主备服务器上都要安装和配置keepalived
配置文件所在位置
/etc/keepalived/keepalived.conf
配置文件中是按模块划分的
! Configuration File for keepalived global_defs { router_id mysql_ha } vrrp_script check_run { script "/etc/keepalived/check_mysql.sh" interval 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 200 priority 99 advert_int 1 nopreempt authentication { auth_type PASS auth_pass 1200 } track_script { check_run } virtual_ipaddress { 192.168.3.99/24 } }
vrrp_script模块中:
定义用于检查mysql是否运行正常的脚本,以及检查的时间间隔
vrrp_instance 模块中:
定义了keepalived服务所处的状态,这个状态只有BACKUP和MASTER两个值
interface :定义了绑定 虚拟ip的网络接口,必定要是服务器上可用的网络接口
virtual_router_id :定义了虚拟服务的id,要取0到255之间的数字
priority :定义了优先级,值越高,优先级越大,备份的备设备的值要比主设备低
nopreempt:此值表明不抢占资源,意思是原来的主宕机后,即便再恢复后也不会把虚拟IP抢回来,对于数据库来讲,这样能够避免主从切换的二次伤害的可能
authentication :配置验证信息,这个在两个节点必须是一致的
virtual_ipaddress :定义了使用的虚拟ip信息
[client] port = 3306 # 客户端端口号为3306 socket = /home/mysql/data/mysql.sock [mysqld] # skip # skip_name_resolve = 1 skip-external-locking =1 # GENERAL # user = mysql # MySQL启动用户 default_storage_engine = InnoDB # 新数据表的默认数据表类型 character-set-server = utf8 # #服务端默认编码(数据库级别) socket = /home/mysql/data/mysql.sock pid_file = /home/mysql/data/mysqld.pid basedir = /home/mysql #使用该目录做为根目录(Mysql安装目录); port = 3306 bind-address = 0.0.0.0 log_error_verbosity = 3 explicit_defaults_for_timestamp = off #sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES #sql_mode = NO_ENGINE_SUBSTITUTION # undo log # innodb_undo_directory = /home.mysql/undo # innodb_undo_tablespaces = 32 # MyISAM # key_buffer_size =32M # SAFETY # max_allowed_packet = 100M max_connect_errors = 1000000 sysdate_is_now =1 #innodb = FORCE #innodb_strict_mode = 1 # Replice # server-id = 100 relay_log = /home/mysql/sql_log/mysqld-relay-bin #plugin-load = semisync_master.so log_slave_updates = on master_info_repository = TABLE relay_log_info_repository =TABLE #######主主复制新增的配置########### auto_increment_increment = 2 # 控制自增ID增加的步长,默认为1 auto_increment_offset = 1 # 控制自增ID从哪一个值开始 ##################### # gtid_mode = on # enforce_gtid_consistency =on # skip-slave-start =1 #rpl_semi_sync_master_enabled = 1 #rpl_semi_sync_master_timeout=200 # 0.2 second master_info_respository = TABLE # gtid_mode= on # enforce_gtid_consistency = on # skip-slave-start = 1 # DATA STORAGE # datadir = /home/mysql/data #mysql 数据文件存放的目录 tmpdir = /tmp # MySQL存放临时文件的目录 # BINARY LOGGING # log_bin = /home/mysql/sql_log/mysql-bin max_binlog_size = 1000M binlog_format = row expire_log_days = 7 sync_binlog = 1 # CACHES AND LIMITS # tmp_table_size = 32M max_heap_table_size = 32M query_cache_type = 0
auto_increment_increment ,auto_increment_offset 这两个参数是动态参数,咱们能够直接经过命令进行修改,不须要重启
查看并修改
命令以下
mysql> show variables like 'auto%'; mysql> set global auto_increment_increment=2; mysql> set global auto_increment_offset =1;
从服务器配置进行相似修改便可
从服务器配置
[client] port = 3306 # 客户端端口号为3306 socket = /home/mysql/data/mysql.sock [mysqld] # skip # skip_name_resolve = 1 skip-external-locking =1 # GENERAL # user = mysql # MySQL启动用户 default_storage_engine = InnoDB # 新数据表的默认数据表类型 character-set-server = utf8 # #服务端默认编码(数据库级别) socket = /home/mysql/data/mysql.sock pid_file = /home/mysql/data/mysqld.pid basedir = /home/mysql #使用该目录做为根目录(Mysql安装目录); port = 3306 bind-address = 0.0.0.0 log_error_verbosity = 3 explicit_defaults_for_timestamp = off #sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES #sql_mode = NO_ENGINE_SUBSTITUTION read_only = on # undo log # innodb_undo_directory = /home.mysql/undo # innodb_undo_tablespaces = 32 # MyISAM # key_buffer_size =32M # SAFETY # max_allowed_packet = 100M max_connect_errors = 1000000 sysdate_is_now =1 #innodb = FORCE #innodb_strict_mode = 1 # Replice # server-id = 101 relay_log = /home/mysql/sql_log/mysqld-relay-bin #plugin-load = semisync_master.so log_slave_updates = on master_info_repository = TABLE relay_log_info_repository =TABLE #######主主复制新增的配置########### auto_increment_increment = 2 # 控制自增ID增加的步长,默认为1 auto_increment_offset = 2 # 控制自增ID从哪一个值开始 ##################### # gtid_mode = on # enforce_gtid_consistency =on # skip-slave-start =1 #rpl_semi_sync_master_enabled = 1 #rpl_semi_sync_master_timeout=200 # 0.2 second master_info_respository = TABLE # gtid_mode= on # enforce_gtid_consistency = on # skip-slave-start = 1 # DATA STORAGE # datadir = /home/mysql/data #mysql 数据文件存放的目录 tmpdir = /tmp # MySQL存放临时文件的目录 # BINARY LOGGING # log_bin = /home/mysql/sql_log/mysql-bin max_binlog_size = 1000M binlog_format = row expire_log_days = 7 sync_binlog = 1 # CACHES AND LIMITS # tmp_table_size = 32M max_heap_table_size = 32M query_cache_type = 0
mysql> show variables like 'auto%'; mysql> set global auto_increment_increment=2; mysql> set global auto_increment_offset =2;
从服务器查看二进制日志信息
命令
mysql> show master status \G
能够查看当前使用的日志文件
File:mysql-bin:000003
和日志点
Position:25423894
而后去主服务器上使用change master命令
因为从到主的复制链路以前已开启过,如今只须要配置主到从的
因为是主主复制 是把当前的主看成从,把当前的从看成主,在主上配置的master_host的值是从的ip,
命令以下:
mysql> change master to master_host='192.168.2.100', -> master_user='dba_repl', -> master_password='123456', ->MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=25423894; mysql> start slave;
yum install keepalived -y
[root@localhost ~]# cd /etc/keepalived/ [root@localhost keepalived]# ls check_mysql.sh keepalived.bak keepalived.conf
check_mysql.sh 必定要有执行权限
chmod a+x check_mysql.sh
[root@localhost keepalived]# /etc/init.d/keepalived start
启动成功后,能够经过ip addr命令查看虚拟ip
能够经过手动关闭mysql模式宕机,查看主的ip addr中的虚拟Ip已不存在,此时已虚拟Ip在从服务器上
一台主服务器,一台从服务器,加入了keepalived服务来监控主从服务器的运行健康状态,并经过keepalived服务器生成了一个虚拟IP,前端应用是经过虚拟IP来进行数据库的访问,而且为了使主库宕机后能尽快恢复,把原来的主从复制改成了主主复制
可是目前的读写操做还只是所有经过虚拟IP使用同一台数据库服务器(主服务器或主备服务器)来进行访问的,因此这个架构也没有解决单台数据库服务器读写压力大的问题
对于数据库服务器来讲,读负载和写负载是两个不一样的问题
相对于写负载,解决读负载要更容易,由于咱们能够很容易的获得多个slave服务器,而且在正常的业务环境中数据库所执行的读操做次数要远远高于写操做的次数
同时那些有性能问题的慢查询,也都是读操做产生的
解决方式见:如何解决MySQL读压力大的问题
MySQL复制没法缓解写压力
利用缓存,合并屡次写为一次写
缓解写压力须要对MasterDB进行拆分
前面数据库操做规范中说过,程序所使用的数据库帐号只能在同一个数据库下进行操做,不容许跨库查询数据库
MasterDB中有mc_userdb、mc_productdb、mc_orderdb三个数据库
创建好新的数据库集群后,就能够在新老集群之间创建主从同步关系,把要拆分的DB同步到新的集群中
即 把mc_productdb同步到商品集群中 ,mc_orderdb同步到订单集群中
当数据库同步成功后,找一个业务的低峰时间段,好比凌晨三、4点时,把老集群上数据库的帐号,迁移到新的数据库集群中
迁移成功后,修改老集群的应用在老集群数据库上的连接,把
对mc_productdb和mc_orderdb上的连接修改到新的集群上