前言

  开心一刻

    一个女人自朋友圈写道:我家老公昨天和别人家的老婆出去旅游,迄今未归,我则被别人家的老公折腾了一天,好累哦!

    圈子下面,评论无数,老公在下面评论到:能不能好好说话,我只不过陪女儿去毕业旅游行,而你负责在家留守,照顾三岁儿子,要不要写的这么刺激、让人浮想联翩的? 你是不是有点虎?

诺维斯基:你往哪射了?

周子瑜:我只是个娱乐明星,射箭我不是专业的...

  路漫漫其修远兮,吾将上下而求索!

  github:https://github.com/youzhibing

  码云(gitee):https://gitee.com/youzhibing

前情回顾

  通过前面的两篇博文:Mycat - 实现数据库的读写分离与高可用Mycat - 高可用与负载均衡实现,满满的干货!,我们完成了如下图所示的组件部署

组件结构图一

  SQL请求发给VIP,keepalived完成VIP的映射,并通过lvs将请求转发mycat,mycat根据SQL请求类型(DML SQL还是SELECT SQL,亦或是强制指定db节点)将SQL分发到具体的db,完成由具体的数据库服务完成SQL的执行。

  但这还只是停留在数据库层面的部署,还没集成我们的应用,没有实际意义,那么我们如何集成我们的应用,实现mycat的使命呢?

应用集成

  如果mycat搭建好了,进行应用集成非常简单,下面我们一步一步来实现各种情况下的应用集成

  Mysql的读写分离与高可用

    数据库的读写分离可以在代码层面实现(可参考:spring集成mybatis实现mysql读写分离),但不推荐,代码的核心职责应该是业务的实现,如果将大篇的代码用来实现数据库的读写分离与高可用,那就背离了本意、南辕北辙了。

    计算机领域有句名言:“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”。既然我们的代码直接对接数据库不好实现数据库的读写分离与高可用,那就在中间新增一层中间件来实现,从而产生了数据库中间件(mycat只是实现之一),应用代码直接与数据库中间对接,由数据库中间件来实现数据库的读写分离与高可用。此时的组件结构图如下

组件结构图二

    具体的部署过程可参考:Mycat - 实现数据库的读写分离与高可用,此时应用如何集成了?其实非常简单,只需要将我们的连接池配置中的数据库地址改成mycat的地址即可(将mycat看成数据库),具体如下

    application.yml

server:
port: 8886
spring:
#连接池配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.212:8066/TESTDB?useSSL=false&useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
initial-size: 1 #连接池初始大小
max-active: 20 #连接池中最大的活跃连接数
min-idle: 1 #连接池中最小的活跃连接数
max-wait: 60000 #配置获取连接等待超时的时间
pool-prepared-statements: true #打开PSCache,并且指定每个连接上PSCache的大小
max-pool-prepared-statement-per-connection-size: 20
validation-query: SELECT 1 FROM DUAL
validation-query-timeout: 30000
test-on-borrow: false #是否在获得连接后检测其可用性
test-on-return: false #是否在连接放回连接池后检测其可用性
test-while-idle: true #是否在连接空闲一段时间后检测其可用性
#mybatis配置
mybatis:
type-aliases-package: com.lee.mycat.entity
#config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/*.xml
# pagehelper配置
pagehelper:
helperDialect: mysql
#分页合理化,pageNum<=0则查询第一页的记录;pageNum大于总页数,则查询最后一页的记录
reasonable: true
supportMethodsArguments: true
params: count=countSql
logging:
level:
com.lee.mycat.mapper: DEBUG

    UserWeb.java

package com.lee.mycat.web;

import com.lee.mycat.entity.User;
import com.lee.mycat.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("/mycat")
public class UserWeb { @Autowired
private IUserService userService; @RequestMapping("/getUserByNameFromMasterDb")
public User getUserByNameFromMasterDb(String name) {
return userService.getUserByNameFromMasterDb(name);
} @RequestMapping("/getUserByNameFromSlaveDb")
public User getUserByNameFromSlaveDb(String name) {
return userService.getUserByNameFromSlaveDb(name);
} @RequestMapping("/getUserByName")
public User getUserByName(String name) {
return userService.getUserByName(name);
} @RequestMapping("/addUser")
public Integer addUser(String name, Integer age) {
return userService.insertUser(new User(name, age));
}
}

    UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lee.mycat.mapper.UserMapper"> <sql id="Base_Column_List">
id,name,age
</sql> <select id="getUserByNameFromMasterDb" resultType="User" parameterType="String">
/*!mycat:db_type=master*/ SELECT
<include refid="Base_Column_List" />
FROM
tbl_user
WHERE name=#{name}
</select>
<select id="getUserByNameFromSlaveDb" resultType="User" parameterType="String">
/*!mycat:db_type=slave*/ SELECT
<include refid="Base_Column_List" />
FROM
tbl_user
WHERE name=#{name}
</select>
<select id="getUserByName" resultType="User" parameterType="String">
SELECT
<include refid="Base_Column_List" />
FROM
tbl_user
WHERE name=#{name}
</select>
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO
tbl_user(name, age)
VALUES
(#{name}, #{age})
</insert>
</mapper>

    UserMapper.xml文件中会与我们平时的写法有些许不同,有时候需要明确指定强制走master还是slave节点。具体细节可查看:spring-boot-mycat

    测试结果

      如上图所示,我们一开始新增了一个用户:Jiraiye,其年龄是50,我们手动改了mysql slave中Jiraiye的年龄为52是为了更直观的验证SQL请求最终走的是mysql master还是mysql slave。从上图可知,一般的Select SQL走的是从库(DML SQL走主库这个就不用说了),如在mapper.xml中强制指定了db节点,那么就会在指定的mysql节点上来执行SQL。

      mysql的高可用就没进行测试了,应用其实是感知不到的;mysql master宕机了,mycat会按我们配置好的进行mysql db的切换,正常服务于我们的应用。

  Mycat的高可用

    mysql的读写分离与高可用我们是实现了,可mycat却存在高可用问题,一旦mycat宕机了,整个数据库层就相当于宕机了。可想而知,我们需要实现mycat的高可用。

    mycat的高可用搭建过程可参考:Mycat - 高可用与负载均衡实现,满满的干货!,此时的组件结构图如下

组件结构图三

    应用工程改动非常小,只需要将数据库连接配置的url改成VIP即可,如下

jdbc:mysql://192.168.1.212:8066/TESTDB?useSSL=false&useUnicode=true&characterEncoding=utf-8
改成
jdbc:mysql://192.168.1.200:8066/TESTDB?useSSL=false&useUnicode=true&characterEncoding=utf-8

    测试结果

      mysql的读写分离依然正常工作,当mycat master宕机后,mycat slave接管任务,进行sql的转发,实现了mycat的高可用;期间出现了非常短时间的异常提示,这是因为数据库连接池中都是212上的mycat连接,212现在已经宕机了,所以会出现一次异常提示,但连接池立马做出了反应,重新建立数据库连接,此时连接池中的连接都是连接的110。

  Mycat的负载均衡

    上述mycat的高可用中,绝大多数情况下,mycat slave一直处于等待状态,未提供任何服务,因为我们的mycat master一般而言是不会宕机的。那有没有什么做法可以让slave也处理SQL请求,而又和master互备实现mycat高可用呢?那就是实现Mycat的负载均衡,此时mycat不存在主从关系,而是它俩两两互备,此时的组件结构图就是组件结构图一。应用工程不用变,数据库连接还是配置VIP。具体就不演示了,大家自行去实践即可。

总结

  1、数据库中间件可以降低应用代码的复杂性,让其专职于业务代码的实现,而数据库层面的工作交给数据库中间件;mycat只是数据库中间件的一种实现,却也是比较优秀的实现,她是开源的。

  2、并发量不高的情况下,实现mycat的高可用即可,无需实现Mycat的负载均衡;实现mycat的负载均衡需要更多的硬件成本和维护成本,却没有带来质变的收益,就性价比而言,不升反降。

  3、具体需要部署成什么组件结构,需要看具体的需求,很多情况下根本用不到mycat中间件,如果用到了mycat中间件,个人认为最好还是实现mycat的高可用,至于需不需要实现mycat的负载均衡,就看具体的并发量了,这个也没个标准,就要结合实际情况来排查是不是mycat的负载过高了,如果确实是mycat负载过高,那么就有必要实现mycat的负载均衡来降低单个mycat的负载了。没有绝对的最优部署,只有当下最合适的部署。

参考

  《Mycat权威指南》

应用集成mycat,实现mycat的高可用与mysql的读写分离的更多相关文章

  1. Mycat高可用解决方案三(读写分离)

    Mycat高可用解决方案三(读写分离) 一.系统部署规划 名称 IP 主机名称 配置 192.168.199.112 mycat01 2核/2G Mysql主节点 192.168.199.110 my ...

  2. MHA高可用架构与Atlas读写分离

    1.1 MHA简介 1.1.1 MHA软件介绍 MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton ...

  3. MySQL 高可用:mysql+mycat实现数据库分片(分库分表)

    本文引用于http://blog.csdn.net/kk185800961/article/details/51147029 MySQL 高可用:mysql+mycat实现数据库分片(分库分表) 什么 ...

  4. MyCAT实现MySQL的读写分离

    在MySQL中间件出现之前,对于MySQL主从集群,如果要实现其读写分离,一般是在程序端实现,这样就带来一个问题,即数据库和程序的耦合度太高,如果我数据库的地址发生改变了,那么我程序端也要进行相应的修 ...

  5. Mycat+MySql 主从复制-读写分离 看这一篇就够了

    ​ 通过mycat和mysql的主从复制配合搭建数据库的读写分离,可以实现mysql的高可用性,下面我们来搭建mysql的读写分离. 1.一主一从 1.在node01上修改/etc/my.cnf的文件 ...

  6. MySQL高可用解决方案(MySQL HA Solution)

    http://blog.sina.com.cn/s/blog_7e89c3f501012vtr.html 什么是高可用性?很多公司的服务都是24小时*365天不间断的.比如Call Center.这就 ...

  7. 通过mycat实现mysql的读写分离

    mysql的主从配置沿用上一篇博客的配置:https://www.cnblogs.com/MasterSword/p/9434169.html mycat下载地址:http://www.mycat.i ...

  8. MySQL高可用方案-MySQL InnoDB Cluster

    MySQL InnoDB Cluster简介 MySQL InnoDB Cluster 是最新GA的MySQL高可用方案,利用MySQL Group Replication和MySQL Shell.M ...

  9. MySQL主从复制之Mycat简单配置和高可用

    什么是Mycat 1.Mycat就是MySQL Server,而Mycat后面连接的MySQL Server,就好象是MySQL的存储引擎,如InnoDB,MyISAM等.因此,Mycat本身并不存储 ...

随机推荐

  1. Android Keystore 对称-非对称加密

    Android数据加密: Anroid数据加密方式 Android 提供了 KeyStore 等可以长期存储和检索加密密钥的机制,Android KeyStore 系统特别适合于存储加密密钥. “An ...

  2. C++ otlv4 连接 sql server 数据库小记

    otlv4介绍: http://otl.sourceforge.net/ 测试代码 // testotlv4.cpp : 定义控制台应用程序的入口点. // #include "stdafx ...

  3. mpvue-docs基于vue来开发微信小程序

    http://mpvue.com/和https://tencent.github.io/wepy/

  4. python练习题目

    1.查看本机安装python版本 2.用python打印"Hello World",给出源代码和执行结果 a.命令行窗口输出(前提:python程序加入PATH系统环境变量) b. ...

  5. mysql错误:The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement解决方法

    本文为大家讲解的是mysql错误:The MySQL server is running with the --skip-grant-tables option so it cannot execut ...

  6. 锐捷交换机配置DHCP SERVER给固定的MAC地址分配静态IP

    今天突发奇想,想给自己的手机分配固定地址,使得接入公司无线网络时每次都取到同一ip地址,这样可以排除认证登录问题. 上网溜达一下,记录下锐捷官方的[常见问题]如下,经验证可行. 需求: 给MAC地址为 ...

  7. 20175324王陈峤宇 2018-2019-2《Java程序设计》结对编程项目-四则运算 第一周 阶段性总结

    20175324王陈峤宇 2018-2019-2<Java程序设计>结对编程项目-四则运算 第一周 阶段性总结 需求分析 这次的结对作业是要求我们利用栈来设计一个计算器. 自动生成四则运算 ...

  8. 反编译python打包的exe文件

    目录 1.前言 2.使用环境 3.还原过程 4.号外 5.exe文件和所用到的反编译工具 6.参考 7.去签名(补漏) 前言 拿到了利用驱动人生进行传播的病毒样本,发现是python打包成的exe文件 ...

  9. JMeter 测试 ActiveMq

    JMeter 测试 ActiveMq 的资料非常少, 我花了大量的时间才研究出来 关于ActiveMq 的文章请参考我另外的文章. 阅读目录 版本号: ActiveMq 版本号:  5.91 Jmet ...

  10. Java线程中的同步

    1.对象与锁 每一个Object类及其子类的实例都拥有一个锁.其中,标量类型int,float等不是对象类型,但是标量类型可以通过其包装类来作为锁.单独的成员变量是不能被标明为同步的.锁只能用在使用了 ...