MySQL高可用架构设计

                                     MySQL高可用架构设计

一、MySQL复制功能

    1、MySQL复制功能提供分担读负载

    MySQL高可用架构设计_第1张图片

        MySQL高可用架构设计_第2张图片

    2、复制解决了什么问题?

        (1) 实现在不同服务器上的数据分布;

            a、利用二进制日志增量进行;

            b、不需要太多的带宽;

            c、在使用基于行的复制在进行大批量的更改时,会对宽带带来一定的压力;

            d、跨IDC(互联网数据中心)环境下进行复制时,应该分批进行。

        (2) 实现数据读取的负载均衡;

            a、需要其他组件配合完成;

            b、利用DNS轮循的方式把程序的读连接到不同的备份数据库;

            c、使用LVS,haproxy这样的处理方式;

            d、非共享架构,同样的数据分布在多台服务器上。

        (3) 增强了数据安全性;

            a、利用备库的备份来减少主库负载;

            b、复制并不能代替备份;           

        (4) 实现数据库高可用和故障切换;

            a、方便进行数据库高可用架构的部署;

            b、避免MySQL单点失败。

        (5) 实现数据库在线升级,测试高版本的MySQL和我们现在的代码是否兼容。

 

二、MySQL二进制日志

    MySQL高可用架构设计_第3张图片

    MySQL高可用架构设计_第4张图片

    1、二进制日志的格式

        (1) 基于段的格式 binlog_format = STATEMENT 

            a、优点:

                . 日志记录量相对较小,节约磁盘及网络I/O

                    只对一条记录修改或者插入时,row格式所产生的日志量小于段产生的日志量。

            b、缺点:

                . 可能造成MySQL复制的主从服务器数据不一致,从而中断复制链路cd

                    必须要记录上下文信息,保证语句在从服务器上执行结果和在主服务器上相同。

                    特定函数如UUID(),user()这样非确定性函数还是无法复制。

            c、实例:

                设置二进制日志格式:

                    set session binlog_format=STATEMENT;

                查看二进制日志格式:

                    show variables like 'binlog_format';

                    MySQL高可用架构设计_第5张图片

                获取Binlog文件列表:

                    show binary logs;

                    报错:ERROR 1381 (HY000): You are not using binary logging

                    解决方案:

                        show variables like 'log_bin';

                        MySQL高可用架构设计_第6张图片

                        cd /etc

                        vi my.cnf

                        在mysqld配置项下面加上log_bin=mysql_bin

                            [mysqld]

                            log_bin = mysql_bin

                        service mysqld restart

                        show variables like 'log_bin';

                        MySQL高可用架构设计_第7张图片

                        show binary logs;

                        MySQL高可用架构设计_第8张图片

                    刷新Binlog文件列表:

                        flush logs;

                        show binary logs;

                        MySQL高可用架构设计_第9张图片

                    查看二进制日志文件:

                        create database crn;

                        use crn;

                        create table t(id int, c1 varchar(10));

                        insert into t values(1, "aa");

                        insert into t values(2, "bb");

                        update t set c1="dd" where id=1;                   

                        MySQL高可用架构设计_第10张图片

                        show variables like 'log_%';

                         MySQL高可用架构设计_第11张图片

                         cd /var/lib/mysql

                         ls

                         ls -lh

                        mysqlbinlog mysql_bin.000002

                        结果如下:

 /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#190407 17:57:26 server id 1  end_log_pos 120 CRC32 0x0c408b63     Start: binlog v 4, server v 5.6.43-log created 190407 17:57:26
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
hsmpXA8BAAAAdAAAAHgAAAABAAQANS42LjQzLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAWOL
QAw=
'/*!*/;
# at 120
#190407 18:01:25 server id 1  end_log_pos 211 CRC32 0xed57a432     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631285/*!*/;
SET @@session.pseudo_thread_id=3/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;

create database crn
/*!*/;
# at 211
#190407 18:02:03 server id 1  end_log_pos 321 CRC32 0xb6e6b07a     Query    thread_id=3    exec_time=0    error_code=0
use `crn`/*!*/;
SET TIMESTAMP=1554631323/*!*/;

create table t(id int, c1 varchar(10))
/*!*/;
# at 321
#190407 18:02:26 server id 1  end_log_pos 398 CRC32 0x133c4114     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631346/*!*/;
BEGIN
/*!*/;
# at 398
#190407 18:02:26 server id 1  end_log_pos 499 CRC32 0x904a8f21     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631346/*!*/;

insert into t values(1, "aa")
/*!*/;
# at 499
#190407 18:02:26 server id 1  end_log_pos 530 CRC32 0x0c153acd     Xid = 18
COMMIT/*!*/;
# at 530
#190407 18:02:36 server id 1  end_log_pos 607 CRC32 0x4215eb14     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631356/*!*/;
BEGIN
/*!*/;
# at 607
#190407 18:02:36 server id 1  end_log_pos 708 CRC32 0x9f885b6e     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631356/*!*/;

insert into t values(2, "bb")
/*!*/;
# at 708
#190407 18:02:36 server id 1  end_log_pos 739 CRC32 0x4a770ccf     Xid = 19
COMMIT/*!*/;
# at 739
#190407 18:03:01 server id 1  end_log_pos 816 CRC32 0x7f805ee1     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631381/*!*/;
BEGIN
/*!*/;
# at 816
#190407 18:03:01 server id 1  end_log_pos 919 CRC32 0x40f307a8     Query    thread_id=3    exec_time=0    error_code=0
SET TIMESTAMP=1554631381/*!*/;

update t set c1="dd" where id=1
/*!*/;
# at 919
#190407 18:03:01 server id 1  end_log_pos 950 CRC32 0x8cc849d7     Xid = 20
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

 

        (2) 基于行的日志格式 binlog_format=ROW

            Row格式可以避免MySQL复制中出现的主从不一致问题。

            同一SQL语句修改了10000条数据的情况下,基于段的日志格式只会记录这个SQL语句,基于行的日志会有10000条记录分别记录每一行的数据修改。

            a、优点:

                . 使用MySQL主从复制更加安全;

                . 对每一行数据的修改比基于段的复制高效;
                . 误操作而修改了数据库中的数据,同时又没有备份可以恢复时,我们就可以通过分析二进制日志,对日志中记录的数据修改操作做反向处理的方式来达到恢复数据的目的。

            b、缺点:

                binlog_row_image = [ FULL | MINIMAL | NOBLOB ]
                    FULL:数据修改时,记录一行数据所有列的内容,无论这些列是否被修改过。比如我们的表中有20列,只对其中的一列进行了update操作,则二进制日志文件中会记录一行中20列数据修改的前后值。

                        use crn;

                        show tables;

                        select * from t;

                        alter table t add c2 text;

                        select * from t;

                        insert into t values(3, 'ee', 'bbb');

                        delete from t where id=1;

                        MySQL高可用架构设计_第12张图片

                        cd /var/lib/mysql

                        ls -lh

                        MySQL高可用架构设计_第13张图片

                        mysqlbinlog -vv mysql_bin.000003 | more

                        MySQL高可用架构设计_第14张图片

                        日志内容如下:

*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#190407 19:23:27 server id 1  end_log_pos 120 CRC32 0x0a724dd7     Start: binlog v 4, server v 5.6.43-log created 190407 19:23:27
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
r92pXA8BAAAAdAAAAHgAAAABAAQANS42LjQzLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAddN
cgo=
'/*!*/;
# at 120
#190407 19:25:20 server id 1  end_log_pos 217 CRC32 0x7157bca0     Query    thread_id=4    exec_time=0    error_code=0
use `crn`/*!*/;
SET TIMESTAMP=1554636320/*!*/;
SET @@session.pseudo_thread_id=4/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;

alter table t add c2 text
/*!*/;
# at 217
#190407 19:26:09 server id 1  end_log_pos 288 CRC32 0x6ae33d7e     Query    thread_id=4    exec_time=0    error_code=0
SET TIMESTAMP=1554636369/*!*/;
BEGIN
/*!*/;
# at 288
#190407 19:26:09 server id 1  end_log_pos 336 CRC32 0xeee69bdd     Table_map: `crn`.`t` mapped to number 71
# at 336
#190407 19:26:09 server id 1  end_log_pos 384 CRC32 0x3a5e9257     Write_rows: table id 71 flags: STMT_END_F

BINLOG '
Ud6pXBMBAAAAMAAAAFABAAAAAEcAAAAAAAEAA2NybgABdAADAw/8AwoAAgfdm+bu
Ud6pXB4BAAAAMAAAAIABAAAAAEcAAAAAAAEAAgAD//gDAAAAAmVlAwBiYmJXkl46
'/*!*/;

### INSERT INTO `crn`.`t`
### SET
###   @1=3 /* INT meta=0 nullable=1 is_null=0 */
###   @2='ee' /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3='bbb' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */

# at 384
#190407 19:26:09 server id 1  end_log_pos 415 CRC32 0xeedfcb20     Xid = 41
COMMIT/*!*/;
# at 415
#190407 19:26:22 server id 1  end_log_pos 486 CRC32 0x718ef806     Query    thread_id=4    exec_time=0    error_code=0
SET TIMESTAMP=1554636382/*!*/;
BEGIN
/*!*/;
# at 486
#190407 19:26:22 server id 1  end_log_pos 534 CRC32 0xdfe7989e     Table_map: `crn`.`t` mapped to number 71
# at 534
#190407 19:26:22 server id 1  end_log_pos 577 CRC32 0xe6b04b94     Delete_rows: table id 71 flags: STMT_END_F

BINLOG '
Xt6pXBMBAAAAMAAAABYCAAAAAEcAAAAAAAEAA2NybgABdAADAw/8AwoAAgeemOff
Xt6pXCABAAAAKwAAAEECAAAAAEcAAAAAAAEAAgAD//wBAAAAAmRklEuw5g==
'/*!*/;

### DELETE FROM `crn`.`t`
### WHERE
###   @1=1 /* INT meta=0 nullable=1 is_null=0 */
###   @2='dd' /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=NULL /* VARSTRING(10) meta=2 nullable=1 is_null=1 */

# at 577
#190407 19:26:22 server id 1  end_log_pos 608 CRC32 0xf245d850     Xid = 42
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

                    MINIMAL:数据修改时,只记录被修改的列。比如我们的表中有20列,只对其中的一列进行了update操作,则二进制日志文件中只会记录一行中这一列数据修改的前后值。

                        set session binlog_row_image=minimal;

                        update t set c2='this 2' where id=2;

                        MySQL高可用架构设计_第15张图片

                        mysqlbinlog -vv mysql_bin.000003 | more

                        MySQL高可用架构设计_第16张图片

                    NOBLOB: :类似于FULL,不同支出在于若没有对TEXT()、BLOB()类型的列数据进行update操作的话,二进制日志文件中就不会记录TEXT()、BLOB()类型的列数据修改的前后值。

                        set session binlog_row_image=noblob;

                        select * from t;

                        update t set c1='fff' where id=3;

                        MySQL高可用架构设计_第17张图片

                        mysqlbinlog -vv mysql_bin.000003 | more

                        MySQL高可用架构设计_第18张图片

                        

        (3) 混合日志格式 binlog_format=MIXED     

            特点:

                . 根据SQL语句由系统决定在基于段和基于行的日志格式中进行选择;

                . 数据量的大小由锁执行的SQL语句决定。                  

                        

    2、如何选择二进制日志的格式

        建议:

            Binlog_format=mixed

            or

            Binlog_format=row

            Binlog_row_image=minimal

 

三、MySQL二进制日志格式对复制的影响

   1、 基于SQL语句的复制(SBR

        二进制日志格式使用的是statement格式

        优点:

            . 生成的日志量少,节约网络传输I/O;

            . 并不强制要求主从数据库的表定义完全相同;

            . 相比于基于行的复制方式更为灵活。     

        缺点:

            . 对于非确定性事件,无法保证主从复制数据的一致性;

            . 对于存储过程,触发器,自定义函数进行的修改也可能造成数据不一致;

            . 相比于基于行的复制方式在从服务器上执行时需要更多的行锁。

   2、基于行的复制(RBR)

        二进制日志格式使用的是基于行的日志格式,对主从数据的一致性更加又保证。

        优点:

            . 可以应用于任何SQL的复制包括非确定函数,存储过程等;

            . 可以减少数据库锁的使用。

                insert into order_cnt(timestr, total, amount) select date(order_date), count(*), sum(amount) from order group by date(order_date);       

                从服务器上不需要对order表整个表进行锁定,只需要同步order_cut表增加的数据列。

        缺点:

            . 要求主从数据库的表结构相同,否则可能会中断复制;

            . 无法在从服务器上单独执行触发器。

    3、混合模式

        根据实际内容在以上两者间切换

 

四、MySQL复制工作方式

    MySQL高可用架构设计_第19张图片

    1、主服务器将变更写入二进制日志;

    2、从服务器读取主服务器的二进制变更并写入到relay_log中;

    3、在从服务器上重放relay_log中的日志。

    基于SQL段的日志是在从库上重新执行记录的SQL

    基于行的日志则是在从库上直接应用对数据库行的修改

 

十、什么是高可用架构

    1、什么是高可用?

        高可用性H.A.(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统奔溃(非计划)所导致的停机时间,以提高系统和应用的可用性。

        (365 * 24 * 60) * (1 - 0.99999) = 5.256

        现实中需要结合业务和成本来选择可用性的级别。

    2、如何实现高可用?

        (1) 避免导致系统不可用的因素,减少系统不可用的时间;

            导致系统不可用的因素:服务器磁盘空间耗尽、性能糟糕的SQL、表结构和索引没有优化、主从数据不一致、人为的操作失误等。

                MySQL高可用架构设计_第20张图片

            . 建立完善的监控及报警系统

            . 对备份数据进行回复测试

            . 正确配置数据库环境

            . 对不需要的数据进行归档和清理

        (2) 增加系统冗余,保证发生系统不可用时可以尽快恢复

            . 避免存在单点故障

            . 主从切换及故障转移

            a、如何解决MySQL单点故障?

                单点故障:单点故障是指在一个系统中提供相同功能的组件只有一个,如果这个组件失效了,就会影响整个系统功能的正常使用。组成应用系统的各个组件都有可能成为单点。

                . 利用SUN共享存储或DRDB磁盘复制解决MySQL单点故障;

                    SUN共享存储:

                        在使用共享存储时,两台服务器能够正常的挂载相同的文件系统,但是只有一条服务器能对其进行操作。如果当前进行处理的服务器宕机了,那么备用的服务器就可以继续挂载文件系统,执行需要的恢复操作,并在失效的服务器的数据上启用MySQL服务。

                    MySQL高可用架构设计_第21张图片

                    DRDB磁盘复制:

                        MySQL高可用架构设计_第22张图片

                . 利用多写集群或NDB集群来解决MySQL单点故障

                    多写集群:

                        目前比较常用的为Percona公司提出的pxc集群。

                            MySQL高可用架构设计_第23张图片                    

                        对于pxc集群中,对于一个事物,只有集群中的所有服务器全部提交后,事物才能被提交。如果集群中的一台服务器不能提交事务,那么所在的集群中的服务器都会对这个事物进行回滚操作。从这一点上可以看出,pxc集群的性能实际上是取决于集群中性能最差的那台服务器的性能。

                        pxc集群优点:

                            集群中所有服务器的性能都是同步的,不存在数据的延迟问题,集群中的任意一台服务器损坏,都不会造成单点损坏问题。

                        pxc集群的缺点:

                            由于pxc集群的性能实际上是取决于集群中性能最差的那台服务器的性能。就算是集群中所有服务器的性能都是一样的,在使用pxc集群时,MySQL的写入性能都会比单台MySQL的写入性能要差。

                            pxc集群只支持Innodb存储引擎,如果我们的服务器中还使用了其他的存储引擎,就不能使用pxc集群。   

                    NDB集群:

                        优点:

                            在NDB集群中,所有的节点都会同步的进行主主复制,也就是说我们可以在任何节点上写入。在NDB集群中,所有的节点都具有相同的读写能力,并且每一行数据都是冗余存储的因此就算是一个节点损坏,也不会丢失数据。

                        缺点:

                            NDB集群中所有的数据都要求存储在内存中,如果内存不足,NDB集群的性能就会非常的差。   

                . 利用MySQL主从复制来解决MySQL单点故障

                    如何解决祝福期的单点问题?

                        主服务器切换后,如何通知应用新的主服务器的IP地址?

                        如何检查MySQL主服务器是否可用?

                        如何处理从服务器和新主服务器之间的那种复制关系?                                  

你可能感兴趣的:(mysql)