zoukankan      html  css  js  c++  java
  • linux搭建主从数据库和Mycat读写分离

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

    搭建主从数据库服务器

    搭建主从数据库服务器

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

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

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

    图解

    工作原理

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

    工作原理说明:

    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的工作目录

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

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

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

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

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

    3. 实现主从挂载

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

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

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

    其中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, 状态结果中会有错误信息的字段

    错误信息字段

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

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

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

    Mycat读写分离

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

    原理图

    Mycat介绍

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

    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

    关于配置的详细内容请参见 Mycat配置文件详细介绍

    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> <!-- 数据库: 对应schema.xml中scheam标签的name属性 -->
        
        <!-- 多个数据库如下写法 -->
        <!-- <property name="schemas">jtdb, jtdb2, jtdb3</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

    schema配置: (如果需要管理多个数据库, 可以写多个scheam标签)

    <!--name属性是自定义的,但是一定要和server.xml中保持一致  dataNode表示数据库的节点信息  jtdb表示逻辑库-->
    <schema name="jtdb" checkSQLschema="false" sqlMaxLimit="100" dataNode="jtdb"/>
    

    dataNode配置: (可以写多个dataNode标签, 对应多个物理数据库)

    <!--定义节点名称/节点主机/数据名称, 和上面的dataNode属性名字要一致-->
    <dataNode name="jtdb" dataHost="localhost1" database="jtdb" />
    

    dataHost配置:

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

    <!--参数介绍-->
    		<!--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">
        <!-- 用户判定心跳的sql简单查询 -->
        <heartbeat>select 1</heartbeat>
        
        <!-- 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>
        
    </dataHost>
    

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

    4. Mycat运行命令

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

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

    5. 检测负载均衡

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

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

    数据库的高可用

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

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

    双主模式图解

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

    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>
    
  • 相关阅读:
    解决android Failed to rename directory 问题
    Android APK反编译
    SQL的bit列名转换成access是/否数据类型,True无效的问题
    android获取屏幕硬件分辨率方法
    cursor:hand 与 cursor:pointer 的区别
    解决android调试是出现:Reinstallation failed due to different application signatures
    Flash as3 基础:AS3中的getChildByName(转)
    机器学习之特征预处理
    用户态和内核态的区别
    深度学习和神经网络的区别(转载)
  • 原文地址:https://www.cnblogs.com/zpKang/p/13488584.html
Copyright © 2011-2022 走看看