目录
一、mysql-proxy实现读写分离
二、MYCAT介绍
三、MYCAT分表分库
mysql-proxy 实现读写分离
较为常见的Mysql读写分离分为以下两种
1)基于程序代码内部实现
在代码中根据select 、insert进行路由分类,这类方法也是目前生产环境下应用最广泛的。优点是性能较好,因为程序在代码中实现,不需要增加额外的硬件开支,缺点是需要开发人员来实现,运维人员无从下手。
2) 基于中间代理层实现
代理一般介于应用服务器和数据库服务器之间,代理数据库服务器接收到应用服务器的请求后根据判断后转发到,后端数据库,有以下代表性的程序。
![abc81f6f6a2db227d8f834faf95dd830186.jpg](https://i-blog.csdnimg.cn/blog_migrate/0857a354a9bcecdb4bb2b27a20dcb05d.jpeg)
(1)mysql_proxy。mysql_proxy是Mysql的一个开源项目,通过其自带的lua脚本进行sql判断。
(2)Atlas。是由 Qihoo 360, Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程。
MySQLProxy介绍
下面使用MySQL官方提供的数据库代理层产品MySQLProxy搭建读写分离。
MySQLProxy实际上是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy,然后经由MySQLProxy进行相应的分析,判断出是读操作还是写操作,分发至对应的MySQLServer上。对于多节点Slave集群,也可以起做到负载均衡的效果。
mysql主服务器 Master:172.25.17.19
mysql从服务器 Slave1:
172.25.17.20
mysql从服务器 Slave2:
172.25.17.21
调度服务器 MySQL-Proxy:
172.25.17.7
1、安装 mysql-proxy
实现读写分离是有 lua 脚本实现的,现在 mysql-proxy 里面已经集成,无需再安装
[root
@proxy ~]# rpm -ivh mysql-proxy-0.8.1-1.el6.x86_64.rpm
2、将rw-splitting.lua 脚本复制到/lib 下
[root
@proxy ~]# cp rw-splitting.lua /lib
3、修改mysql-proxy主配置文件/etc/sysconfig/mysql-proxy
ADMIN_USER="proxy" #主从 mysql 共有的用户
ADMIN_PASSWORD
=
"123456"
#用户的密码
ADMIN_LUA_SCRIPT
=
"/lib/rw-splitting.lua"
#指定管理脚本
PROXY_USER
=
"root"
#运行 mysql-proxy用户
#添加如下代码:[以下代码需写在一行内]
PROXY_OPTIONS
=
"--proxy-address=172.25.17.7:4040
--proxy-read-only-backend-addresses=172.25.17.20:3306--proxy-read-only-backend-addresses=172.25.17.21:3306--proxy-backend-addresses=172.25.17.19:3306--proxy-lua-script=/lib/rw-splitting.lua
--daemon"
#mysql-proxy 运行 ip 和端口,不加端口,默认 4040
4、修改读写分离配置文件vim /lib/rw-splitting.lua
if
not proxy.global.config.rwsplit
then
proxy.global.config.rwsplit
=
{
min_idle_connections
=
1,
#默认超过 4个连接数时,才开始读写分离,改为 1
max_idle_connections
=
1,
#默认 8,改为1
is_debug
=
false
}
end
#这里的 4 、8 是指定链接数,做测试时调整为 1
5、设置mysql-proxy 开机启动,并启动mysql-proxy
[
root@proxy ~
]
# chkconfig mysql-proxy on
[
root@proxy ~
]
# service mysql-proxy start
[
root@proxy ~
]
# netstat -tnlp | grep mysql-proxy
tcp 0 0 172.25.17.7:4040 0.0.0.0:* LISTEN 27352/mysql-proxy
tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN 27352/mysql-proxy
6、在master数据库授权mysql-proxy访问
[root@
master
~]# mysql -puplooking
grant all on *.* to 'proxy'@'172.25.17.7' identified by '123456';
grant all on *.* to 'proxy'@'rhel6' identified by '123456';
flush privileges;
代理服务器上不用装Mysql
主从同步延迟产生原因
当主库的
TPS
并发较高时,产生的
DDL
数量超过
Slave
一个
sql
线程所能承受的范围,那么延迟就产
生了,当然还有就是可能与
slave
的大型
query
语句产生了锁等待
首要原因:数据库在业务上读写压力太大,
CPU
计算负荷大,网卡负荷大,硬盘随机
IO
太高
次要原因:读写
binlog
带来的性能影响,网络传输延迟
主从同步延迟解决方案
架构方面
1.业务的持久化层的实现采用分库架构,mysql 服务可平行扩展分散压力
2.单个库读写分离,一主多从,主写从读,分散压力。
3.服务的基础架构在业务和 mysql 之间加放 cache 层
4.不同业务的 mysql 放在不同的机器
5.使用比主加更了的硬件设备作 slave
反正就是 mysql 压力变小,延迟自然会变小
硬件方面:
采用好的服务器
mysql 主从同步加速
1、sync_binlog 在 slave 端设置为 0
2、–logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
3、直接禁用 slave 端的 binlog
4、slave 端,如果使用的存储引擎是 innodb,innodb_flush_log_at_trx_commit =2
从文件系统本身属性角度优化
master 端
修改 linux、Unix 文件系统中文件的 etime 属性, 由于每当读文件时 OS 都会将读取操作发生的时间回
写到磁盘上,对于读操作频繁的数据库文件来说这是没必要的,只会增加磁盘系统的负担影响 I/O 性能。
可以 通过设置文件系统的 mount 属性,组织操作系统写 atime 信息,在 linux 上的操作为:
打开/etc/fstab,加上 noatime 参数
/dev/sdb1 /data reiserfs noatime 1 2
然后重新 mount 文件系统
#mount -oremount /data
主库是写,对数据安全性较高,比如 sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之类的设
置是需要的
而 slave 则不需要这么高的数据安全,完全可以讲 sync_binlog 设置为 0 或者关闭
binlog,innodb_flushlog 也可以设置为 0 来提高 sql 的执行效率
1、sync_binlog=1 o
MySQL 提供一个 sync_binlog 参数来控制数据库的 binlog 刷到磁盘上去。
默认,sync_binlog=0,表示 MySQL 不控制 binlog 的刷新,由文件系统自己控制它的缓存的刷新。这
时候的性能是最好的,但是风险也是最大的。一旦系统 Crash,在 binlog_cache 中的所有 binlog 信息都
会被丢失。
如 果 sync_binlog>0,表示每 sync_binlog 次事务提交,MySQL 调用文件系统的刷新操作将缓存刷下
去。最安全的就是 sync_binlog=1 了,表示每次事务提交,MySQL 都会把 binlog 刷下去,是最安全但
是性能损耗最大的设置。这样的话,在数据库所在的主机 操作系统损坏或者突然掉电的情况下,系统才
有可能丢失 1 个事务的数据。
但是 binlog 虽然是顺序 IO,但是设置 sync_binlog=1,多个事务同时提交,同样很大的影响 MySQL
和 IO 性能。
虽然可以通过 group commit 的补丁缓解,但是刷新的频率过高对 IO 的影响也非常大。对于高并发事务
的系统来说,
“sync_binlog”设置为 0 和设置为 1 的系统写入性能差距可能高达 5 倍甚至更多。
所以很多 MySQL DBA 设置的 sync_binlog 并不是最安全的 1,而是 2 或者是 0。这样牺牲一定的一致
性,可以获得更高的并发和性能。
默 认情况下,并不是每次写入时都将 binlog 与硬盘同步。因此如果操作系统或机器(不仅仅是 MySQL
服务器)崩溃,有可能 binlog 中最后的语句丢失 了。要想防止这种情况,你可以使用 sync_binlog 全局
变量(1 是最安全的值,但也是最慢的),使 binlog 在每 N 次 binlog 写入后与硬盘同 步。即使
sync_binlog 设置为 1,出现崩溃时,也有可能表内容和 binlog 内容之间存在不一致性。
2、innodb_flush_log_at_trx_commit (这个很管用)
抱怨 Innodb 比 MyISAM 慢 100 倍?那么你大概是忘了调整这个值。默认值 1 的意思是每一次事务提交
或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。特别是使用电 池供电缓存(Battery
backed up cache)时。设成 2 对于很多运用,特别是从 MyISAM 表转过来的是可以的,它的意思是不
写入硬盘而是写入系统缓存。
日志仍然会每秒 flush 到硬 盘,所以你一般不会丢失超过 1-2 秒的更新。设成 0 会更快一点,但安全方
面比较差,即使 MySQL 挂了也可能会丢失事务的数据。而值 2 只会在整个操作系统 挂了时才可能丢数
据。
3.
进行分库分表处理,这样减少数据量的复制同步操作
1、MYCAT的起源
阿里巴巴在2008年推出了Amoeba,当时正好是在阿里去IOE的浪潮中,Amoeba提供了负载均衡,SQL过滤等功能,在2012年随着阿里业务量增长,Amoeba也越来越不适应当时不断增长的需求,同年在Amoeba的基础上阿里开源了替代Amoeba的产品Cobar,不过后来就没进行维护了,Cobar本身也存在不少问题,在2013年阿里推出了开源产品MYCAT,MYCAT在Cobar系统的基础上进行了升级和改造,修复了很多问题(例如在高并发下回导致Cobar假死),同时开源社区非常活跃,在2017年,MYCAT推出了1.6版本。
2、什么是MYCAT?
MYCAT是基于Java的一个分布式数据库系统中间层,为高并发下数据库的分布式提供解决方案。
3、MYCAT的主要作用是什么?
数据库中间层是位于前端应用和后端数据库之间的一个层。
-
传统Java项目使用数据库连接池的形式连接数据库,这样多个项目连接同一个数据库,冗余的连接会随着项目的增加而出现线性增长,这不利于数据库连接数量的控制,但是当使用中间层之后,前端应用统一通过中间层获取连接,将不用自己维护连接池,可避免连接数不断增加的问题。
-
数据库中间层还可以屏蔽后端数据库的一些变更,使前台应用不受影响,例如对数据库进行了水平或者垂直切分。
-
MYCAT原生实现了对MySQL的支持,也可以通过jdbc形式连接其它关系型数据库 如 Oracle,Sqlserver,也可以连接非关系型数据库 如 mongodb,这个功能其他同类型产品没有。
-
可实现数据库的读写分离,在后端的主从复制数据库集群中,通过MYCAT配置,将前台的写操作路由到主数据库中,将读操作路由到从数据库上。
-
MYCAT可以实现读写分离下的读操作负载均衡,将大量的读操作均衡到不同的从库上,主要出现在一主多从情形下。
-
MYCAT可实现数据库的高可用,在数据库主节点可用的情况下,配置一台可写从节点,这两个节点都配置在MYCAT中,当主节点宕机时,MyCAT会自动将写操作路由到备用节点上,但并不支持在切换之后的继续主从同步。
-
当读写分离已经不能满足持续增加的访问量时,MYCAT可实现数据库的垂直拆分,将所有的数据库表按照模块划分,不同类型的表拆分到不同的数据库服务器。
-
随着业务量的增长,垂直拆分之后如果又出现了数据库性能问题,则需要进行水平切分,这就是俗称的分库分表。将数据量很大的表数据切分到不同的服务器库中,表结构是一样的,而使用MYCAT实现水平切分,对前端应用是完全透明的,不用调整前台逻辑。
4、MYCAT使用场景
当业务系统的读写操作都在一台数据库,数据库出现了性能问题,而且对数据库的所有操作中读负载明显高于写负载时,此时应使用MYCAT读写分离方案。
当数据表数据量达到1000万以后,所有的优化操作都已经用完了,此时应使用MYCAT的分库分表功能。
在统计报表系统中,也可以使用MYCAT加速数据的统计分析。
MYCAT还可以使用在需要同时查询多种数据库的场景,MYCAT支持通过JDBC连接到不同类型的数据库。
5、MYCAT的优势
MYCAT是基于阿里巴巴Cobar进行开发,经历了Alibaba大数据业务的考验。
MYCAT是基于Java进行开发,开源免费,资料文档相对容易找到,跨平台移植更方便。
MYCAT社区活跃,使用人数多,说明功能相对稳定。
支持多种关系型和非关系性数据库。
6、MYCAT 其他概念
逻辑库,逻辑库是存在于MYCAT中的一个数据库定义,相当于后端数据库分片之后的一个集合视图,前端应用只需要关注逻辑库而并不需要关注它的分片结构,MYCAT会保存逻辑库的定义,而不会保存逻辑库数据,同理的概念还有逻辑表,数据库表进行水平切分后分布在不同的服务器中,前端应用只需要对逻辑表进行操作。
ER关系分片策略,在进行数据库表的垂直切分时,MYCAT可按照ER关系,将相互关联的表切分到相同的数据库中,提升查询效率。
全局序列号,数据库分片之后,相同的表可能产生相同的ID,全局序列号可是提供跨分片的序列号。
安装
可以了解下Mycat的背景和应用情况,这样使用起来比较有信心。
官网有个文档,属于详细的介绍,初次入门,看起来比较花时间。
下载:
建议大家选择 1.6-RELEASE 版本,毕竟是比较稳定的版本。
安装:
根据不同的系统选择不同的版本。包括linux、windows、mac,作者考虑还是非常周全的,当然,也有源码版的。(ps:源码版的下载后,只要配置正确,就可以正常运行调试,这个赞一下。)
Mycat的安装其实只要解压下载的目录就可以了,非常简单。
安装完成后,目录如下:
目录
|
说明
|
bin
|
mycat命令,启动、重启、停止等
|
catlet
|
catlet为Mycat的一个扩展功能
|
conf
|
Mycat 配置信息,重点关注
|
lib
|
Mycat引用的jar包,Mycat是java开发的
|
logs
|
日志文件,包括Mycat启动的日志和运行的日志。
|
配置
Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:
文件
|
说明
|
server.xml
|
Mycat的配置文件,设置账号、参数等
|
schema.xml
|
Mycat对应的物理数据库和数据库表的配置
|
rule.xml
|
Mycat分片(分库分表)规则
|
Mycat的架构其实很好理解,Mycat是代理,Mycat后面就是物理数据库。和Web服务器的Nginx类似。对于使用者来说,访问的都是Mycat,不会接触到后端的数据库。
我们现在做一个主从、读写分离,简单分表的示例。结构如下图:
服务器
|
IP
|
说明
|
Mycat
|
192.168.0.2
|
mycat服务器,连接数据库时,连接此服务器
|
database1
|
192.168.0.3
|
物理数据库1,真正存储数据的数据库
|
database2
|
192.168.0.4
|
物理数据库2,真正存储数据的数据库
|
Mycat作为主数据库中间件,肯定是与代码弱关联的,所以代码是不用修改的,使用Mycat后,连接数据库是不变的,默认端口是8066。连接方式和普通数据库一样,如:jdbc:
mysql://192.168.0.2:8066/
server.xml
示例
Copy
<
user
name
=
"test"
>
<
property
name
=
"password"
>
test
</
property
>
<
property
name
=
"schemas"
>
lunch
</
property
>
<
property
name
=
"readOnly"
>
false
</
property
>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</
user
>
重点关注下面这段,其他默认即可。
参数
|
说明
|
user
|
用户配置节点
|
--name
|
登录的用户名,也就是连接Mycat的用户名
|
--password
|
登录的密码,也就是连接Mycat的密码
|
--schemas
|
数据库名,这里会和schema.xml中的配置关联,多个用逗号分开,例如需要这个用户需要管理两个数据库db1,db2,则配置db1,dbs
|
--privileges
|
配置用户针对表的增删改查的权限,具体见文档吧
|
我这里配置了一个账号test 密码也是test,针对数据库lunch,读写权限都有,没有针对表做任何特殊的权限。
schema.xml
schema.xml是最主要的配置项,首先看我的配置文件。
Copy
<?
xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<!-- 数据库配置,与server.xml中的数据库对应 -->
<
schema
name
=
"lunch"
checkSQLschema
=
"false"
sqlMaxLimit
=
"100"
>
<
table
name
=
"lunchmenu"
dataNode
=
"dn1"
/>
<
table
name
=
"restaurant"
dataNode
=
"dn1"
/>
<
table
name
=
"userlunch"
dataNode
=
"dn1"
/>
<
table
name
=
"users"
dataNode
=
"dn1"
/>
<
table
name
=
"dictionary"
primaryKey
=
"id"
autoIncrement
=
"true"
dataNode
=
"dn1,dn2"
rule
=
"mod-long"
/>
</
schema
>
<!-- 分片配置 -->
<
dataNode
name
=
"dn1"
dataHost
=
"test1"
database
=
"lunch"
/>
<
dataNode
name
=
"dn2"
dataHost
=
"test2"
database
=
"lunch"
/>
<!-- 物理数据库配置 -->
<
dataHost
name
=
"test1"
maxCon
=
"1000"
minCon
=
"10"
balance
=
"0"
writeType
=
"0"
dbType
=
"mysql"
dbDriver
=
"native"
>
<
heartbeat
>
select user();
</
heartbeat
>
<
writeHost
host
=
"hostM1"
url
=
"192.168.0.2:3306"
user
=
"root"
password
=
"123456"
>
</
writeHost
>
</
dataHost
>
<
dataHost
name
=
"test2"
maxCon
=
"1000"
minCon
=
"10"
balance
=
"0"
writeType
=
"0"
dbType
=
"mysql"
dbDriver
=
"native"
>
<
heartbeat
>
select user();
</
heartbeat
>
<
writeHost
host
=
"hostS1"
url
=
"192.168.0.3:3306"
user
=
"root"
password
=
"123456"
>
</
writeHost
>
</
dataHost
>
</
mycat:schema
>
参数
|
说明
|
schema
|
数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应
|
dataNode
|
分片信息,也就是分库相关配置
|
dataHost
|
物理数据库,真正存储数据的数据库
|
每个节点的属性逐一说明:
schema:
属性
|
说明
|
name
|
逻辑数据库名,与server.xml中的schema对应
|
checkSQLschema
|
数据库前缀相关设置,建议看文档,这里暂时设为folse
|
sqlMaxLimit
|
select 时默认的limit,避免查询全表
|
table:
属性
|
说明
|
name
|
表名,物理数据库中表名
|
dataNode
|
表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
|
primaryKey
|
主键字段名,自动生成主键时需要设置
|
autoIncrement
|
是否自增
|
rule
|
分片规则名,具体规则下文rule详细介绍
|
dataNode
属性
|
说明
|
name
|
节点名,与table中dataNode对应
|
datahost
|
物理数据库名,与datahost中name对应
|
database
|
物理数据库中数据库名
|
dataHost
属性
|
说明
|
name
|
物理数据库名,与dataNode中dataHost对应
|
balance
|
均衡负载的方式
|
writeType
|
写入方式
|
dbType
|
数据库类型
|
heartbeat
|
心跳检测语句,注意语句结尾的分号要加。
|
应用场景
数据库分表分库
配置如下:
Copy
<?
xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<!-- 数据库配置,与server.xml中的数据库对应 -->
<
schema
name
=
"lunch"
checkSQLschema
=
"false"
sqlMaxLimit
=
"100"
>
<
table
name
=
"lunchmenu"
dataNode
=
"dn1"
/>
<
table
name
=
"restaurant"
dataNode
=
"dn1"
/>
<
table
name
=
"userlunch"
dataNode
=
"dn1"
/>
<
table
name
=
"users"
dataNode
=
"dn1"
/>
<
table
name
=
"dictionary"
primaryKey
=
"id"
autoIncrement
=
"true"
dataNode
=
"dn1,dn2"
rule
=
"mod-long"
/>
</
schema
>
<!-- 分片配置 -->
<
dataNode
name
=
"dn1"
dataHost
=
"test1"
database
=
"lunch"
/>
<
dataNode
name
=
"dn2"
dataHost
=
"test2"
database
=
"lunch"
/>
<!-- 物理数据库配置 -->
<
dataHost
name
=
"test1"
maxCon
=
"1000"
minCon
=
"10"
balance
=
"0"
writeType
=
"0"
dbType
=
"mysql"
dbDriver
=
"native"
>
<
heartbeat
>
select user();
</
heartbeat
>
<
writeHost
host
=
"hostM1"
url
=
"192.168.0.2:3306"
user
=
"root"
password
=
"123456"
>
</
writeHost
>
</
dataHost
>
<
dataHost
name
=
"test2"
maxCon
=
"1000"
minCon
=
"10"
balance
=
"0"
writeType
=
"0"
dbType
=
"mysql"
dbDriver
=
"native"
>
<
heartbeat
>
select user();
</
heartbeat
>
<
writeHost
host
=
"hostS1"
url
=
"192.168.0.3:3306"
user
=
"root"
password
=
"123456"
>
</
writeHost
>
</
dataHost
>
</
mycat:schema
>
我在192.168.0.2、192.168.0.3均有数据库lunch。
lunchmenu、restaurant、userlunch、users这些表都只写入节点dn1,也就是192.168.0.2这个服务,而dictionary写入了dn1、dn2两个节点,也就是192.168.0.2、192.168.0.3这两台服务器。分片的规则为:mod-long。
主要关注rule属性,rule属性的内容来源于rule.xml这个文件,Mycat支持10种分表分库的规则,基本能满足你所需要的要求,这个必须赞一个,其他数据库中间件好像都没有这么多。
table中的rule属性对应的就是rule.xml文件中tableRule的name,具体有哪些分表和分库的实现,建议还是看下文档。我这里选择的mod-long就是将数据平均拆分。因为我后端是两台物理库,所以rule.xml中mod-long对应的function count为2,见下面部分代码:
Copy
<
tableRule
name
=
"mod-long"
>
<
rule
>
<
columns
>
id
</
columns
>
<
algorithm
>
mod-long
</
algorithm
>
</
rule
>
</
tableRule
>
<
function
name
=
"mod-long"
class
=
"io.mycat.route.function.PartitionByMod"
>
<!-- how many data nodes -->
<
property
name
=
"count"
>
2
</
property
>
</
function
>
数据库读写分离
配置如下:
Copy
<?
xml version=
"1.0"
?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<!-- 数据库配置,与server.xml中的数据库对应 -->
<
schema
name
=
"lunch"
checkSQLschema
=
"false"
sqlMaxLimit
=
"100"
>
<
table
name
=
"lunchmenu"
dataNode
=
"dn1"
/>
<
table
name
=
"restaurant"
dataNode
=
"dn1"
/>
<
table
name
=
"userlunch"
dataNode
=
"dn1"
/>
<
table
name
=
"users"
dataNode
=
"dn1"
/>
<
table
name
=
"dictionary"
primaryKey
=
"id"
autoIncrement
=
"true"
dataNode
=
"dn1"
/>
</
schema
>
<!-- 分片配置 -->
<
dataNode
name
=
"dn1"
dataHost
=
"test1"
database
=
"lunch"
/>
<!-- 物理数据库配置 -->
<
dataHost
name
=
"test1"
maxCon
=
"1000"
minCon
=
"10"
balance
=
"1"
writeType
=
"0"
dbType
=
"mysql"
dbDriver
=
"native"
>
<
heartbeat
>
select user();
</
heartbeat
>
<
writeHost
host
=
"hostM1"
url
=
"192.168.0.2:3306"
user
=
"root"
password
=
"123456"
>
<
readHost
host
=
"hostM1"
url
=
"192.168.0.3:3306"
user
=
"root"
password
=
"123456"
>
</
readHost
>
</
writeHost
>
</
dataHost
>
</
mycat:schema
>
这样的配置与前一个示例配置改动如下:
删除了table分配的规则,以及datanode只有一个
datahost也只有一台,但是writehost总添加了readhost,balance改为1,表示读写分离。
以上配置达到的效果就是102.168.0.2为主库,192.168.0.3为从库。
注意:
Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhos
t,这个问题当时候我纠结了好久,数据写入writehost后,readhost一直没有数据,以为是自己配置的问题,后面才发现Mycat就没有实现主从复制的功能,毕竟数据库本身自带的这个功能才是最高效稳定的。
至于其他的场景,如同时主从和分表分库也是支持的了,只要了解这个实现以后再去修改配置,都是可以实现的。而热备及故障专业官方推荐使用haproxy配合一起使用,大家可以试试。
使用
Mycat的启动也很简单,启动命令在Bin目录:
Copy
#
#启动
mycat start
#
#停止
mycat stop
#
#重启
mycat restart
如果在启动时发现异常,在logs目录中查看日志。
-
wrapper.log 为程序启动的日志,启动时的问题看这个
-
mycat.log 为脚本执行时的日志,SQL脚本执行报错后的具体错误内容,查看这个文件。mycat.log是最新的错误日志,历史日志会根据时间生成目录保存。
mycat启动后,执行命令不成功,可能实际上配置有错误,导致后面的命令没有很好的执行。
Mycat带来的最大好处就是使用是完全不用修改原有代码的,在mycat通过命令启动后,你只需要将数据库连接切换到Mycat的地址就可以了。如下面就可以进行连接了:
Copy
mysql -h192.168.0.1 -P8806 -uroot -p123456
连接成功后可以执行sql脚本了。
所以,可以直接通过sql管理工具(如:navicat、datagrip)连接,执行脚本。我一直用datagrip来进行日常简单的管理,这个很方便。
Mycat还有一个管理的连接,端口号是9906.
Copy
mysql -h192.168.0.1 -P9906 -uroot -p123456
连接后可以根据管理命令查看Mycat的运行情况,当然,喜欢UI管理方式的人,可以安装一个Mycat-Web来进行管理,有兴趣自行搜索。
简而言之,开发中使用Mycat和直接使用Mysql机会没有差别。
常见问题
使用Mycat后总会遇到一些坑,我将自己遇到的一些问题在这里列一下,希望能与大家有共鸣:
-
Mycat是不是配置以后,就能完全解决分表分库和读写分离问题?
Mycat配合数据库本身的复制功能,可以解决读写分离的问题,但是针对分表分库的问题,不是完美的解决。或者说,至今为止,业界没有完美的解决方案。
分表分库写入能完美解决,但是,不能完美解决主要是联表查询的问题,Mycat支持两个表联表的查询,多余两个表的查询不支持。 其实,很多数据库中间件关于分表分库后查询的问题,都是需要自己实现的,而且节本都不支持联表查询,Mycat已经算做地非常先进了。
分表分库的后联表查询问题,大家通过合理数据库设计来避免。
-
Mycat支持哪些数据库,其他平台如 .net、PHP能用吗?
官方说了,支持的数据库包括MySQL、SQL Server、Oracle、DB2、PostgreSQL 等主流数据库,很赞。
尽量用Mysql,我试过SQL Server,会有些小问题,因为部分语法有点差异。
-
Mycat 非JAVA平台如 .net、PHP能用吗?
可以用。这一点MyCat做的也很棒。