当前位置: 首页 > news >正文

电子商务网站设计流程vuejs做视频网站

电子商务网站设计流程,vuejs做视频网站,网站建设微信小程序开发,云南住房和城乡建设厅网站基于mysql集群&mybatis-plus动态数据源实现数据库读写分离和从库负载均衡教程(详细案例) 本案例基于 Spring Boot 2.7.x MyBatis-Plus 3.5.x MySQL 8.0 实现,包含完整的项目搭建、配置、代码编写和测试验证,适合中小型项目快…

基于mysql集群&mybatis-plus动态数据源实现数据库读写分离和从库负载均衡教程(详细案例)

本案例基于 Spring Boot 2.7.x + MyBatis-Plus 3.5.x + MySQL 8.0 实现,包含完整的项目搭建、配置、代码编写和测试验证,适合中小型项目快速落地读写分离。

一、环境准备

1. 数据库环境(已搭建的主从集群)

角色IP地址数据库账号权限说明
主库192.168.1.100root/Root@123456读写权限(处理写请求)
从库1192.168.1.101read_user/Read@123456只读权限(仅SELECT,处理读请求)
从库2192.168.1.102read_user/Read@123456只读权限(仅SELECT,处理读请求)

2. 项目依赖(pom.xml)

创建 Spring Boot 项目,在 pom.xml 中引入核心依赖(动态数据源、MyBatis-Plus、MySQL 驱动等):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.15</version> <!-- 稳定版 --><relativePath/></parent><groupId>com.example</groupId><artifactId>mysql-read-write-split</artifactId><version>1.0-SNAPSHOT</version><dependencies><!-- Spring Boot Web(用于测试接口) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis-Plus 核心依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4.1</version></dependency><!-- 动态数据源插件(实现读写分离核心) --><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.6.1</version></dependency><!-- MySQL 驱动(适配 MySQL 8.0) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><!-- Lombok(简化实体类代码) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Spring Boot 测试(用于单元测试) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>

二、核心配置(application.yml)

src/main/resources/application.yml 中配置 多数据源、负载均衡策略、MyBatis-Plus 等核心参数:

# 服务端口
server:port: 8080# 数据库配置(动态数据源)
spring:datasource:dynamic:primary: master  # 默认数据源(写请求默认走主库)strict: false    # 非严格模式:找不到指定数据源时,自动使用primary数据源load-balance: round_robin  # 从库负载均衡策略:round_robin(轮询)、random(随机)health: true     # 开启数据源健康检测(故障从库自动剔除)health-timeout: 3000  # 健康检测超时时间(毫秒)# 多数据源列表datasource:# 主库数据源(处理写请求)master:url: jdbc:mysql://192.168.1.100:3306/test?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: rootpassword: Root@123456driver-class-name: com.mysql.cj.jdbc.Driver# 从库1数据源(处理读请求)slave1:url: jdbc:mysql://192.168.1.101:3306/test?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: read_userpassword: Read@123456driver-class-name: com.mysql.cj.jdbc.Driver# 从库2数据源(处理读请求)slave2:url: jdbc:mysql://192.168.1.202:3306/test?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: read_userpassword: Read@123456driver-class-name: com.mysql.cj.jdbc.Driver# 数据源分组(将从库归为一组,实现负载均衡)datasource-group:slave_group: slave1,slave2  # slave_group组包含slave1和slave2# MyBatis-Plus 配置
mybatis-plus:mapper-locations: classpath*:mapper/**/*.xml  # Mapper.xml文件路径type-aliases-package: com.example.entity       # 实体类包路径configuration:map-underscore-to-camel-case: true  # 开启下划线转驼峰(如user_name -> userName)log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 打印SQL日志(方便测试验证)

三、代码编写(分层实现)

实体类 → Mapper → Service → Controller 分层编写代码,核心通过 @DS 注解指定数据源。

1. 实体类(Entity)

对应数据库 test 库的 user 表(提前在主库创建表):

package com.example.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.time.LocalDateTime;/*** 用户实体类(对应test.user表)*/
@Data
@TableName("user")  // 关联数据库表名
public class User {@TableId(type = IdType.AUTO)  // 主键自增private Long id;              // 用户IDprivate String username;      // 用户名private String password;      // 密码(实际项目需加密存储)private Integer age;          // 年龄private LocalDateTime createTime;  // 创建时间(默认当前时间)
}

2. 数据库表创建(主库执行)

在主库 test 库中创建 user 表(从库会自动同步):

CREATE TABLE IF NOT EXISTS `user` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',`username` varchar(50) NOT NULL COMMENT '用户名',`password` varchar(100) NOT NULL COMMENT '密码',`age` int DEFAULT NULL COMMENT '年龄',`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

3. Mapper 接口(数据访问层)

继承 MyBatis-Plus 的 BaseMapper,无需手动写 SQL(简单CRUD):

package com.example.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;/*** User Mapper 接口(MyBatis-Plus自动实现CRUD)*/
@Mapper  // 标记为MyBatis Mapper接口
public interface UserMapper extends BaseMapper<User> {// 无需额外方法,BaseMapper已提供:insert、deleteById、updateById、selectById、selectList等
}

4. Service 层(业务逻辑层)

核心层:通过 @DS 注解指定数据源,实现读写分离与负载均衡。

4.1 Service 接口
package com.example.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.User;import java.util.List;/*** User Service 接口*/
public interface UserService extends IService<User> {// 写操作:新增用户(走主库)boolean addUser(User user);// 读操作:按ID查询用户(走从库集群,负载均衡)User getUserById(Long id);// 读操作:查询所有用户(走从库1,指定单个从库)List<User> listAllUserFromSlave1();// 读操作:按年龄查询用户(走从库2,指定单个从库)List<User> listUserByAge(Integer age);
}
4.2 Service 实现类(核心:@DS 注解使用)
package com.example.service.impl;import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import com.example.service.UserService;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;/*** User Service 实现类* 关键:@DS注解指定数据源,未指定则默认走primary(master)*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {/*** 写操作:新增用户* 未加@DS注解 → 默认走primary(master主库),符合"写请求走主库"原则*/@Overridepublic boolean addUser(User user) {return save(user);  // MyBatis-Plus提供的save方法(INSERT操作)}/*** 读操作:按ID查询用户* @DS("slave_group") → 走从库集群(slave1和slave2),按轮询策略负载均衡*/@Override@DS("slave_group")public User getUserById(Long id) {return getById(id);  // MyBatis-Plus提供的getById方法(SELECT操作)}/*** 读操作:查询所有用户* @DS("slave1") → 强制走slave1从库*/@Override@DS("slave1")public List<User> listAllUserFromSlave1() {return list();  // MyBatis-Plus提供的list方法(SELECT * FROM user)}/*** 读操作:按年龄查询用户* @DS("slave2") → 强制走slave2从库* 自定义SQL(需在Mapper.xml中编写)*/@Override@DS("slave2")public List<User> listUserByAge(Integer age) {// 调用Mapper自定义方法(参数用Map传递,或用@Param注解)return baseMapper.selectListByAge(age);}
}

5. Mapper 自定义 SQL(可选,复杂查询)

若需要复杂查询(如按条件筛选),在 src/main/resources/mapper/UserMapper.xml 中编写 SQL:

<?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.example.mapper.UserMapper"><!-- 自定义查询:按年龄查询用户 --><select id="selectListByAge" resultType="com.example.entity.User">SELECT id, username, password, age, create_time AS createTimeFROM userWHERE age = #{age}</select></mapper>

同时在 UserMapper 接口中添加对应方法:

// UserMapper.java 中新增方法
List<User> selectListByAge(@Param("age") Integer age);

6. Controller 层(接口层,用于测试)

编写 REST 接口,通过 Postman 或浏览器测试读写分离效果:

package com.example.controller;import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** User 控制器(测试读写分离接口)*/
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;/*** 1. 写操作:新增用户(走主库)* 请求方式:POST* 请求体:{"username":"test1","password":"123456","age":20}*/@PostMapping("/add")public String addUser(@RequestBody User user) {boolean success = userService.addUser(user);return success ? "新增用户成功(走主库)" : "新增用户失败";}/*** 2. 读操作:按ID查询用户(走从库集群,负载均衡)* 请求方式:GET* 示例:http://localhost:8080/user/get/1*/@GetMapping("/get/{id}")public User getUserById(@PathVariable Long id) {User user = userService.getUserById(id);return user;}/*** 3. 读操作:查询所有用户(走slave1从库)* 请求方式:GET* 示例:http://localhost:8080/user/list/slave1*/@GetMapping("/list/slave1")public List<User> listAllUserFromSlave1() {return userService.listAllUserFromSlave1();}/*** 4. 读操作:按年龄查询用户(走slave2从库)* 请求方式:GET* 示例:http://localhost:8080/user/list/age?age=20*/@GetMapping("/list/age")public List<User> listUserByAge(@RequestParam Integer age) {return userService.listUserByAge(age);}
}

四、项目启动类

添加 @MapperScan 注解,扫描 Mapper 接口:

package com.example;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** 项目启动类*/
@SpringBootApplication
@MapperScan("com.example.mapper")  // 扫描Mapper接口所在包
public class MysqlReadWriteSplitApplication {public static void main(String[] args) {SpringApplication.run(MysqlReadWriteSplitApplication.class, args);}}

五、测试验证(核心步骤)

启动项目后,通过 SQL日志数据库数据 验证读写分离与负载均衡效果。

1. 验证“写操作走主库”

步骤1:调用新增用户接口

用 Postman 发送 POST 请求:

  • URL:http://localhost:8080/user/add
  • 请求体:
    {"username": "test_user1","password": "123456","age": 25
    }
    
步骤2:查看 SQL 日志

控制台会打印新增用户的 SQL,且数据源为 master

JDBC Connection [com.zaxxer.hikari.HikariProxyConnection@xxxx] will be used by dynamic datasource
==>  Preparing: INSERT INTO user ( username, password, age, create_time ) VALUES ( ?, ?, ?, ? )
==> Parameters: test_user1(String), 123456(String), 25(Integer), 2025-09-10T10:00:00(LocalDateTime)
<==  Updates: 1
步骤3:验证主从数据同步
  • 主库查询:SELECT * FROM test.user; → 能看到 test_user1
  • 从库1/2查询:SELECT * FROM test.user; → 也能看到 test_user1(主从同步生效)。

2. 验证“读操作走从库集群(负载均衡)”

步骤1:多次调用“按ID查询”接口

用浏览器或 Postman 多次访问:http://localhost:8080/user/get/1(假设新增用户的ID为1)。

步骤2:查看 SQL 日志(轮询效果)

第一次请求:数据源为 slave1

JDBC Connection [com.zaxxer.hikari.HikariProxyConnection@xxxx] will be used by dynamic datasource : slave1
==>  Preparing: SELECT id,username,password,age,create_time AS createTime FROM user WHERE id=?
==> Parameters: 1(Long)
<==  Total: 1

第二次请求:数据源自动切换为 slave2(轮询策略生效):

JDBC Connection [com.zaxxer.hikari.HikariProxyConnection@xxxx] will be used by dynamic datasource : slave2
==>  Preparing: SELECT id,username,password,age,create_time AS createTime FROM user WHERE id=?
==> Parameters: 1(Long)
<==  Total: 1

第三次请求:又切换回 slave1,以此循环,证明从库负载均衡生效。

3. 验证“指定从库读取”

步骤1:调用“查询所有用户(slave1)”接口

访问:http://localhost:8080/user/list/slave1,日志显示数据源为 slave1

JDBC Connection [com.zaxxer.hikari.HikariProxyConnection@xxxx] will be used by dynamic datasource : slave1
==>  Preparing: SELECT id,username,password,age,create_time AS createTime FROM user
==> Parameters: 
<==  Total: 1
步骤2:调用“按年龄查询(slave2)”接口

访问:http://localhost:8080/user/list/age?age=25,日志显示数据源为 slave2

JDBC Connection [com.zaxxer.hikari.HikariProxyConnection@xxxx] will be used by dynamic datasource : slave2
==>  Preparing: SELECT id, username, password, age, create_time AS createTime FROM user WHERE age = ?
==> Parameters: 25(Integer)
<==  Total: 1

六、常见问题处理

1. 从库连接失败(日志显示“Access denied”)

  • 原因:从库 read_user 账号密码错误,或未授予 SELECT 权限。
  • 解决:在从库执行授权语句:
    -- 从库执行:授予read_user只读权限
    GRANT SELECT ON test.* TO 'read_user'@'%' IDENTIFIED WITH mysql_native_password BY 'Read@123456';
    FLUSH PRIVILEGES;
    

2. 负载均衡不生效(始终走同一个从库)

  • 原因:application.yml 中未配置 datasource-group,或 @DS 注解指定的是单个从库(如 @DS("slave1"))。
  • 解决:确保 datasource-group 配置正确,且读操作注解为 @DS("slave_group")

3. 主从延迟导致读不到新数据

  • 原因:主库写入后,数据同步到从库有延迟(如1秒),立即读从库会看到旧数据。
  • 解决:核心读请求(如“刚新增完用户就查询”)强制走主库,添加 @DS("master") 注解:
    @Override
    @DS("master")  // 强制走主库,避免主从延迟
    public User getNewUserById(Long id) {return getById(id);
    }
    

七、总结

本案例通过 MyBatis-Plus 动态数据源插件 实现了:

  1. 读写分离:写操作默认走主库,读操作通过 @DS 注解走从库;
  2. 从库负载均衡:从库集群(slave_group)按轮询策略分发读请求;
  3. 灵活路由:支持指定单个从库(如 @DS("slave1"))或强制走主库(如 @DS("master"))。

该方案无需额外中间件,代码侵入性低,适合中小型 Spring Boot 项目快速落地读写分离,且后续可通过自定义负载均衡策略(如权重)进一步优化。

http://www.dtcms.com/a/536782.html

相关文章:

  • 新手做网站需要哪些软件thinkphp旅游网站源码
  • 漳州市城乡建设局网站6wordpress自定义排版
  • Falco:云原生世界中的安全守护者
  • 塘沽做网站的公司电子商城市场
  • 一篇文章详解Kafka Broker
  • Vue3 创建项目
  • 怎样注册自己网站公司企业网站制作需要多少钱
  • 京东网站建设吗做宣传的网站
  • 单细胞空间--纤维相关蛋白阳性成纤维细胞调控伴瘤栓肾细胞癌的肿瘤微环境重构
  • Visual Studio 2022打包生成exe安装程序
  • 做造价在哪个网站查价格建筑公司年度工作总结报告
  • 现代化专业群建设专题网站搬瓦工wordpress建站
  • PostgreSQL PostGIS中的元数据表
  • ProcDump 学习笔记(6.11):以非交互方式运行 ProcDump(服务器/生产环境指南)
  • yolov4和yolov5(yolov4的工业化)
  • 手写线程池第1弹:深入理解线程池:从原理到实战,手写高性能线程池的完整指南
  • 网站没有域名电子商务网站硬件建设的核心
  • 上海 松江 网站制作南通做网站
  • 如何在 Spring Boot 项目中使用 @Slf4j 注解结合 Logback 进行系统日志管理
  • SQLite 事务
  • 第 1 章 JVM 和 Java 体系架构_java 字节码
  • MarketUP营销自动化核心方法:从数据驱动到全链路增
  • 沙田镇仿做网站网站价格
  • 信创背景下,中职计算机网络专业人才培养方案探讨
  • 且网站制作开源系统有哪些
  • AR智能巡检:电力运维的“透视眼”与“超级大脑”
  • 漳州电脑网站建设西安市建设网
  • 从冷换仓到热追踪:项目方如何在不暴露风险的前提下守住主动权
  • 机器人运动控制中的 Actor-Critic 强化学习预训练
  • [人工智能-大模型-97]:大模型应用层 - 随着技术的发展,软件工程与软件开发过程提效演进阶段(工具化 → 流程化 → 智能化)和未来的展望。