单一架构
- 一个应用服务器和一个数据库

缺点:如果出现硬件故障或自然灾害可能会导致数据全部丢失,造成一定的损失
定时备份数据?
如果数据库存储的数据太多,比如 G 级别的数据,每次备份耗时很长且备份要占用大量的空间
主从架构
了解
也叫主备架构
- master/slave
- 或 master/backup
使用场景:从节点仅用来做备份,不对外提供服务
原理:主节点使用 binlog 记录操作日志,将其同步给从节点进行备份(单向异步)
菊花链:每个节点也可以有从节点,树状结构,高度无限制
小实验
准备
配置每个节点的同步信息,保证 server-id 唯一
配置文件:/etc/mysql/mysql.conf.d/mysqld.cnf
比如主节点的配置:
从节点配置一样,只用保证 server-id 两两不相同即可
主节点
查看 server-id 是否配置成功mysql> show variables like 'server_id';
查看作为主节点时的节点状态mysql> show master status;
File 和 Position 两个属性在从节点上要用到(告诉从节点从哪里开始同步)
从节点
指定要同步的主节点信息,包括主机信息、连接信息、文件、开始位置
change master tomaster_host='192.168.241.128',master_user='root',master_password='mysql123!ROOT',master_log_file='mysql-bin.000001',master_log_pos=157;

开启同步mysql> start slave;
mysql> stop slave;
查看从节点状态mysql> show slave status\G;
非上图结果,且 Slave_IO_Running 为 NO,且出错:Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. 原因:虚拟机克隆导致多个机器的
/var/lib/mysql/auto.cnf文件相同,而这个文件记录 server-uuid,多机的 uuid 不能相同,应该把该文件删掉,再次启动 mysql 时会自动生成 操作:删掉“克隆机”中的 /var/lib/mysql/auto.cnf,重启 mysql,发现每个机器又生成了一个 auto.cnf 且内容不同 注意:重启 mysql 不用再配置上边的【指定主节点信息】和【开始同步】 配置完后,重新启动,成功
验证
在主节点(192.168.241.128)上创建数据库、创建表、添加记录
查看从节点(192.168.241.129),发现他已经同步成功
MySQL集群
主从架构扩展与 MySQL 集群:https://blog.csdn.net/qq_45453266/article/details/113871739
MySQL 各集群方案:https://www.cnblogs.com/lgx211/p/12456859.html
读写分离架构
使用MyCat实现读写分离
基于上边的【主从架构】
MyCat 官网:http://www.mycat.org.cn/(mycat2)
使用 mycat 1.6 http://www.mycat.org.cn/mycat1.html(目前已有 mycat2,功能更丰富;mycat1 比较稳定)
⭐MyCat 1 wiki:https://github.com/MyCATApache/Mycat-Server/wiki
读写分离架构:让从库分担一部分服务,减轻主节点的并发压力。一般来说读操作由从节点来处理,写操作由主节点处理。
准备两台 mysql 5.7,且配置成主从架构(master:192.168.241.128,slave:192.168.241.129)
下载 mycat 1.6.x,解压
修改 schema.xml
<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://io.mycat/"><!--定义mycat逻辑库,dataNode属性记录数据节点名(一个标签)--><schema name="mycatdb" checkSQLschema="false" sqlMaxLimit="300" dataNode="myDataNode"></schema><!--定义数据节点,name属性即数据节点的名字,dataHost属性记录真实主机名(一个标签),--><!-- database属性记录真实的库,即我们的库(这里product是一个商品库)--><dataNode name="myDataNode" dataHost="myDataHost" database="product" /><!--定义数据主机,name属性即数据主机的名字--><dataHost name="myDataHost" maxCon="1000" minCon="10" balance="1"writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100"><!--心跳检测--><heartbeat>select user()</heartbeat><!--主节点--><writeHost host="hostMaster1" url="192.168.241.128:3306" user="root" password="mysql123!ROOT"><!--从节点--><readHost host="hostSlave1" url="192.168.241.129:3306" user="root" password="mysql123!ROOT" /></writeHost></dataHost></mycat:schema>
修改 server.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mycat:server SYSTEM "server.dtd"><mycat:server xmlns:mycat="http://io.mycat/"><system><property name="defaultSqlParser">druidparser</property><property name="charset">utf8</property></system><!--配置用户信息,name属性指定用户名,password属性指定密码,schemas指定schemas.xml中定义的schema.name--><user name="root"><property name="password">mycat123!ROOT</property><property name="schemas">mycatdb</property></user></mycat:server>
编写业务类(注意声明式事务传播策略的使用)
@Servicepublic class ProductService {@AutowiredProductMapper productMapper;/*这个业务方法不使用事务,会去从库查询。如何验证?修改从库数据,使其区别于主库,查询数据,看来自哪里注:如果使用默认的REQUIRED传播策略,则会查询主库。因为会使用事务,被判定为可能包含修改操作*/@Transactional(propagation = Propagation.SUPPORTS)public List<Product> findAll() {return productMapper.findAll();}/*这个业务方法会使用事务,且为 update 语句,会去主库操作如何验证?主从库都发生了这个修改,说明修改的是主库*/@Transactional(propagation = Propagation.REQUIRED)public int decreaseStore(Integer id) {return productMapper.decreaseStore(id);}}
测试查询和修改
@SpringBootTest(classes = Main.class)@RunWith(SpringRunner.class)public class T {@AutowiredProductService productService;@Testpublic void t1() {productService.findAll().forEach(System.out::println);}@Testpublic void t2() {System.out.println(productService.decreaseStore(1));}}
注意点 1:需要使用 5.x 版本的 mysql 驱动(MySQL驱动版本和MySQL版本最好都是 5.x,不然很难配)
注意点 2:配置连接信息时,需指定 mycat 地址,其端口号为 8066,数据库为 schema.name
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://192.168.241.130:8066/mycatdb?characterEncoding=UTF-8&useSSL=falsedriver-class-name: com.mysql.jdbc.Driverusername: rootpassword: mycat123!ROOTmybatis:mapper-locations: classpath:/mybatis/mapper/*Mapper.xmltype-aliases-package: im.engure.entity
原本我的机器上装的是 mysql 8,但是 mysql 1.6 默认使用 5.x 版本的驱动,mycat 连接 mysql 8.x 产生了很多的兼容性问题 于是在一台 docker 上搭建了两台 5.7 版本的 mysql,用他们两个搭建主从复制架构。思路:使用 —link 建立容器关联,部分命令如下图
- 创建两个容器。第一个为 master,第二个为 slave,且后者依赖前者
- 在 salve 上指定 master,不通过 ip 指定(写死了),而是通过容器名指定(因为上边用了 —link=xxx)
源代码:https://gitee.com/engureguo/mybatis-cache-with-redis 的 check-mycat


