mysql-replication(主从复制)原理与实现以及实际应用架构上需要考虑的一些问题

mysql_replication(主从复制)简单原理:

将master上更新的操作记录到二进制bin-log里面去,由slaves在读取bin-log日志,到本地的中继日志relay-log,slaves再执行relay-log里的事件

复制过程:

master上开启bin-log功能,使其上面的操作都记录在二进制文件里;
slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。
SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。
此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。

整个复制过程需要三个进程的参与
master:I/O进程
slaves:I/O进程,SQL进程
mysql支持的复制类型:

(1):基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。
一旦发现没法精确复制时, 会自动选着基于行的复制。
(2):基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
(3):混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。

mysql的安装

请参看这篇文章https://boke.wsfnk.com/archives/49.html

实现mysql的主从复制

主master上
vim /etc/my.cnf

[mysqld]
server-id=1     #这个id全局唯一,slaves上的id不能与之冲突
log-bin=mysql-bin   #必须开启二进制日志功能

启动并进入主master

systemctl start mysqld
mysql -uroot -p

mysql> GRANT REPLICATION SLAVE ON *.* to 'fnk'@'%' identified by '123456789';   #创建一个同步账户,用来同步数据用,*.*表示所有数据库,可以单独指明
                    #'fnk'同步账户,'%'授权slave的ip,%表示任一ip,可以指定为具体ip
                    #'7845'是账户密码
    mysql> flush tables with read lock; #锁定数据库,不允许更改任何数据
    mysql> show master status;      #查看状态,这些数据都要记录,一会儿会在slave端用到

从slave上
vim /etc/my.cnf

[mysqld]
server-id=2     #这个id,全局唯一,不能与master,或者其他slaves冲突
log-bin=mysql-bin   #slaves上没有必要开启bin-log功能,当slave作为其他slave的master时除外
#binlog-do-db=databasename1,databasename2      #这个参数是指定需要复制的数据库名字,多个用逗号分开,
                                               #若是不设置这个参数,默认复制主上的所有数据库;
#binlog-ignore-db=databasename1,databasename2  #这个参数是指定不需要复制的数据库名字,用法与上相同,
                                               #这两个参数可以都不用,也可以二用其一

启动并进入从slave

systemctl start mysqld
mysql -uroot -p

mysql> change master to
master_host = '192.168.10.162',
master_user = 'fnk',
master_password = '123456789',
master_log_file = 'mysql-bin.000002',
master_log_pos = 1005;

mysql> slave start;      #启动slave端的复制进程

mysql> show slave status\G  #查看slaves端的I/O进程,与SQL进程

Slave_IO_Running=Yes
Slave_SQL_Running=Yes
是否为YES状态,那就说明主从复制已经配置好了,你可以在主master上执行增,删,改操作,然后查看从slave的内容有无跟着变化
只有当其为yes状态才是ok的,若你发现配置没有问题,但确实NO的状态
这时你应该考虑关闭你系统上的防火墙

注意:主从复制的模式下,实现很简单,但这种机制也很脆弱,如果想重启master,为了数据的一致性,那么请在slave上执行mysql> slave stop;

情景一:在master上已经有一些生产数据了,为了分担读的压力,需要再增加一个slave;问怎么操作
解析:bin-log日志会进行增长轮替,不可能记录了,master上从初始到现在的所有操作,所以
先在主master上创建授权账户,然后锁表,mysql> flush tables with read lock; #锁定数据库,不允许更改任何数据
再将数据从主上导出,并在新的slave上进行导入操作;
后续操作便是,开启mysql的主从复制了
别忘了还要在master上解除锁mysql> UNLOCK TABLES;



既然都用到了mysql的主从复制,那么应该考虑到以下问题了

1:master的写操作,slaves被动的进行一样的操作,保持数据一致性,那么slave是否可以主动的进行写操作?

分析:假设slave可以主动的进行写操作,slave又无法通知master,这样就导致了master和slave数据不一致了。
因此slave不应该进行写操作,至少是slave上涉及到复制的数据库不可以写。实际上,这里已经揭示了读写分离的概念。

2:主从复制中,可以有N个slave,可是这些slave又不能进行写操作,要他们干嘛?

分析:灾备;类似于高可用的功能,一旦master挂了,可以让slave顶上去,同时slave提升为master。 salve可以用来分担°的负载

3:主从复制中有master,slave1,slave2,…等等这么多MYSQL数据库,那比如一个JAVA WEB应用到底应该连接哪个数据库?

insert/delete/update这些更新数据库的操作,用connection(for master)进行操作,(增,删,改,到主上操作
select用connection(for slaves)进行操作。(读查,到从上操作
那我们的应用程序还要完成怎么从slaves选择一个来执行select,例如简单的轮循算法。(读实现负载均衡

这样的设计有两种思路实现:直接在程序里写死,通过一些中间件实现分离。如:mysql-proxy;atlas;cobar;tddl

4:如果mysql proxy , direct , master他们中的某些挂了怎么办?
分析:像这些关键处设置多个

5:当master的二进制日志每产生一个事件,都需要发往slave,如果我们有N个slave,那是发N次,还是只发一次?

如果只发一次,发给了slave-1,那slave-2,slave-3,…它们怎么办?
显 然,应该发N次。实际上,在MYSQL master内部,维护N个线程,每一个线程负责将二进制日志文件发往对应的slave。master既要负责写操作,还的维护N个线程,负担会很重。可 以这样,slave-1是master的从,slave-1又是slave-2,slave-3,…的主,同时slave-1不再负责select。 slave-1将master的复制线程的负担,转移到自己的身上。这就是所谓的级联复制的概念。

6:当一个select发往mysql proxy,可能这次由slave-2响应,下次由slave-3响应,这样的话,就无法利用查询缓存了。

应该找一个共享式的缓存,比如memcache来解决。将slave-2,slave-3,…这些查询的结果都缓存至memcached中。

7:随着应用的日益增长,读操作很多,我们可以扩展slave,但是如果master满足不了写操作了,怎么办呢?

scale on ?更好的服务器? 没有最好的,只有更好的,太贵了。。。
scale out ? 主从复制架构已经满足不了。
可以分库【垂直拆分】,分表【水平拆分】。


数据库层:

高可用(heartbeat+drbd实现单写热备)(mysql_replication双写,双机互备)
主从复制(多slaves向master同步,也可以是级联同步水平扩展)
读写分离(可以是客户端实现,也可以是中间层实现)
读负载均衡(LVS/haproxy)
共享式读缓存(memcached)

声明:本文为原创,作者为 辣条①号,转载时请保留本声明及附带文章链接:https://boke.wsfnk.com/archives/50.html
微信打赏微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者

最后编辑于:2020/2/19作者: 辣条①号

现在在做什么? 接下来打算做什么? 你的目标什么? 期限还有多少? 进度如何?

暂无评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注