Mysql 主从复制原理

jopen 10年前

Mysql 主从复制原理

随着网站业务的不断发展,用户量的不断增加,数据量不断地增长,数据库的访问量也相应的增长,到了一定的时间,网站首先出现的瓶颈就是在数据库层 (这里没有将缓存加入进来),这时候就需要对数据库进行适当的拆分,比如说分库或分表等,如果数据库在分库,分表后还是出现瓶颈,这时就好考虑数据库读写 分离,尤其在读多写少的时候。

mysql中读写分离的方案就是主从复制,master服务器将更新的记录到binary log中,mysql中这个叫二进制日志事件(binary log events), slaver服务器将master中的binary log events 复制到自己的中继日志(relay log)中,slave服务器将监听中继日志,将中继日志的改变记录到数据库中。下图描述了复制的过程:

Mysql 主从复制原理

 

其中,mysql支持大概3种类型的复制类型:

1.基于语句的复制,(也叫做逻辑复制,logical replication),优点是基于语句的复制的二进制日志可以很好的进行压缩,而且日志的数据量也较小,缺点是基于语句的复制必须是串行化。

2.基于记录的复制(Row-Based Replication),在二进制日志中记录下实际数据的改变,优点就是可以对任何语句都能正确工作,一些语句的效率更高,缺点就是二进制日志会很大,不能使用mysqlbinlog来查看二进制日志.

3.混合类型的复制,默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制.

复制能解决的一些问题:

1.数据分布 (Data distribution )

2.可以实现负载均衡(load balancing),通常所说的读写分离

3.可以实现数据的备份(Backups),但是不能当真正意义上数据备份来用

4.高可用性和容错行(比如双主模型中的互为主从能实现高可用)

但是,主从复制也带来其他一系列其他问题,典型的就是主从不同步,导致主从不同步的原因是 :服务器一般都是多核多线程,导致主节点可以同时执行多条读写操作,而记录二进制日志则必须按顺序有先后的记录,从节点在一条一条复制过去,生成中继日 志,再执行语句,这里就会出现复制延迟。其他问题就是写入无法扩展,锁表率上升等。

复制的体系结构有以下一些基本原则:

(1) 每个slave只能有一个master;

(2) 每个slave只能有一个唯一的服务器ID;

(3) 每个master可以有很多slave;

(4) 如果你设置log_slave_updates,slave可以是其它slave的master,从而扩散master的更新

Mysql复制常见的几种模式:

1.一主多从

由一个master和一个slave组成复制系统是最简单的情况。Slave之间并不相互通信,只能与master进行通信。主要用于读压力比较大的应用的数据库端廉价扩展解决方案。

Mysql 主从复制原理

2.主主复制

Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。这样,任何一方所做的变更,都会通过复制应用到另 外一方的数据库中。在这种复制架构中,各自上运行的不是同一db,比如左边的是db1,右边的是db2,db1的从在右边反之db2的从在左边,两者互为 主从,再辅助一些监控的服务还可以实现一定程度上的高可以用。

Mysql 主从复制原理

3.主动-被动模式(HA)

这种模式由master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中只有一个节点在提供读写服务,另外一个节点时刻准备着,当主节点一旦故障马上接替服务。比如通过corosync+pacemaker+drbd+mysql就可以提供这样一组高可用服务,主备模式下再跟着slave服务器,也可以实现读写分离.

Mysql 主从复制原理

主从复制中容易出现的问题:

1.限制从服务器只读,保证主从数据一致。

show global variables like ‘%read%‘

更改slave的全局服务器变量read_only为on

set global read_only on

从节点上授权只读 set global read_only = 1;如果永久有效更改mysql的my.ini 或my.cnf,在[mysql] 中设置read_only = 1

2.保证主从复制时的事务安全

如果mysql比较繁忙它会把二进制日志缓存在内存中,不繁忙时才会把他写到磁盘中,前提就是mysql对二进制日志事件数据会缓冲。在 master上设置如下参数 set global  sync_binlog = 1 事物一提交,就必须同步二进制日志,这样会降低性能,但是数据非常重要的情况下。