分享

springboot+mycat数据库中间件+mysql(一主一备)主从复制

 甘甘灰 2018-08-07

硬件:3台linux系统虚拟主机,Ip分别为192.168.43.23做主库(读写,192.168.43.12备库(读),192.168.43.155(安装mycat数据库中间件)

 1.mycat读写分离架构图


                                       


       主要实现原理:




2. linux下使用yum安装mysql


(mastr192.168.43.23,slave192.168.43.12)


  2.1安装mysql 服务器端:

          yuminstall mysql-server

          yuminstall mysql-devel


 2.2编辑mastr192.168.43.23 mysql配置文件

     vim  /etc/my.conf  加入

    default-character-set=utf8//设置字符集

    server_id=23//服务id

    log-bin=mysql-bin//开启日志


2.3编辑slave192.168.43.12配置文件

   vim  /etc/my.conf  加入

  default-character-set=utf8

  server_id=12

  log-bin=mysql-bin

  binlog_do_db=everyday//表示要同步的主机数据库实例是everyday


2.4创建root管理员

 mysqladmin -u root password 123456


2.5登录

  mysql -uroot -p输入密码即可。


3.开放远程连接权限(开放所有IP以root账号连接)

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456'  WITH GRANT OPTION;


4同步主从数据库


4.1主服务器给从服务器授权


 登录mysql主服务器,执行sql:

 grant replication slave on *.* to 'root'@'192.168.43.12'identified by '123456';FLUSH PRIVILEGES; 

然后执行此语句SHOW MASTER STATUS


4.2登录mysql从服务器,执行sql

STOP SLAVE;

change master tomaster_host='192.168.43.23',master_user='root',master_password='123456',

master_log_file='mysql-bin.000007',master_log_pos=2070;

START SLAVE;

然后执行该语句:SHOW SLAVE STATUS查询到结果yes,yes 说明同步成功

数据同步原理:通过同步2进制sql文件mysql-bin.000007进行同步,包含delete,insert,update等操作记录。


5.安装mycat数据库中间件

什么是mycat

一个彻底开源的,面向企业应用开发的大数据库集群

支持事务、ACID、可以替代MySQL的加强版数据库

一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群

一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQLServer

结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品

一个新颖的数据库中间件产品


5.1.安装mycat(192.168.43.155)

解压  tar zxvfMycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/

移动到/usr/local目录  mv  mycat/usr/local

cd /usr/local/mycat/bin

./mycatstart启动
./mycat stop
停止


5.2配置mycat实现读写分离

# vim /usr/local/mycat/conf/server.xml  //新增2个账号用来登录mycat,添加以下内容

  1. <username="mycatread"> //mycat用户名
  2. <propertyname="password">mycat</property> //mycat密码
  3. <propertyname="schemas">mydb</property> //mycat虚拟数据库名
  4. <propertyname="readOnly">true</property> //只读
  5. </user>
  6. <username="mycat">
  7. <propertyname="password">mycat</property>
  8. <propertyname="schemas">mydb</property>
  9. </user>

在这里要注意,默认的虚拟数据名是TESTDB,如果schema.xml里面没有配置testdb,那就要把testdb改成schema.xml里面有的虚拟数据名。这里定义的用户名和密码,虚拟数据库名,并不是在mysql中真实存在的。

:wq 保存退出

vim schema.xml

配置schema.xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
  3. <mycat:schema xmlns:mycat="http://cat/">
  4. <schema name="mydb" checkSQLschema="false" sqlMaxLimit="100" dataNode="my1" />//定义虚拟数据库名mydb
  5. <dataNode name="my1" dataHost="test1" database="everyday" /> //真实数据库名test
  6. <dataHost name="test1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" >
  7. <heartbeat>select user()</heartbeat>
  8. <writeHost host="hostM1" url="192.168.43.23:3306" user="root" password="123456" > //真实数据库的连接方式
  9. <readHost host="hostS1" url="192.168.43.12:3306" user="root" password="123456" /> //同上
  10. </writeHost>
  11. </dataHost>
  12. </mycat:schema>
mycat的配置参数,相当的多。重点说一下 balance="1"与writeType="0"

a.balance 属性负载均衡类型,目前的取值有 4 种:

1.balance="0",不开启读写分离机制,所有读操作都发送到当前可用的 writeHost上。

2.balance="1",全部的 readHost与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,并且 M1 与M2 互为主备),正常情况下, M2,S1,S2 都参与 select 语句的负载均衡。

3.balance="2",所有读操作都随机的在 writeHost、 readhost 上分发。

4.balance="3", 所有读请求随机的分发到 wiriterHost对应的 readhost 执行,writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有, 1.3 没有。

b.writeType属性

负载均衡类型,目前的取值有 3种:

1.writeType="0",所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个

writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties.

2.writeType="1",所有写操作都随机的发送到配置的 writeHost

3. writeType="2",没实现。

  1. # ./mycat start
  2. Starting Mycat-server...
  3. # netstat -tpnl |grep 8066
  4. tcp 0 0 :::8066 :::* LISTEN 31728/java
  5. # ./mycat status
  6. Mycat-server is running (31726).

6 配置完成之后添加数据测试

登录windows系统中的mysql客户端进行连接

mycat连接方式如下:


 


mycat中间件做读写分离完成


         

7springboot通过application.yml文件配置mycat连接池

项目目录

 

项目依赖pom.xml

  1. <project xmlns="http://maven./POM/4.0.0" xmlns:xsi="http://www./2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven./POM/4.0.0 http://maven./xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.sunyard</groupId>
  5. <artifactId>spboot</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <!--必须要引入继承 spring-boot-starter-parent 帮我们实现很多jar的依赖,不需要写jar版本 -->
  8. <parent>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-parent</artifactId>
  11. <version>1.5.3.RELEASE</version>
  12. </parent>
  13. <dependencies>
  14. <!-- springmvc springboot默认集成,添加springboot-web依赖即可 -->
  15. <dependency>
  16. <groupId>org.springframework.boot</groupId>
  17. <artifactId>spring-boot-starter-web</artifactId>
  18. </dependency>
  19. <!--引入freeMarker依赖 -->
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-freemarker</artifactId>
  23. </dependency>
  24. <!-- 引入mysql驱动jar包 -->
  25. <dependency>
  26. <groupId>mysql</groupId>
  27. <artifactId>mysql-connector-java</artifactId>
  28. </dependency>
  29. <!-- springboo与mybatis整合包 -->
  30. <dependency>
  31. <groupId>org.mybatis.spring.boot</groupId>
  32. <artifactId>mybatis-spring-boot-starter</artifactId>
  33. <version>1.1.1</version>
  34. </dependency>
  35. <!-- jdbc -->
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-jdbc</artifactId>
  39. </dependency>
  40. <!-- yml支持 @ConfigurationProperties 注解 -->
  41. <dependency>
  42. <groupId>org.springframework.boot</groupId>
  43. <artifactId>spring-boot-configuration-processor</artifactId>
  44. </dependency>
  45. </dependencies>
  46. </project>

application.yml

 

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://192.168.43.155:8066/mydb
  4. username: mycat
  5. password: mycat
  6. driverClassName: com.mysql.jdbc.Driver

controller

 

  1. package com.spboot.controller;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.ui.ModelMap;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.servlet.ModelAndView;
  8. import com.spboot.pojo.Ticket;
  9. import com.spboot.service.TicketService;
  10. @Controller
  11. public class TicketController {
  12. @Autowired
  13. private TicketService ticketService;
  14. @RequestMapping("/getTicketList.do")
  15. public ModelAndView getTicketList() {
  16. List<Ticket> ticketList = ticketService.getTicketList();
  17. ModelAndView mav = new ModelAndView();
  18. mav.setViewName("index");
  19. mav.addObject("ticketList", ticketList);
  20. return mav;
  21. };
  22. @RequestMapping("/getFtl.do")
  23. public ModelAndView getFtl(ModelAndView mav) {
  24. mav.addObject("name", "ss");
  25. mav.setViewName("index");
  26. return mav;
  27. };
  28. @RequestMapping("/index")
  29. public String getFtlt(ModelMap map) {
  30. map.addAttribute("name", "你妈");
  31. return "index";
  32. };
  33. }

 

service

  1. package com.spboot.service;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Service;
  5. import com.spboot.mapper.TicketMapper;
  6. import com.spboot.pojo.Ticket;
  7. import com.spboot.utils.common.TimeUtils;
  8. @Service
  9. public class TicketService {
  10. @Autowired
  11. private TicketMapper ticketMapper;
  12. public List<Ticket> getTicketList() {
  13. List<Ticket> ticketList = ticketMapper.getTicketList();
  14. for (Ticket ticket : ticketList) {
  15. String beginTimeStr = TimeUtils.getISOTime(ticket.getBeginTime());
  16. String endTimeStr = TimeUtils.getISOTime(ticket.getEndTime());
  17. ticket.setBeginTimeStr(beginTimeStr);
  18. ticket.setEndTimeStr(endTimeStr);
  19. }
  20. return ticketList;
  21. }
  22. }

 

mapper

 

  1. package com.spboot.mapper;
  2. import java.util.List;
  3. import org.apache.ibatis.annotations.Select;
  4. import com.spboot.pojo.Ticket;
  5. public interface TicketMapper {
  6. @Select("select * from ticket;")
  7. List<Ticket> getTicketList();
  8. }

ticket

 

  1. package com.spboot.pojo;
  2. import java.util.Date;
  3. /**
  4. *
  5. * @ClassName: Ticket
  6. * @Description: 车票信息实体类
  7. * @author wenf.jiao
  8. * @date 2018年1月14日 下午7:29:17
  9. *
  10. */
  11. public class Ticket {
  12. /*
  13. * 车票ID
  14. */
  15. private Integer ticketID;
  16. /*
  17. * 开车地点
  18. */
  19. private String startting;
  20. /*
  21. * 到站地点
  22. */
  23. private String destination;
  24. /*
  25. * 价钱
  26. */
  27. private Integer price;
  28. /*
  29. * 开车时间
  30. */
  31. private Date beginTime;
  32. /*
  33. * 到站时间
  34. */
  35. private Date endTime;
  36. /*
  37. * 开车时间字符串
  38. */
  39. private String beginTimeStr;
  40. /*
  41. * 到站时间字符串
  42. */
  43. private String endTimeStr;
  44. public Integer getTicketID() {
  45. return ticketID;
  46. }
  47. public void setTicketID(Integer ticketID) {
  48. this.ticketID = ticketID;
  49. }
  50. public String getStartting() {
  51. return startting;
  52. }
  53. public void setStartting(String startting) {
  54. this.startting = startting;
  55. }
  56. public String getDestination() {
  57. return destination;
  58. }
  59. public void setDestination(String destination) {
  60. this.destination = destination;
  61. }
  62. public Integer getPrice() {
  63. return price;
  64. }
  65. public void setPrice(Integer price) {
  66. this.price = price;
  67. }
  68. public Date getBeginTime() {
  69. return beginTime;
  70. }
  71. public void setBeginTime(Date beginTime) {
  72. this.beginTime = beginTime;
  73. }
  74. public Date getEndTime() {
  75. return endTime;
  76. }
  77. public void setEndTime(Date endTime) {
  78. this.endTime = endTime;
  79. }
  80. public String getBeginTimeStr() {
  81. return beginTimeStr;
  82. }
  83. public void setBeginTimeStr(String beginTimeStr) {
  84. this.beginTimeStr = beginTimeStr;
  85. }
  86. public String getEndTimeStr() {
  87. return endTimeStr;
  88. }
  89. public void setEndTimeStr(String endTimeStr) {
  90. this.endTimeStr = endTimeStr;
  91. }
  92. }

index.ftl(模板引擎)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Insert title here</title>
  6. </head>
  7. <body>
  8. <div align="center">
  9. <table class="table" border="2">
  10. <thead>
  11. <tr>
  12. <th>车票编号</th>
  13. <th>出发地点</th>
  14. <th>目的地</th>
  15. <th>价钱</th>
  16. <th>发车时刻</th>
  17. <th>到达时刻</th>
  18. </tr>
  19. </thead>
  20. <tbody>
  21. <#list ticketList as ticket>
  22. <tr>
  23. <td>${ticket.ticketID}</td>
  24. <td>${ticket.startting}</td>
  25. <td>${ticket.destination}</td>
  26. <td>${ticket.price}</td>
  27. <td>${ticket.beginTimeStr}</td>
  28. <td>${ticket.endTimeStr}</td>
  29. </tr>
  30. </#list>
  31. </tbody>
  32. </table>
  33. </body>
  34. </html>

全局捕获异常

  1. package com.spboot.spexception;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import org.springframework.core.annotation.AnnotationUtils;
  7. import org.springframework.web.bind.annotation.ControllerAdvice;
  8. import org.springframework.web.bind.annotation.ExceptionHandler;
  9. import org.springframework.web.bind.annotation.ResponseBody;
  10. import org.springframework.web.bind.annotation.ResponseStatus;
  11. /**
  12. *
  13. * @ClassName: GlobalExceptionHandler
  14. * @Description: springboot全局异常捕获
  15. * @author
  16. * @date 2018年1月26日
  17. *
  18. */
  19. @ControllerAdvice
  20. public class GlobalExceptionHandler {
  21. @ResponseBody
  22. @ExceptionHandler(Exception.class)
  23. public Map<String, Object> exceptionHandler(HttpServletRequest request,HttpServletResponse response,Exception e){
  24. if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class)!=null) {
  25. try {
  26. throw e;
  27. } catch (Exception e1) {
  28. e1.printStackTrace();
  29. }
  30. }
  31. Map<String, Object> resMap=new HashMap<>();
  32. resMap.put("url", request.getRequestURL());
  33. resMap.put("class",e.getClass());
  34. resMap.put("cause",e.getCause());
  35. resMap.put("message",e.getMessage());
  36. return resMap;
  37. }
  38. }

application.java

  1. package application;
  2. import org.mybatis.spring.annotation.MapperScan;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  5. import org.springframework.context.annotation.ComponentScan;
  6. /**
  7. *
  8. * @ClassName: application
  9. * @Description: 企业级启动方式
  10. * @author
  11. * @date 2018年1月26日 下午4:27:25
  12. *
  13. */
  14. @ComponentScan(basePackages="com.spboot.*")
  15. @MapperScan(basePackages="com.spboot.*")
  16. @EnableAutoConfiguration
  17. public class Application {
  18. public static void main(String[] args) {
  19. SpringApplication.run(Application.class, args);
  20. }
  21. }

点击右键启动项目,控制台打印如下日志

 访问接口

结果页面

 

 

 

 

 

 

 

 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多