共计 6263 个字符,预计需要花费 16 分钟才能阅读完成。
什么是读写分离
在数据库集群架构中,让主库负责处理事务性查询,而从库只负责处理 select 查询,让两者分工明确达到提高数据库整体读写性能。当然,主数据库另外一个功能就是负责将事务性查询导致的数据变更同步到从库中,也就是写操作。
读写分离的好处
1)分摊服务器压力,提高机器的系统处理效率
读写分离适用于读远比写的场景,如果有一台服务器,当 select 很多时,update 和 delete 会被这些 select 访问中的数据堵塞,等待 select 结束,并发性能并不高,而主从只负责各自的写和读,极大程度的缓解 X 锁和 S 锁争用;
假如我们有 1 主 3 从,不考虑上述 1 中提到的从库单方面设置,假设现在 1 分钟内有 10 条写入,150 条读取。那么,1 主 3 从相当于共计 40 条写入,而读取总数没变,因此平均下来每台服务器承担了 10 条写入和 50 条读取(主库不承担读取操作)。因此,虽然写入没变,但是读取大大分摊了,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了,说白了就是拿机器和带宽换性能;
2)增加冗余,提高服务可用性,当一台数据库服务器宕机后可以调整另外一台从库以最快速度恢复服务
Mycat 原理
Mycat 是一个开源的分布式数据库系统,但是因为数据库一般都有自己的数据库引擎,而 Mycat 并没有属于自己的独有数据库引擎,所有严格意义上说并不能算是一个完整的数据库系统,只能说是一个在应用和数据库之间起桥梁作用的中间件。
在 Mycat 中间件出现之前,MySQL 主从复制集群,如果要实现读写分离,一般是在程序段实现,这样就带来了一个问题,即数据段和程序的耦合度太高,如果数据库的地址发生了改变,那么我的程序也要进行相应的修改,如果数据库不小心挂掉了,则同时也意味着程序的不可用,而对于很多应用来说,并不能接受;
引入 Mycat 中间件能很好地对程序和数据库进行解耦,这样,程序只需关注数据库中间件的地址,而无需知晓底层数据库是如何提供服务的,大量的通用数据聚合、事务、数据源切换等工作都由中间件来处理;
Mycat 中间件的原理是对数据进行分片处理,从原有的一个库,被切分为多个分片数据库,所有的分片数据库集群构成完成的数据库存储,有点类似磁盘阵列中的 RAID0.
Mycat 配置安装
环境准备:保证多实例 /data/3306/ 和 /data/3307 已经实现简单异步主从复制
1)安装 JDK
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
# 注意版本必须 JDK7 或者更高版本
[root@db02 tools]# rpm -ivh jdk-8u91-linux-x64.rpm
Preparing… ########################################### [100%]
1:jdk1.8.0_91 ########################################### [100%]
# 我这里下载的 rpm 包,安装比较方便
2)下载 Mycat
https://github.com/MyCATApache/Mycat-download#
# 这里测试用的是 Mycat-server-1.4-release 版本
解压拷贝到 /application/mycat 目录
3)创建用户
主库,web 用户有增删改查权限
mysql> grant select,update,delete,insert on lilongzi.* to web@’172.16.2.%’ identified
by’123456′;
从库由于只负责读数据,所有 web 只有 select 权限
mysql> grant select on lilongzi.* to web@’172.16.2.%’ identified by ‘123456’;
4)修改配置文件
[root@db02 conf]# vim /application/mycat/conf/server.xml #MyCAT 对外的“虚拟数据库”配置文件
s”>32</property> –>
</system>
<user name=”web”> #web 为主库和分库刚建立的用户
<property name=”password”>123456</property> #用户密码
<property name=”schemas”>lilongzi</property> #数据库名称
</user>
<user name=”web_r”> #web_r 表示只给读权限
<property name=”password”>123456</property>
<property name=”schemas”>lilongzi</property>
<property name=”readOnly”>true</property>
</user>
[root@db02 conf]# vim /application/mycat/conf/server.xml #详细主库及读写分离模式配置文件
<schema name=”lilongzi” checkSQLschema=”false” sqlMaxLimit=”100″
dataNode=”dn1″>
#name= 你的数据库名,添加 dataNode=”dn1″ 表示数据库只在 dn1 上,没有分库
<table name=”test” primaryKey=”ID” type=”global” dataNode=”dn1,dn2,dn3″ />
#table 修改为你的表名,如果有多张表,可以按照这个格式添加
</schema>
<!– <dataNode name=”dn1$0-743″ dataHost=”localhost1″ database=”db$0-743″
/> –>
<dataNode name=”dn1″ dataHost=”localhost1″ database=”lilongzi” />
<dataNode name=”dn2″ dataHost=”localhost1″ database=”lilongzi” />
<dataNode name=”dn3″ dataHost=”localhost1″ database=”lilongzi” />
<dataHost name=”localhost1″ maxCon=”1000″ minCon=”10″ balance=”1″
writeType=”0″ dbType=”mysql” dbDriver=”native” switchType=”1″
slaveThreshold=”100″>
<heartbeat>select user()</heartbeat>
<!– can have multi write hosts –>
<writeHost host=”hostM1″ url=”172.16.2.10:3306″ user=”web”
password=”123456″>
<!– can have multi read hosts –>
<readHost host=”hostS1″ url=”172.16.2.10:3307″ user=”web”
password=”123456″ />
</writeHost>
<!– <writeHost host=”hostM2″ url=”localhost:3316″ user=”root”
password=”123456″/> –>
</dataHost>
这里面,有两个参数需要注意,balance 和 switchType。
其中,balance 指的负载均衡类型,目前的取值有 4 种:
1. balance=”0″, 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
2. balance=”1″,全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。
3. balance=”2″,所有读操作都随机的在 writeHost、readhost 上分发。
4. balance=”3″,所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力
writeType 表示写模式
writeType=”0″,所有的操作发送到配置的第一个 writehost
writeType=”1″,随机发送到配置的所有 writehost
writeType=”2″,不执行写操作
switchType 指的是切换的模式,目前的取值也有 4 种:
1. switchType=’-1′ 表示不自动切换
2. switchType=’1′ 默认值,表示自动切换
3. switchType=’2′ 基于 MySQL 主从同步的状态决定是否切换, 心跳语句为 show slave status
4. switchType=’3’ 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1),心跳语句为 show status like ‘wsrep%’。
5)启动 Mycat
[root@db02 bin]# ./mycat console &
Running Mycat-server…
wrapper | –> Wrapper Started as Console
wrapper | Launching a JVM…
jvm 1 | Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=64M; support was removed in 8.0
jvm 1 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
jvm 1 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
jvm 1 |
jvm 1 | log4j 2016-07-09 06:04:28 [./conf/log4j.xml] load completed.
jvm 1 | MyCAT Server startup successfully. see logs in logs/mycat.log
[root@db02 bin]# lsof -i:{8066,9066}
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 87340 root 46u IPv6 212352 0t0 TCP *:9066 (LISTEN) #虚拟 schema 管理端口
java 87340 root 50u IPv6 212354 0t0 TCP *:8066 (LISTEN) #虚拟 schema 登陆端口
# 能看到这个说明咱们的 Mycat 已经启动成功了
6)接下来我们就要验证一下否真的已经实现读写分离 …
方法:
停掉从库的 SQL 线程,让从库虽然读取到了主库的 binlog,但是不能发起 SQL 线程写入到自己的数据库中,这样我们模拟访问,插入一条数据,在主库中应该能看到新插入的数据,但是模拟访问的客户端却看不到,就说明读写分离成功。
我们在其他主机 A 上模拟 web 用户访问登陆查看数据
[root@m01 ~]# mysql -uweb -p123456 -h172.16.2.10 -P8066 #注意这里使用虚拟 schema 的登陆端口 8066
mysql> show databases;
+———-+
| DATABASE |
+———-+
| lilongzi |
+———-+
1 row in set (0.00 sec)
mysql> use lilongzi;
Database changed
mysql> show tables;
+——————–+
| Tables in lilongzi |
+——————–+
| customer |
| customer_addr |
| employee |
| goods |
| hotnews |
| orders |
| order_items |
| test | #test 为我们改过的表
| travelrecord |
+——————–+
9 rows in set (0.00 sec)
mysql> select * from test;
+—-+——–+
| id | name |
+—-+——–+
| 1 | 小明 |
+—-+——–+
1 row in set (0.00 sec)
我们停掉从库 3307 的 SQL 线程
mysql> stop slave sql_thread;
Query OK, 0 rows affected (0.00 sec)
在主机 A 远程插入一条数据 test
mysql> insert into test values(2,’test2′);
ERROR 1105 (HY000): Duplicate entry ‘2’ for key ‘PRIMARY’
mysql> select * from test;
+—-+——–+
| id | name |
+—-+——–+
| 1 | 小明 | #立马查一下发现是看不到的
+—-+——–+
1 row in set (0.01 sec)
但是在主库上面
mysql> select * from test;
+—-+——–+
| id | name |
+—-+——–+
| 1 | 小明 |
| 2 | test2 | #显示已经写入成功
+—-+——–+
2 rows in set (0.00 sec)
从库这边
mysql> select * from test;
+—-+——–+
| id | name |
+—-+——–+
| 1 | 小明 | #同样看不到
+—-+——–+
1 row in set (0.00 sec)
MyCAT 实现 MySQL 读写分离实践 http://www.linuxidc.com/Linux/2016-01/127957.htm
MyCAT 实现 MySQL 的读写分离 http://www.linuxidc.com/Linux/2016-01/127555.htm
MyCAT ER 分片的验证 http://www.linuxidc.com/Linux/2016-02/128636.htm
LVS+Keepalived 搭建 MyCAT 高可用负载均衡集群 http://www.linuxidc.com/Linux/2016-03/129231.htm
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-07/133518.htm