linux搭建主从数据库和Mycat读写分离

目录

linux搭建主从数据库和Mycat读写分离

搭建主从数据库服务器

搭建主从数据库服务器

从数据库可以理解为主数据库的实时备份, 当主数据库发生变化, 从数据库也会发生变化

从库可以有多个, 但是一般不会超过3个从库

一般从数据库为只读, 如果从数据库数据认为的更改了, 主数据库不会该表

图解

linux搭建主从数据库和Mycat读写分离

工作原理

左边为主数据库, 有边为从数据库

linux搭建主从数据库和Mycat读写分离

工作原理说明:

  1. 数据库主库将更新的数据信息写入到二进制日志文件中.
  2. 数据库从库通过IO线程去主库中获取二进制文件修改内容. 之后写入到中继日志中
  3. 数据库从库中的Sql线程读取中继日志中的信息,实现数据的同步. 并且为了降低组件之间的耦合性,采用异步的方式处理.

1. 前提准备

  1. 两台centos服务器 或 虚拟机, 并且都安装了数据库, mysql或mariadb
  2. 先手动同步数据库中的数据 (利用sqlyog等工具导出主数据库数据, 导入到从数据库)保证目前两个数据库同步

2. 开启二进制日志

主库可从库都要开启

更改数据库核心配置文件 vim /etc/my.cnf (版本不同, 配置文件位置也可能不同)

在 [mysqld] 下面加入如下内容

[mysqld]
# 服务id (此id从库和主库都不能重复, 每个数据库有自己的id)
server-id=1
# 配置二进制日志文件名称, 可以任意 (可以和从数据库一致)
log-bin=mysql-bin

我们从配置文件上面的 datadir 属性可以看到mysql的工作目录

linux搭建主从数据库和Mycat读写分离

即, 生成的二进制日志文件也在改工作目录中

现在重启mysql服务器: systemctl restart mariadb

到工作目录/var/lib/mysql中查看, 可以看到生成的两个文件

linux搭建主从数据库和Mycat读写分离

其中mysql-bin.000001文件, 每次数据库重启, 文件后缀就会加1

其他数据库也重复以上操作, 保证数据库的二进制日志文件都开启 (注意mysql核心配置文件中server-id属性不能重复)

3. 实现主从挂载

主从挂载应该由从库向主库进行挂载.由从库远程连接主库,之后读取二进制日志文件信息.

3.1. 确定主库二进制日志信息

确定主库中的二进制日志文件信息命令: 在主数据库中输入: show master status;

linux搭建主从数据库和Mycat读写分离

其中Position字段相当于是一个指针, 即从数据库读取的时候会从这个指针出开始读取, 而不是把整个文件都要读取, 这大大提升了效率

3.2 实现主从挂载

在所有的从库中连接主库 (所有的从库都要执行)

/*我是从库 默认条件下数据库都是主库host/port/user/password/二进制文件/pos*/
CHANGE MASTER TO MASTER_HOST="192.168.126.129", -- 主库的ip地址(公网/私网)
	         MASTER_PORT=3306,  -- 主库端口号
	         MASTER_USER="root",  -- 主库用户名
	         MASTER_PASSWORD="123456",  -- 主库密码
	         MASTER_LOG_FILE="mysql-bin.000001",  -- 上一步查到的File字段, 日志文件名
	         MASTER_LOG_POS=245;  -- 上一步查到的Position字段

/*启动主从服务*/
START  SLAVE;
/*检查主从状态*/
SHOW SLAVE  STATUS;

检查主从状态显示如下信息的两个字段为yes, 说明启动成功, 如果没有yes, 状态结果中会有错误信息的字段

linux搭建主从数据库和Mycat读写分离

错误信息字段

linux搭建主从数据库和Mycat读写分离

如果信息写错, 先关闭主从服务, 在重复上面的操作

/*关闭主从服务*/
STOP  SLAVE;

数据库主从复制/读写分离

Mycat读写分离

Mycat有java语言所编写的一个数据库分库分表中间件

原理图

linux搭建主从数据库和Mycat读写分离

Mycat介绍

官网: http://www.mycat.org.cn/

Mycat是数据库分库分表中间件, 是一个活跃的、性能好的开源数据库中间件!

关键特性如下: (可从官网中查看更多)

linux搭建主从数据库和Mycat读写分离

1. Mycat下载

下载地址: http://dl.mycat.org.cn/

我下载版本为1.7, 不同版本应该大体步骤类似,

可参考使用文档: https://github.com/MyCATApache/Mycat-Server/wiki

2. 安装Mycat

解压

上传到服务器并解压 (使用tar -zxvf 命令解压即可)

3. 配置MyCat

配置文件在 Mycat根目录/conf

3.1 配置server.xml

端口: <property name="serverPort">8066</property>

端口一般不需要配置, 默认为8066

在server.xml底部配置用户, 例如:

<user name="root"> <!-- 用户名 -->
    <property name="password">123456</property> <!-- 密码 -->
    <property name="schemas">jtdb</property> <!-- 数据库 -->
</user>

以上配置对应mysql中的配置如下

# 数据库的IP写MyCat服务所在主机的IP (公网/私网)
spring.datesource.url=jdbc:mysql://xxx.xxx.xxx.xxx:8066/jtdb
# Mycat中配置的用户名
spring.datasource.username=root
# Mycat中配置的密码
spring.datasource.password=123456

3.2 配置schema.xml

dataHost标签内部进行读写配置

例如有两台数据库服务器, ip分别为 192.168.126.129 和 192.168.126.130, 其中前者为主库, 后者为从库, 如下配置

<!-- writeHost标签配置 [写]数据库, 内部的readHost标签配置 [读]数据库 -->
<!-- 下面配置表示主数据库可写,可读. 从数据库只可读 -->
<!-- user属性和password属性分别代表指定ip的数据库用户名和密码 -->
<writeHost host="hostM1" url="192.168.126.129:3306" user="root" password="123456">
    <!--读数据库1-->
    <readHost host="hostS1" url="192.168.126.130:3306" user="root" password="123456" />
    <!--读数据库2-->
    <readHost host="hostS2" url="192.168.126.129:3306" user="root" password="123456" />
</writeHost>

因为一台主数据库对应多个从数据库, 上面这种配置就很合理, (一个写对应多个读)

4. Mycat运行命令

进入到Mycat的bin目录, 来启动Mycat, 启动之后最好进行一次检测状态操作, 确保Mycat已经启动

./mycat  start    启动命令 
./mycat  status   检查状态
./mycat  restart  重启命令
./mycat  stop     停止命令

5. 检测负载均衡

以上配置完成后, 读可以从两个数据库读, 写只能写主库.

我们可以试着改变从库的数据, 这时候主库数据不会发生变化, 在项目中查询这个数据返回到页面, 可以看到两个数据库中不同的结果, 就说明成功了 (但是切记, 测试完成后, 记得改回原来从库中的shuj,使两个数据库中数据保持一致, 防止不必要的崩溃)

数据库的高可用

上面的配置中, 当主数据库发生故障时, 数据库则无法使用, 从数据库不能代替主数据库进行工作

实现数据库的高可用可以进行双向绑定, 即双主模式

双主模式图解

配置2台数据 互为主从. 这样的效果可以保证在主库宕机的之后,用户操作都是从库.当主库重启之后,从库会把数据同步给主库.最终实现了数据的一致性.

linux搭建主从数据库和Mycat读写分离

1. 实现主从挂载

两台服务器互相挂载 (不是单向挂载), 挂载方法参考 [点击跳转挂载方法]

双向绑定完成后记得重启数据库服务

2. 配置schema.xml

添加一个writeHost标签, 并且确保dataHost 标签的switchType属性值为1

dataHost完整配置如下:

<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
    <heartbeat>select 1</heartbeat>

    <writeHost host="hostM1" url="192.168.126.129:3306" user="root" password="root">
        <!--读数据库1-->
        <readHost host="hostS1" url="192.168.126.130:3306" user="root" password="root" />
        <!--读数据库2-->
        <readHost host="hostS2" url="192.168.126.129:3306" user="root" password="root" />

    </writeHost>

    <writeHost host="hostM2" url="192.168.126.130:3306" user="root" password="root">
        <!--读数据库1-->
        <readHost host="hostS1" url="192.168.126.130:3306" user="root" password="root" />
        <!--读数据库2-->
        <readHost host="hostS2" url="192.168.126.129:3306" user="root" password="root" />
    </writeHost>

</dataHost>

3. 重启Mycat

在Mycat的bin中

./mycat restart # 重启
./mycat status # 查看运行状态

schema配置解析

完整文件

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	
	<!--name属性是自定义的  dataNode表示数据库的节点信息  jtdb表示逻辑库-->
	<schema name="jtdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="jtdb"/>

	<!--定义节点名称/节点主机/数据名称-->
	<dataNode name="jtdb" dataHost="localhost1" database="jtdb" />
		<!--参数介绍-->
		<!--balance 0表示所有的读操作都会发往writeHost主机 -->  
		<!--1表示所有的读操作发往readHost和闲置的主节点中-->
		<!--writeType=0 所有的写操作都发往第一个writeHost主机-->	
		<!--writeType=1 所有的写操作随机发往writeHost中-->
		<!--dbType 表示数据库类型 mysql/oracle-->
		<!--dbDriver="native"  固定参数 不变-->
		<!--switchType=-1 表示不自动切换, 主机宕机后不会自动切换从节点-->
		<!--switchType=1  表示会自动切换(默认值)如果第一个主节点宕机后,Mycat会进行3次心跳检测,如果3次都没有响应,则会自动切换到第二个主节点-->
		<!--并且会更新/conf/dnindex.properties文件的主节点信息 localhost1=0 表示第一个节点.该文件不要随意修改否则会出现大问题-->
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select 1</heartbeat>

		<!--配置第一台主机主要进行写库操作,在默认的条件下Mycat主要操作第一台主机在第一台主机中已经实现了读写分离.因为默认写操作会发往137的数据库.读的操作默认发往141.如果从节点比较忙,则主节点分担部分压力.
		-->
		<writeHost host="hostM1" url="192.168.126.129:3306" user="root" password="root">
			<!--读数据库1-->
			<readHost host="hostS1" url="192.168.126.130:3306" user="root" password="root" />
			<!--读数据库2-->
			<readHost host="hostS2" url="192.168.126.129:3306" user="root" password="root" />
			
		</writeHost>

			<!--定义第二台主机 由于数据库内部已经实现了双机热备.-->
			<!--Mycat实现高可用.当第一个主机137宕机后.mycat会自动发出心跳检测.检测3次.-->
			<!--如果主机137没有给Mycat响应则判断主机死亡.则回启东第二台主机继续为用户提供服务.-->
			<!--如果137主机恢复之后则处于等待状态.如果141宕机则137再次持续为用户提供服务.-->
			<!--前提:实现双机热备.-->
		
		<writeHost host="hostM2" url="192.168.126.130:3306" user="root" password="root">
			<!--读数据库1-->
			<readHost host="hostS1" url="192.168.126.130:3306" user="root" password="root" />
			<!--读数据库2-->
			<readHost host="hostS2" url="192.168.126.129:3306" user="root" password="root" />
		</writeHost>
		
	</dataHost>
</mycat:schema>

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-->
	<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="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">1</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">true</property>

		<!-- XA Recovery Log日志路径 -->
		<!--<property name="XARecoveryLogBaseDir">./</property>-->

		<!-- XA Recovery Log日志名称 -->
		<!--<property name="XARecoveryLogBaseName">tmlog</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"/>
	   </whitehost>
       <blacklist check="false">
       </blacklist>
	</firewall>
	-->

	<user name="root">
		<property name="password">123456</property>
		<property name="schemas">TESTDB</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="user">
		<property name="password">user</property>
		<property name="schemas">TESTDB</property>
		<property name="readOnly">true</property>
	</user>

</mycat:server>
上一篇:dedecms内容页调用缩略图 缩略图多种用法(借鉴)


下一篇:Mycat 数据切分