Mysql和Redis的主从对比入门

这是第一篇博客,作为一个刚刚准备踏入架构师的phper,我就是一个小白,看了一天的mysql和redis的主从配置,总结一下一天的所学,文章所有内容均是理论,没有亲身实践过。

Mysql

mysql高可用,MHA架构,这个架构我今天尚未了解,以后补充。
mysql主从很多种。

  1. 一主一从
  2. 一主多从
  3. 多主一从(5.7以后支持)
  4. 双主复制
  5. 级联复制

一·基本信息配置

要想了解主从,必须先了解binlog,mysql-binlog是MySQL数据库的二进制日志,用于记录用户对数据库操作的SQL语句((除了数据查询语句)信息。可以使用mysqlbin命令查看二进制日志的内容。
binlog的格式也有三种:STATEMENT、ROW、MIXED 。

1、STATMENT模式:基于SQL语句的复制(statement-based replication, SBR),每一条会修改数据的sql语句会记录到binlog中。
优点:不需要记录每一条SQL语句与每行的数据变化,这样子binlog的日志也会比较少,减少了磁盘IO,提高性能。
缺点:在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)
2、基于行的复制(row-based replication, RBR):不记录每一条SQL语句的上下文信息,仅需记录哪条数据被修改了,修改成了什么样子了。
优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。
缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨。
3、混合模式复制(mixed-based replication, MBR):以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

企业场景如何选择binlog的模式
1、 如果生产中使用MySQL的特殊功能相对少(存储过程、触发器、函数)。选择默认的语句模式,Statement Level。
2、 如果生产中使用MySQL的特殊功能较多的,可以选择Mixed模式。
3、 如果生产中使用MySQL的特殊功能较多,又希望数据最大化一致,此时最好Row level模式;但是要注意,该模式的binlog非常“沉重”。

在MySQL配置文件my.cnf文件中的mysqld节中添加下面的配置文件:

vim my.cnf(在[mysqld]模块中配置)
[mysqld]
log-bin = /data/3306/mysql-bin #这个地方我理解的就是存放binlog的目录,
#在这个目录下面会生成各种00001.log这样的格式,因为有的博客这个地方写的是
#.log文件结尾,感觉应该不对,我没有亲自测试。。。
binlog_format="STATEMENT"
#binlog_format="ROW"
#binlog_format="MIXED"

binlog 简单来说就是记录mysql的行为。下面开始说主从。
假设现在有两台mysql服务器AB,首先要同步两台服务器的基本数据库配置,多少数据库,多少表,有人会问,binlog不是会自动同步的吗,如果是两台崭新的服务器,上面没有任何的数据的,那么完全可以直接配置主从,但更多的场景,线上是单服务器,只有master,需要添加从服务器。

有很多种配置主从同步的方法,可以总结为如下的步骤:

  1. 在主服务器上,必须开启二进制日志机制和配置一个独立的ID
  2. 在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号
  3. 在开始复制进程前,在主服务器上记录二进制文件的位置信息
  4. 如果在开始复制之前,数据库中已经有数据,就必须先创建一个数据快照(可以使用mysqldump导出数据库,或者直接复制数据文件)
  5. 配置从服务器要连接的主服务器的IP地址和登陆授权,二进制日志文件名和位置
1.在主服务器A上进行备份:
mysqldump -uroot -p --all-databases --lock-all-tables > ~/master_db.sql

–all-databases表示备份所有数据库(当恢复时就不需要再创建数据库了)–lock-all-tables表示在备份时对表数据进行上锁,意思是备份期间执行增删改操作需要等待

2. 在从服务器B上进行数据还原

在主服务器中通过scp命令将备份到桌面上的master_db.sql文件推送到从服务器中
在从服务器上执行以下命令

mysql -uroot -p < master.sql

主服务器备份的数据库恢复到从服务器后,此时查看从服务器的数据库中是否存在主服务器数据库中的各种数据库。

3.下面开始在主服务器A上配置信息

编辑设置mysqld的配置文件,设置log_bin和server-id,一般将IP地址尾数设置为server-id得值,必须保证主服务器和从服务器上的server-id的值不能相同
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
这个地方应该是在
[mysqld]
log-bin=XXXX
server-id=222 //[必须]服务器唯一ID,默认是1,一般取IP最后一段
binlog-do-db=需要复制的数据库名,如果复制多个数据库,重复设置这个选项即可
binlog-ignore-db=不需要复制的数据库苦命,如果复制多个数据库,重复设置这个选项即可
配置完后重启服务器

sudo service mysql restart

然后再进入mysql命令行,开始授权
GRANT REPLICATION SLAVE ON . TO ‘slave’@’%’ identified by ‘slave’;
FLUSH PRIVILEGES;

获取主服务器的二进制日志信息
show master status;

Mysql和Redis的主从对比入门_第1张图片
File为使用的日志文件名字,Position为使用的文件位置,这两个参数须记下,配置从服务器时会用到

4.配置从服务器slaveB

如果mysql的版本大于5.5
打开mysql.in添加下面值
server-id=2
    master-host=192.168.1.1 //主数据库的ip
    master-user=mstest   //第一步创建账号的用户名
    master-password=123456 //第一步创建账号的密码
    master-port=3306
    master-connect-retry=60
    replicate-do-db=czc //要同步的mstest数据库,要同步多个数据库,就多加几个replicate-db-db=数据库名
mysql的版本小于5.5
打开mysql.ini添加一个server_id,随便写一个不重复的id,从服务器中的 binlog = 目录,等各种参数可以完全注释,也算是一种优化。

因为小于5.5的不能使用直接配置的方法,只能采用命令行的方式配置
change master to master_host=‘192.168.4.63’, master_user=‘slave’, master_password=‘slave’,master_log_file=‘mysql-bin.000007’, master_log_pos=600; 其中的参数就是之前的授权和status里面的信息。

开启同步
slave start;
show slave status\G; 看信息
Mysql和Redis的主从对比入门_第2张图片
Master_Log_File: SLAVE中的I/O线程当前正在读取的主服务器二进制日志文件的名称
Read_Master_Log_Pos: 在当前的主服务器二进制日志中,SLAVE中的I/O线程已经读取的位置
Relay_Log_File: SQL线程当前正在读取和执行的中继日志文件的名称
Relay_Log_Pos: 在当前的中继日志中,SQL线程已读取和执行的位置
Relay_Master_Log_File: 由SQL线程执行的包含多数近期事件的主服务器二进制日志文件的名称
Slave_IO_Running: I/O线程是否被启动并成功地连接到主服务器上
Slave_SQL_Running: SQL线程是否被启动
Seconds_Behind_Master: 从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。

看这几项是否出现,出现表示成功了。可自行在主数据库里面添加修改数据测试

很多博客在这里就结束,确实 这样的话,主从就已经配置完了,那么主从配置完了,主从之间是如何同步的??主从延迟又是怎么来的,怎么解决主从延迟呢???下面我来继续解决

二.主从同步的问题

先说一下主从同步的原理。
MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL thread)运行在从节点,对于每一个主从连接,都需要三个进程来完成。当主节点有多个从节点时,主节点会为每一个当前连接的从节点建一个binary log dump 进程,而每个从节点都有自己的I/O进程,SQL进程。从节点用两个线程将从主库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。

1.在master机器上的操作:
当master上的数据发生变化时,该事件变化会按照顺序写入bin-log中。当slave链接到master的时候,master机器会为slave开启binlog dump线程。当master的binlog发生变化的时候,bin-log dump线程会通知slave,并将相应的binlog内容发送给slave。
2.在slave机器上操作
当主从同步开启的时候,slave上会创建两个线程:I\O线程。该线程连接到master机器,master机器上的binlog dump 线程会将binlog的内容发送给该I\O线程。该I/O线程接收到binlog内容后,再将内容写入到本地的relay log;sql线程。该线程读取到I/O线程写入的ralay log。并且根据relay log。并且根据relay log 的内容对slave数据库做相应的操作。

i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中;
主库会生成一个 log dump 线程,用来给从库 i/o线程传binlog;
SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;

从节点上的I/O 进程连接主节点,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

主节点接收到来自从节点的I/O请求后,通过负责复制的I/O进程根据请求信息读取指定日志指定位置之后的日志信息,返回给从节点。返回信息中除了日志所包含的信息之外,还包括本次返回的信息的bin-log file 的以及bin-log position;从节点的I/O进程接收到内容后,将接收到的日志内容更新到本机的relay log中,并将读取到的binary log文件名和位置保存到master-info 文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log 的哪个位置开始往后的日志内容,请发给我”;

Slave 的 SQL线程检测到relay-log 中新增加了内容后,会将relay-log的内容解析成在祝节点上实际执行过的操作,并在本数据库中执行。

所以这个地方我的理解是,主服务器修改binlog日志,然后通知slave,然后从服务器的i/o线程去请求主库的binlog,并且更新的操作。

这里还有一个知识点,就是关于主从同步的模式问题,异步模式,半同步模式,全同步模式,GTID复制模式,链接: https://baijiahao.baidu.com/s?id=1617888740370098866&wfr=spider&for=pc

写了这么多,那么开始步入整体,主从延迟的产生和处理方式。

从库同步延迟情况出现的
● show slave status显示参数Seconds_Behind_Master不为0,这个数值可能会很大
● show slave status显示参数Relay_Master_Log_File和Master_Log_File显示bin-log的编号相差很大,说明bin-log在从库上没有及时同步,所以近期执行的bin-log和当前IO线程所读的bin-log相差很大
● mysql的从库数据目录下存在大量mysql-relay-log日志,该日志同步完成之后就会被系统自动删除,存在大量日志,说明主从同步延迟很厉害

1)、MySQL数据库主从同步延迟原理mysql主从同步原理:主库针对写操作,顺序写binlog,从库单线程去主库顺序读”写操作的binlog”,从库取到binlog在本地原样执行(随机写),来保证主从数据逻辑上一致。mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生binlog,binlog是顺序写,所以效率很高,slave的Slave_IO_Running线程到主库取日志,效率比较高,下一步,问题来了,slave的Slave_SQL_Running线程将主库的DDL和DML操作在slave实施。DML和DDL的IO操作是随即的,不是顺序的,成本高很多,还可能可slave上的其他查询产生lock争用,由于Slave_SQL_Running也是单线程的,所以一个DDL卡主了,需要执行10分钟,那么所有之后的DDL会等待这个DDL执行完才会继续执行,这就导致了延时。有朋友会问:“主库上那个相同的DDL也需要执行10分,为什么slave会延时?”,答案是master可以并发,Slave_SQL_Running线程却不可以。

2)、MySQL数据库主从同步延迟是怎么产生的?当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。首要原因:数据库在业务上读写压力太大,CPU计算负荷大,网卡负荷大,硬盘随机IO太高次要原因:读写binlog带来的性能影响,网络传输延迟。当主库的并发较高时,产生的DML数量超过slave的SQL Thread所能处理的速度,

(3)、MySql数据库从库同步的延迟解决方案
1)、架构方面

1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。

2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。

3.服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力。

4.不同业务的mysql物理上放在不同机器,分散压力。

5.使用比主库更好的硬件设备作为slave总结,mysql压力小,延迟自然会变小。

2)、硬件方面

1.采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。

2.存储用ssd或者盘阵或者san,提升随机写的性能。

3.主从间保证处在同一个交换机下面,并且是万兆环境。

总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。

3)、mysql主从同步加速

1、sync_binlog在slave端设置为0

2、–logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。

3、直接禁用slave端的binlog

4、slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit =2

4)、MySql数据库从库同步其他问题及解决方案

1)、mysql主从复制存在的问题: ● 主库宕机后,数据可能丢失 ● 从库只有一个sql Thread,主库写压力大,复制很可能延时2)、解决方法: ● 半同步复制—解决数据丢失的问题 ● 并行复制----解决从库复制延迟的问题

3)、半同步复制mysql semi-sync(半同步复制)半同步复制: ● 5.5集成到mysql,以插件的形式存在,需要单独安装 ● 确保事务提交后binlog至少传输到一个从库 ● 不保证从库应用完这个事务的binlog ● 性能有一定的降低,响应时间会更长 ● 网络异常或从库宕机,卡主主库,直到超时或从库恢复4)、主从复制–异步复制原理、半同步复制和并行复制原理比较

所以主从同步的延迟 跟模式的选择也有很大关系。
————————————————
感谢各位博主:

链接: https://www.jianshu.com/p/8b95dba5b191.
链接: https://baijiahao.baidu.com/s?id=1617888740370098866&wfr=spider&for=pc.
链接: https://blog.csdn.net/hao_yunfeng/article/details/82392261.
链接: https://www.jianshu.com/p/8b95dba5b191.
链接: link.
链接: link.

你可能感兴趣的:(myql)