MySQL-读写分离
介绍
读写分离目的
-
数据库负载均衡
当数据库请求增多时,单例数据库不能够满足业务需求。需要进行数据库实例的扩容。多台数据库同时相应请求。也就是说需要对数据库的请求,进行负载均衡
但是由于数据库服务特殊原因,数据库扩容基本要求为:数据的一致性和完整性。所以要保证多台数据库实例的数据一致性和完整性,以MySQL为例来说,官方提供了主从复制机制
-
读写分离
数据库的负载均衡不同于其他服务的负载均衡,数据要求一致性。在主从复制的基础上,常见的数据库负载均衡使用的是读写分离方式。写入到主数据库,在从数据库读取。
-
数据库读写分离,是一种特殊的负载均衡实现
实际业务中,读写分离的实时性不高,对于要求实时性高的业务,可通过以下方式实现:
- 读主(不常见)
- 读取缓存:先写入主库,在写入缓存,最后读取缓存
- 弹出提示信息:等待跳转(5s)|数据正在审核中
实现方式
业务代码直接实现读写分离
- 需要在业务代码中,判断数据操作是读还是写,读连接从数据库服务器操作,写连接主数据库服务器操作。以LNMP为例,可以通过PHP代码实现读写分离
- 特点:操作方便,成本低
中间件代理实现读写分离
- 在业务代码中,数据库的操作,不直接连接数据库,而是先请求到中间件服务器(代理服务器),由代理服务器,判断是读操作去从数据服务器,写操作去主数据服务器
- 特点:除了能够实现读写分离,还可以作为数据库集群的管理平台
- 常见如下
代理中间件 | 说明 |
---|---|
MySQL Proxy | MySQL官方 测试版 不再维护 |
Atlas | 奇虎360 基于MySQL Proxy https://github.com/Qihoo360/Atlas |
DBProxy | 美团点评 |
Amoeba | 早期阿里巴巴 |
cobar | 阿里巴巴 |
MyCat | 基于阿里的Cobar 开源 |
kingshared | go语言开发https://github.com/flike/kingshard |
proxysql | http://www.proxysql.com/ |
读写分离实现
主从复制搭建
- 主从复制原理:主服务器开启bin-log,记录写操作。从服务器获取到主服务器的bin-log ,记录到relay-log中。从服务器在通过异步的线程方式,基于relay-log进行数据重演。
虚拟机 | 主机名 | IP地址 |
---|---|---|
server03 | mysql1.master | 192.168.139.130 |
server06 | mysql2.slave | 192.168.139.133 |
- 基于server03克隆server06
- 基本环境配置
vim /etc/sysconfig/network
vim /etc/sysconfig/network-scripts/ifcfg-eth
cd /etc/udev/rules.d/
rm -rf 70-persistent-net.rules
reboot
cat >> /etc/hosts <<EOF
192.168.139.130 mysql1.master
192.168.139.133 mysql2.slave
EOF
- master配置
添加专门用于主从复制的用户
[root@mysql1 ~]# mysql -uroot -p123456
mysql> grant replication slave on *.* to 'slave'@'192.168.139.%'identified by '123456';
mysql> select * from mysql.user\G
开启二进制日志
[root@mysql1 ~]# vim /etc/my.cnf
7 [mysqld]
15 log_bin = mysql-index
21 server_id = 1
[root@mysql1 ~]# cd /usr/local/mysql/data
[root@mysql1 data]# service mysqld restart
[root@mysql1 data]# ls
mysql-index.000001
导出数据库,确保主从开始数据一致(由于从数据库是克隆主数据库的,可不做此步骤)
[root@mysql1 ~]# mysqldump -uroot -p'123456' --all-databases > /root/mysql.sql
查看master上bin-log的位置
mysql> show master status;
+--------------------+----------+
| File | Position |
+--------------------+----------+
| mysql-index.000001 | 120 |
+--------------------+----------+
- slave配置
修改server-id(与主不一致)
[root@mysql2 ~]# vim /etc/my.cnf
7 [mysqld]
21 server_id = 2
修改/usr/local/mysql/data/auto.cnf中的server-uuid(与主不一致)
[root@mysql2 ~]# rm -rf /usr/local/mysql/data/auto.cnf
[root@mysql2 ~]# service mysqld restart
主从复制配置
mysql> stop slave;
mysql> change master to
master_host='192.168.139.130',
master_user='slave',
master_password='123456',
master_log_file='mysql-index.000001',
master_log_pos=120;
mysql> start slave;
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.139.130
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-index.000001
Read_Master_Log_Pos: 120
Relay_Log_File: mysql2-relay-bin.000002
Relay_Log_Pos: 285
Relay_Master_Log_File: mysql-index.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
代码实现读写分离
[root@web1 ~]# vim rwbymysqli.php
<?php
//创建类
class Mysql {
//构造方法
//当类被实例化时,会触发此方法
public f