本篇来实现mysql在程序中的读写分离
使用到数据库中间件myCat,实现读写库的自动路由
服务器环境:
linux Centos 7
mysql8.0.21
服务器三台(一主一从)
192.168.121.10 (主库)、
192.168.121.20 (从库)
192.168.121.30(mycat中间件)三台机器均需安装同一版本mysql
数据库安装步骤参考linux安装mysql详细教程(远程连接)
下面主要讲myCat的安装部署
1、安装java环境(mycat基于java,已有则忽略)
#安装Java环境(mycat基于java) 已有则忽略
wget http://dl.mycat.io/jdk-8u20-linux-x64.tar.gz
# 解压到/usr/local
tar -zxcf jdk-8u20-linux-x64.tar.gz /usr/local
mv jdk-8u20-linux-x64 jdk
sudo vim /etc/profile
export JDK_HOME=/usr/local/jdk
export PATH=%PATH:$JDK_HOME/bin
# 保存退出
source /etc/profile2、下载安装mycat(我mysql 8.0 下载的mycat 1.6.6)
#下载安装包
wget http://dl.mycat.io/1.6.6.1/Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz
#解压
tar -xvf Mycat-server-1.6.6.1-release-20181031195535-linux.tar.gz -C /usr/local
#配置环境变量
sudo vim /etc/profile
export MYCAT_HOME=/usr/local/mycat
export PATH=%PATH:$MYCAT_HOME/bin
#保存退出
source /etc/profile3、开始修改配置文件
主要两个(schema.xml、server.xml)
server.xml:定义用户以及系统相关变量,如端口等
schema.xml:定义逻辑库,表、分片节点等内容
rule.xml:定义分片规则
server.xml:
主要修改下面两个<user>内的用户名、密码、库名
还有<property name="useOffHeapForMerge">0</property> 为0 默认是1开启
[root@centos7 conf]# cat server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License. - You
may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
- - Unless required by applicable law or agreed to in writing, software -
distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
License for the specific language governing permissions and - limitations
under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="nonePasswordLogin">0</property> <!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户-->
<property name="useHandshakeV10">1</property>
<property name="useSqlStat">0</property> <!-- 1为开启实时统计、0为关闭 -->
<property name="useGlobleTableCheck">0</property> <!-- 1为开启全加班一致性检测、0为关闭 -->
<property name="sequnceHandlerType">2</property>
<property name="subqueryRelationshipCheck">false</property> <!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false -->
<!-- <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议-->
<!-- <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号-->
<!-- <property name="processorBufferChunk">40960</property> -->
<!--
<property name="processors">1</property>
<property name="processorExecutor">32</property>
-->
<!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
<property name="processorBufferPoolType">0</property>
<!--默认是65535 64K 用于sql解析时最大文本长度 -->
<!--<property name="maxStringLiteralLength">65535</property>-->
<!--<property name="sequnceHandlerType">0</property>-->
<!--<property name="backSocketNoDelay">1</property>-->
<!--<property name="frontSocketNoDelay">1</property>-->
<!--<property name="processorExecutor">16</property>-->
<!--
<property name="serverPort">8066</property> <property name="managerPort">9066</property>
<property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property>
<property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
<!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志-->
<property name="handleDistributedTransactions">0</property>
<!--
off heap for merge/order/group/limit 1开启 0关闭
-->
<property name="useOffHeapForMerge">0</property>
<!--
单位为m
-->
<property name="memoryPageSize">64k</property>
<!--
单位为k
-->
<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<!--
单位为m
-->
<property name="systemReserveMemorySize">384m</property>
<!--是否采用zookeeper协调切换 -->
<property name="useZKSwitch">false</property>
<!-- XA Recovery Log日志路径 -->
<!--<property name="XARecoveryLogBaseDir">./</property>-->
<!-- XA Recovery Log日志名称 -->
<!--<property name="XARecoveryLogBaseName">tmlog</property>-->
<!--如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接-->
<property name="strictTxIsolation">false</property>
<property name="useZKSwitch">true</property>
</system>
<!-- 全局SQL防火墙设置 -->
<!--白名单可以使用通配符%或着*-->
<!--例如<host host="127.0.0.*" user="root"/>-->
<!--例如<host host="127.0.*" user="root"/>-->
<!--例如<host host="127.*" user="root"/>-->
<!--例如<host host="1*7.*" user="root"/>-->
<!--这些配置情况下对于127.0.0.1都能以root账户登录-->
<firewall>
<whitehost>
<host host="1*7.0.0.*" user="root"/>
<host host="172.*" user="root"/>
</whitehost>
<blacklist check="false">
</blacklist>
</firewall>
<!-- 登陆用户名, 即MyCat连接用户名 -->
<!-- 写入帐号的配置 -->
<user name="用户1" defaultAccount="true">
<!-- 登陆密码, 即MyCat连接密码 -->
<property name="password">密码</property>
<!-- 数据库名, 即MyCat的逻辑库, 此处会与schema.xml的配置存在关联 -->
<property name="schemas">库名</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="用户2">
<property name="password">密码</property>
<property name="schemas">库名</property>
<property name="readOnly">true</property>
</user>
</mycat:server>schema.xml
修改逻辑库名,mycat访问地址ip、主库、从库ip、访问库的用户名密码
[root@centos7 conf]# cat schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 数据库设置,此数据库为逻辑数据库,name与server.xml中schemas对应 -->
<!-- schema : 定义mycat实例中的逻辑库,也就是mycat服务中有数据库,mycat可以有多个逻辑库,每个逻辑库都有自己的相关配置 -->
<!-- name : 逻辑数据库名,与server.xml中的schemas对应-->
<!-- checkSQLschema : 数据库前缀相关设置,当该值为true时,例如我们执行语句select * from db_store.company 。mycat会把语句修改为 select * from company 去掉db_store -->
<!-- sqlMaxLimit : 当该值设置为某个数值时,每条执行的sql语句,如果没有加上limit语句,Mycat会自动加上对应的值。不写的话,默认返回所有的值。
* 需要注意的是,如果运行的schema为非拆分库的,那么该属性不会生效。需要自己sql语句加limit -->
<!-- 如果schema中没有table配置,需要指定dataNode属性 -->
<schema name="库名" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
<!-- 节点配置 : 分片信息,也就是分库相关配置-->
<!-- dataNode : 定义了mycat中的数据节点,也就是我们所说的数据分片。一个datanode标签就是一个独立的数据分片
* 如下表述的意思为,使用名字为db_storeHOST数据库实例上的db_store物理数据库,这就组成一个数据分片,最后我们用db_store_dataNode来标示这个分片-->
<!-- name : 定义数据节点的唯一名称, 在table标签上用这个名字建立表与分片对应的关系 -->
<!-- dataHost : 用于定义该分片属于哪个数据库实例,属性与datahost标签上定义的name对应 -->
<!-- database : 用于定义该分片属于数据库实例上的物理库,也就是真实的数据库名 -->
<dataNode name="dn1" dataHost="mycatip地址" database="真实数据库名" />
<!-- 节点主机配置 : 物理数据库,真正存储数据的数据库 -->
<!-- 这个标签直接定义了具体数据库实例,读写分离配置和心跳语句 -->
<!-- name : 唯一标示dataHost标签,供上层dataNode使用 -->
<!-- maxCon : 指定每个读写实例连接池的最大连接 -->
<!-- minCon : 指定每个读写实例连接池的最小连接 -->
<!-- balance : 负载均称类型
* 0 : 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
* 1 : 全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1-S1,M2-S2 并且M1 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡
* 2 : 所有读操作都随机的在writeHost、readHost上分发
* 3 : 所有读请求随机的分发到writeHst对应的readHost执行,writeHost不负担读写压力 -->
<!-- writeType : 负载均衡类型
* 0 : 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties
* 1 : 所有写操作都随机的发送到配置的 writeHost。1.5以后版本废弃不推荐 -->
<!-- switchType : 节点切换方式
* -1 : 不自动切换
* 1 : 默认值 自动切换
* 2 : 基于MySql主从同步的状态决定是否切换心跳语句为 show slave status
* 3 : 基于mysql galary cluster 的切换机制(适合集群)1.4.1 心跳语句为 show status like 'wsrep%'-->
<!-- dbType : 指定后端链接的数据库类型目前支持二进制的mysql协议,还有其他使用jdbc链接的数据库,例如:mongodb,oracle,spark等 -->
<!-- dbDriver : 指定连接后段数据库使用的driver,目前可选的值有native和JDBC。使用native的话,因为这个值执行的是二进制的mysql协议,所以可以使用mysql和maridb,其他类型的则需要使用JDBC驱动来支持; 如果使用JDBC的话需要符合JDBC4标准的驱动jar 放到mycat\lib目录下 -->
<!-- tempReadHostAvailable : 如果配置了这个属性 writeHost 下面的 readHost 仍旧可用,默认 0 可配置(0、1) -->
<dataHost name="mycatip地址" maxCon="1000" minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!-- 指明用于和后端数据库进行心跳检查的语句 -->
<!-- mysql : 可以用select user()-->
<!-- oracle : 可以用select 1 from dual-->
<heartbeat>select user()</heartbeat>
<!-- readHost/writeHost : 这两个标签都指定后端数据库的相关配置,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例 -->
<!-- host : 标识不同的示例, 一般 writeHost 我们使用*M1,readHost 我们用*S1 -->
<!-- url : 后端实例连接地址。
* Native:地址:端口
* JDBC:jdbc的url -->
<!-- user : 后端存储实例需要的用户名称 -->
<!-- password : 后端存储实例需要的密码 -->
<!-- weight : 权重, 配置在 readhost 中作为读节点的权重 -->
<!-- usingDecrypt : 是否对密码加密,默认0(不加密)。具体加密方法看官方文档 -->
<writeHost host="主库hostname" url="主库ip:3306" user="" password="">
<!-- can have multi read hosts -->
<readHost host="从库hostname" url="从库ip:3306" user="" password="" />
</writeHost>
</dataHost>
</mycat:schema>修改完成
启动,bin目录下 ./mycat start
日志可查看 cat /usr/local/mycat/logs/wrapper.log
STATUS | wrapper | 2021/11/29 12:40:06 | --> Wrapper Started as Daemon
STATUS | wrapper | 2021/11/29 12:40:06 | Launching a JVM...
INFO | jvm 1 | 2021/11/29 12:40:06 | Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=64M; support was removed in 8.0
INFO | jvm 1 | 2021/11/29 12:40:07 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO | jvm 1 | 2021/11/29 12:40:07 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
INFO | jvm 1 | 2021/11/29 12:40:07 |
INFO | jvm 1 | 2021/11/29 12:40:09 | MyCAT Server startup successfully. see logs in logs/mycat.logcat /usr/local/mycat/logs/mycat.log 查看正常输出
bin目录下 ./mycat status查看运行状态
其他问题
1.启动正常,mycat.log显示访问不通
set Error 1 DBHostConfig [hostName=centos20, url=*.*.*.*:3306]
2021-11-29 11:37:24.072 ERROR [$_NIOREACTOR-11-RW] (io.mycat.backend.heartbeat.MySQLHeartbeat.nextDector(MySQLHeartbeat.java:215)) - set Error 1 DBHostConfig [hostName=centos20, url=ip:3306]查看是否主从库主机名hostname是否正确
[root@centos20 bin]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 centos20
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 centos202.查看使用的主从数据库用户权限是否开启
目前我安装部署遇见的两个问题,其他暂时没遇见,遇见再补充。。。。
















