数据库主从复制和读写分离
参考文档:
http://www.cnblogs.com/crazylqy/p/5542558.html
http://www.cnblogs.com/gl-developer/p/6170423.html
https://mp.weixin.qq.com/s?__biz=MzAxMTEyOTQ5OQ==&mid=400643724&idx=1&sn=82e5b5ec9e0567abea4cc1d960265d9e#rd
https://www.jianshu.com/p/89ad5129a8b7
在实际的生产环境中,如果把对数据库的读和写操作都放在同一个数据库服务器上来进行,无论从安全性、高可用性还是高并发等各个方面都是不可取的。因此,一般来说都是通过主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力。如下图所示:
主从复制和读写分离的好处:
1. 将读操作和写操作分离到不同的数据库上,避免主服务器出现性能瓶颈;
2. 主服务器进行写操作时,不影响查询应用服务器的查询性能,降低阻塞,提高并发;
3. 数据拥有多个容灾副本,提高数据安全性,同时当主服务器故障时,可立即切换到其他服务器,提高系统可用性;
主从复制
1. MySQL支持的复制类型
- 基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。
- 基于行的复制。把改变的数据复制到从服务器上,而不是把命令在从服务器上执行一遍。
- 混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
2.主从复制的工作过程
a. 在每个事务更新数据完成之前,master在二进制日志记录(binary log)这些改变。写入二进制日志完成后,master通知存储引擎提交事务。
b. Slave将master的binary log复制到其中继日志(Relay log)。首先slave开始一个工作线程(I/O),I/O线程在master上打开一个普通的连接,然后开始binlog dump process。binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件,I/O线程将这些事件写入中继日志。
c. Sql slave thread(sql从线程)处理该过程的最后一步,sql线程从中继日志读取事件,并重放其中的事件而更新slave数据,使其与master中的数据一致,只要该线程与I/O线程保持一致,中继日志通常会位于os缓存中,所以中继日志的开销很小。
整个过程如下图所示:
3. 主从复制的三种方式
- 同步复制:
所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。
这样,显然不可取,也不是MYSQL复制的默认设置。比如,在WEB前端页面上,用户增加了条记录,需要等待很长时间。
- 异步复制:
如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心。这是MYSQL的默认设置。
- 半同步复制:
master只保证slaves中的一个操作成功,就返回,其他slave不管。
这个功能,是由google为MYSQL引入的。
读写分离
读写分离指的是在主服务器上进行修改操作(如insert/delete/update这些更新数据库的操作),从服务器只能提供读取数据(select),不能写入。这样,在实现了备份的同时也实现了数据库性能的优化,以及提升了服务器安全。如下图所示:
目前较为常见的MySQL读写分离分为以下两种:
1. 基于程序代码内部实现
在代码中根据select 、insert进行路由分类,这类方法也是目前生产环境下应用最广泛的。优点是性能较好,因为程序在代码中实现,不需要增加额外的硬件开支,缺点是需要开发人员来实现,运维人员无从下手。
2.基于中间代理层实现
代理一般介于应用服务器和数据库服务器之间,代理数据库服务器接收到应用服务器的请求后根据判断后转发到后端数据库。代理有以下代表性的程序。
- mysql_proxy。mysql_proxy是Mysql的一个开源项目,通过其自带的lua脚本进行sql判断。
- Atlas。是由 Qihoo 360, Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
- Amoeba。由阿里巴巴集团在职员工陈思儒使用序java语言进行开发,阿里巴巴集团将其用户生产环境下,但是他并不支持事物以及存数过程。
经过上述简单的比较,不是所有的应用都能够在基于程序代码中实现读写分离,像一些大型的java应用,如果在程序代码中实现读写分离对代码的改动就较大,所以,像这种应用一般会考虑使用代理层来实现。