Java猿社区—ShardingSphere-4.0.1之实现读写分离[通俗易懂]

Java猿社区—ShardingSphere-4.0.1之实现读写分离[通俗易懂]Java猿社区—ShardingSphere-4.0.1之实现读写分离文章目录Java猿社区—ShardingSphere-4.0.1之实现读写分离技术体系背景ShardingSphere介绍注意事项ShardingShpere支持的功能数据分片分布式事务技术准备mysql安装配置POM配置读写分离——一主双从mysql配置环境sql脚本配置读写分离application.propertiesM…

大家好,又见面了,我是你们的朋友全栈君。

Java猿社区—ShardingSphere-4.0.1之实现读写分离


参考:


基于Docker的Mysql主从复制搭建


ShardingSphere官网

技术体系

Springboot2.1.5 + shardingsphere4.0.1 + Mysql5.7 + mysql-connector-java5.1.47

背景

目前公司正在进行的在线客服IM项目,考虑未来会话消息请求流量剧增以及消息存储带来的挑战,单一数据库无法支撑,需要分库&分表、读写分离以应对高并发带来的挑战。
基于市面上较为流行的几个数据库中间件我们结合公司技术体系,再三考虑,决定使用ShardingSphere作为在线客服项目的数据库中间件。

ShardingSphere介绍

Apache ShardingSphere(Incubator) 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(规划中)这3款相互独立,却又能够混合部署配合使用的产品组成。它们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、云原生等各种多样化的应用场景。(来自官网)

注意事项

从ShardingSphere推出4.0.0-RC2版本之后,通过属性文件application.properties配置集成是会有问题的:

  1. springboot2.1.5 + mysql-connector-java5.x + shardingsphere-4.0.0-RC1 + mybatis-spring-boot-starter2.0.1版本后功能正常
  2. springboot2.1.5 + mysql-connector-java5.x + shardingsphere-4.0.0-RC2或3或4.0.1 + mybatis-spring-boot-starter2.0.1的时候,第一先报错required a bean of type ‘com.zzx.sharding.mapper.TeamMessageMapper’ that could not be found.,然后再启动类上添加@MapperScan注解后,报错Caused by: java.lang.IllegalArgumentException: Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required

这是shardsphere4.0.0-RC2发布之后的一个bug,具体是数据源没有成功注入。
下面通过手动注入数据源的方式解决此问题。

ShardingShpere支持的功能

数据分片

  • 分库、分表
  • 读写分离
  • 分片策略定制化
  • 无中心化分布式主键

分布式事务

  • 标准化事务接口
  • XA强一致事务
  • 柔性事务

技术准备

mysql安装配置

具体安装配置请参见网络博客:如基于Docker的Mysql主从复制搭建

POM配置

<?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>
<groupId>com.zzx.shardingsphere</groupId>
<artifactId>zzx-shardingsphere</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>db-read-write</module>
<module>db-table-read-write</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<mybatis-spring-boot>2.0.1</mybatis-spring-boot>
<druid>1.1.16</druid>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<shardingsphere.version>4.0.1</shardingsphere.version>
<fastjson.version>1.2.38</fastjson.version>
<mysql-connector-java.version>5.1.47</mysql-connector-java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot}</version>
</dependency>
<!--mybatis驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid}</version>
</dependency>
<!--shardingsphere版本-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
<!--lombok实体工具-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

读写分离——一主双从

mysql配置环境

主库: localhost:3339/im_bis
从库0: localhost:3340/im_bis
从库1: localhost:3341/im_bis

配置从库0和从库1作为主库的从库,具体配置参考上面提到的基于Docker搭建主从复制网站

sql脚本


DROP SCHEMA IF EXISTS im_bis;
CREATE SCHEMA IF NOT EXISTS im_bis;
use im_bis;
/* Navicat Premium Data Transfer Source Server : 192.168.89.53 Source Server Type : MySQL Source Server Version : 50726 Source Host : 192.168.89.53:3306 Source Schema : ddky_im_bis Target Server Type : MySQL Target Server Version : 50726 File Encoding : 65001 Date: 08/03/2020 13:18:39 */
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for im_team_message
-- ----------------------------
DROP TABLE IF EXISTS `im_team_message`;
CREATE TABLE `im_team_message` (
`id` bigint(20) NOT NULL COMMENT '主键id',
`team_msg_id` bigint(20) DEFAULT NULL COMMENT '群消息id(服务端生成消息id)',
`team_client_msg_id` varchar(32) DEFAULT '' COMMENT '群消息id(客户端生成)',
`team_id` varchar(32) DEFAULT '' COMMENT '群组id(对应群组的accid)',
`msg_type` varchar(15) DEFAULT 'TEXT' COMMENT '消息类型:TEXT-文本,PICTURE-图片,AUDIO-音频,VIDEO-视频,FILE-文件,GEO-地理位置,CUSTOM-自定义,TIP-提醒,ROBOT-AI机器人,NOTICATION-群通知,TEAM_INVITE-邀请入群,TEAM_INVITE_REJECT-拒绝邀请,CUSTOM_TEAM_MSG -群组自定义系统通知',
`event_type` tinyint(4) DEFAULT '1' COMMENT '事件类型:1-会话类型消息(p2p消息、群聊消息、自定义系统通知、云信内置系统通知),2-登录事件,3-登出/离线事件,4-聊天室聊天消息,5-音视频时长、白板时长消息,6-音视频白板大小、下载地址消息,7-单聊消息撤回,8-群聊消息撤回,9-汇报主播、管理员进出聊天室事件消息,10-汇报专线电话通话结束回调抄送的消息,11-汇报短信回执抄送的消息,12-汇报短信上行消息,13-汇报用户进出音视频/白板房间的消息,14-汇报聊天室队列操作的事件消息,20-易盾异步反垃圾结果信息',
`remind_type` tinyint(4) DEFAULT '0' COMMENT '提醒类型:0-普通消息,1-客服进入,2-客户进入,3-客服进入欢迎提醒,4-敏感词命中提醒消息',
`conv_type` varchar(20) DEFAULT '' COMMENT '场景类型:TEAM',
`scene` tinyint(4) DEFAULT '0' COMMENT '场景:0-team,1-p2p,2-superTeam',
`text` varchar(5000) DEFAULT '' COMMENT '内容',
`attach` varchar(5000) DEFAULT '' COMMENT '附加消息',
`team_attach_type` tinyint(4) DEFAULT NULL COMMENT '群通知类型:默认null(普通消息),0-更新群,1-拉人入群,2-踢人出群,3-接受入群邀请,4-通过入群邀请,5-添加群管理员,6-移除群管理员,7-主动退群,8-解散群,9-转让群,10-更新群成员禁言状态',
`send_type` tinyint(4) DEFAULT '0' COMMENT '发送人类型:0-用户,1-客服,2-药师,3-医生',
`send_client_ip` varchar(20) DEFAULT '' COMMENT '发送端ip',
`send_client_port` varchar(5) DEFAULT '' COMMENT '发送端端口',
`send_client_type` varchar(10) DEFAULT '' COMMENT '发送客户端类型: AOS、IOS、PC、WINPHONE、WEB、REST',
`send_device_id` varchar(32) DEFAULT '' COMMENT '发送端设备编号',
`send_nick` varchar(50) DEFAULT '' COMMENT '发送人昵称',
`send_id` varchar(32) DEFAULT '' COMMENT '发送人id(对应客服表和用户表的accid)',
`send_at` bigint(11) DEFAULT NULL COMMENT '发送时间',
`msg_receipt_time` bigint(11) DEFAULT NULL COMMENT '已读回执时间戳,如果有此字段, 说明此时间戳之前的所有消息对方均已读',
`is_revoke` tinyint(4) DEFAULT '0' COMMENT '是否撤销:0-否,1-是',
`revoke_at` bigint(11) DEFAULT '0' COMMENT '撤销时间',
`custom_apns_text` varchar(200) DEFAULT '' COMMENT '自定义系统通知消息推送文本。仅在convType为CUSTOM_PERSON或CUSTOM_TEAM时含此字段',
`ext` varchar(64) DEFAULT '' COMMENT '消息扩展字段',
`antispam` varchar(12) DEFAULT '' COMMENT '标识是否被反垃圾(‘’,true,false)',
`yidun_res` varchar(500) DEFAULT '' COMMENT '易盾反垃圾的原始处理细节',
`msg_status` tinyint(4) DEFAULT '0' COMMENT '消息发送状态:0-发送成功,1-发送中,2-发送失败',
`status` tinyint(4) DEFAULT '0' COMMENT '状态:有效 0:无效',
PRIMARY KEY (`id`),
UNIQUE KEY `index_tt` (`id`,`team_msg_id`,`team_client_msg_id`) USING BTREE,
KEY `index_team_id_on_im_team_message` (`team_id`),
KEY `index_send_at_on_im_team_message` (`send_at`)
) ENGINE=InnoDB AUTO_INCREMENT=2104820 DEFAULT CHARSET=utf8mb4 COMMENT='IM消息表';
SET FOREIGN_KEY_CHECKS = 1;

配置读写分离

application.properties
server.port=8888
spring.main.allow-bean-definition-overriding=true
# ---------------------------------
#   mybatis
# ---------------------------------
mybatis.type-aliases-package=com.zzx.sharding.entity
#mybatis.type-handlers-package=com.example.typehandler
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=3000
mybatis.mapper-locations=classpath*:mapper/*.xml
# --------------------------------
#   druid
# ---------------------------------
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.filters=stat,wall,log4j2
spring.datasource.druid.max-active=50
spring.datasource.druid.initial-size=2
spring.datasource.druid.max-wait=60000
spring.datasource.druid.min-idle=2
spring.datasource.druid.keep-alive=true
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.validation-query=select 'x'
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
spring.datasource.druid.pool-prepared-statements=true
spring.datasource.druid.max-open-prepared-statements=20
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;
spring.datasource.druid.use-global-data-source-stat=true
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions='*.gif,*.png,*.jpg,*.html,*.js,*.css,*.ico,/druid/*'
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.reset-enable=true
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
# 配置日志输出
spring.datasource.druid.filter.log4j2.enabled=true
spring.datasource.druid.filter.log4j2.statement-create-after-log-enabled=false
spring.datasource.druid.filter.log4j2.statement-close-after-log-enabled=false
spring.datasource.druid.filter.log4j2.result-set-open-after-log-enabled=false
spring.datasource.druid.filter.log4j2.result-set-close-after-log-enabled=false
# --------------------------------
#   ShardingSphere
# ---------------------------------
spring.shardingsphere.datasource.names=master,slave0,slave1
# 数据源 主库
spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.url=jdbc:mysql://localhost:3339/im_bis?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456
# 数据源 从库
spring.shardingsphere.datasource.slave0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave0.url=jdbc:mysql://localhost:3340/im_bis?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.slave0.username=root
spring.shardingsphere.datasource.slave0.password=123456
# 数据源 从库
spring.shardingsphere.datasource.slave1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave1.url=jdbc:mysql://localhost:3341/im_bis?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=123456
MasterProp
package com.zzx.sharding.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/** * @author zhouzhixiang * @company 叮当快药科技集团有限公司 * @Date 2020-03-15 */
@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.master")
@Data
public class MasterProp { 

private String url;
private String username;
private String password;
private String type;
private String driverClassName;
}
Slave0Prop
package com.zzx.sharding.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/** * @author zhouzhixiang * @company 叮当快药科技集团有限公司 * @Date 2020-03-15 */
@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.slave0")
@Data
public class Slave0Prop { 

private String url;
private String username;
private String password;
private String type;
private String driverClassName;
}
Slave1Prop
package com.zzx.sharding.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/** * @author zhouzhixiang * @company 叮当快药科技集团有限公司 * @Date 2020-03-15 */
@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.slave1")
@Data
public class Slave1Prop { 

private String url;
private String username;
private String password;
private String type;
private String driverClassName;
}
DataSourceConfig
package com.zzx.sharding.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.zzx.sharding.utils.DataSourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.api.config.masterslave.LoadBalanceStrategyConfiguration;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
/** * @author zhouzhixiang */
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@EnableConfigurationProperties({ 
MasterProp.class, Slave0Prop.class, Slave1Prop.class})
@Slf4j
@MapperScan(basePackages = "com.zzx.sharding.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class DataSourceConfig { 

/** * 配置数据源0,数据源的名称最好要有一定的规则,方便配置分库的计算规则 * * @return */
@Bean(name = "master")
public DataSource master(MasterProp masterProp) { 

Map<String, Object> dsMap = new HashMap<>();
dsMap.put("type", masterProp.getType());
dsMap.put("url", masterProp.getUrl());
dsMap.put("username", masterProp.getUsername());
dsMap.put("password", masterProp.getPassword());
dsMap.put("driverClassName", masterProp.getDriverClassName());
DruidDataSource ds = (DruidDataSource) DataSourceUtil.buildDataSource(dsMap);
// 每个分区最大的连接数
ds.setMaxActive(20);
// 每个分区最小的连接数
ds.setMinIdle(5);
return ds;
}
/** * 配置数据源0,数据源的名称最好要有一定的规则,方便配置分库的计算规则 * * @return */
@Bean(name = "slave0")
public DataSource slave0(Slave0Prop slave0Prop) { 

Map<String, Object> dsMap = new HashMap<>();
dsMap.put("type", slave0Prop.getType());
dsMap.put("url", slave0Prop.getUrl());
dsMap.put("username", slave0Prop.getUsername());
dsMap.put("password", slave0Prop.getPassword());
dsMap.put("driverClassName", slave0Prop.getDriverClassName());
DruidDataSource ds = (DruidDataSource) DataSourceUtil.buildDataSource(dsMap);
// 每个分区最大的连接数
ds.setMaxActive(20);
// 每个分区最小的连接数
ds.setMinIdle(5);
return  ds;
}
/** * 配置数据源0,数据源的名称最好要有一定的规则,方便配置分库的计算规则 * * @return */
@Bean(name = "slave1")
public DataSource slave1(Slave1Prop slave1Prop) { 

Map<String, Object> dsMap = new HashMap<>();
dsMap.put("type", slave1Prop.getType());
dsMap.put("url", slave1Prop.getUrl());
dsMap.put("username", slave1Prop.getUsername());
dsMap.put("password", slave1Prop.getPassword());
dsMap.put("driverClassName", slave1Prop.getDriverClassName());
DruidDataSource ds = (DruidDataSource) DataSourceUtil.buildDataSource(dsMap);
// 每个分区最大的连接数
ds.setMaxActive(20);
// 每个分区最小的连接数
ds.setMinIdle(5);
return  ds;
}
@Bean("dataSource")
public DataSource dataSource(@Qualifier("master") DataSource master, @Qualifier("slave0") DataSource slave0, @Qualifier("slave1") DataSource slave1) throws SQLException { 

// 配置真实数据源
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("master", master);
dataSourceMap.put("slave0", slave0);
dataSourceMap.put("slave1", slave1);
List<String> slaveList = new ArrayList<>();
slaveList.add("slave0");
slaveList.add("slave1");
// 从库负载策略
LoadBalanceStrategyConfiguration loadBalanceStrategyConfiguration = new LoadBalanceStrategyConfiguration("round_robin");
MasterSlaveRuleConfiguration masterSlaveRuleConfiguration = new MasterSlaveRuleConfiguration("ms", "master", slaveList, loadBalanceStrategyConfiguration);
// 打开shardingsphere sql日志
Properties properties = new Properties();
properties.setProperty("sql.show", Boolean.TRUE.toString());
// 配置分片规则
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
//TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration("t_order", "ds${0..1}.t_order_${0..1}");
// 配置分库 + 分表策略
//orderTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}"));
//orderTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_${order_id % 2}"));
//shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);
shardingRuleConfig.getMasterSlaveRuleConfigs().add(masterSlaveRuleConfiguration);
shardingRuleConfig.getTableRuleConfigs().add(getImTeamMessageRuleConfiguration());
// 获取数据源对象
DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, properties);
return dataSource;
}
/** 消息表——im_team_message */
TableRuleConfiguration getImTeamMessageRuleConfiguration() { 

TableRuleConfiguration result = new TableRuleConfiguration("im_team_message");
result.setKeyGeneratorConfig(getImTeamMessageKeyGeneratorConfiguration());
return result;
}
private static KeyGeneratorConfiguration getImTeamMessageKeyGeneratorConfiguration() { 

KeyGeneratorConfiguration result = new KeyGeneratorConfiguration("SNOWFLAKE", "id");
return result;
}
/** 消息表——im_team_message */
@Bean
public DataSourceTransactionManager shardTransactionManager(@Qualifier("dataSource") DataSource dataSource) { 

return new DataSourceTransactionManager(dataSource);
}
@Bean("sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception { 

SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
return bean.getObject();
}
@Bean("sqlSessionTemplate")
@Primary
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { 

return new SqlSessionTemplate(sqlSessionFactory);
}
}

验证

添加数据——写入主库

postman执行: localhost:8888/teamMessage/batchAdd

代码

@PostMapping("batchAdd")
public ServiceResponse batchAdd(HttpServletRequest request, HttpServletResponse response) throws IOException { 

ServiceResponse result = new ServiceResponse<>();
for (int i = 0; i < 20; i++) { 

TeamMessage vo = new TeamMessage();
vo.setSendAt(new Date().getTime());
vo.setTeamId(1000);
vo.setTeamClientMsgId(UUID.randomUUID().toString());
vo.setTeamMsgId(SnowIdUtils.uniqueLong());
vo.setId(SnowIdUtils.uniqueLong());
vo.setText("消息内容-"+UUID.randomUUID());
this.teamMessageServiceApi.insert(vo);
}
result.setCode(ResponseEnum.SUCCESS.getCode());
result.setMsg(ResponseEnum.SUCCESS.getName());
return result;
}

shardingsphere日志

2020-03-11 11:19:24.865  INFO 39211 --- [nio-8888-exec-2] ShardingSphere-SQL : Rule Type: master-slave
2020-03-11 11:19:24.865  INFO 39211 --- [nio-8888-exec-2] ShardingSphere-SQL : SQL: INSERT IGNORE INTO
INSERT IGNORE INTO im_team_message ( id, team_msg_id, team_client_msg_id, remind_type, scene, text, team_attach_type, send_type, team_id, send_at, is_revoke, msg_status, STATUS )
VALUES
( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ::: DataSources: master

写入主库成功
在这里插入图片描述

查询数据——从库查询

查询所有数据
在这里插入图片描述

从库负载均衡算法类型为轮询
控制台sql日志(从从库0查询数据):

SELECT
id,
team_msg_id,
team_client_msg_id,
msg_type,
remind_type,
conv_type,
scene,
text,
team_attach_type,
send_type,
send_client_ip,
send_client_port,
send_client_type,
send_device_id,
send_nick,
team_id,
send_id,
send_at,
msg_receipt_time,
is_revoke,
revoke_at,
msg_status,
event_type,
STATUS,
attach,
custom_apns_text,
ext,
antispam,
yidun_res 
FROM
im_team_message 
WHERE
STATUS = 0 			
::: DataSources: slave0

控制台sql日志(从从库1查询数据):

SELECT
id,
team_msg_id,
team_client_msg_id,
msg_type,
remind_type,
conv_type,
scene,
text,
team_attach_type,
send_type,
send_client_ip,
send_client_port,
send_client_type,
send_device_id,
send_nick,
team_id,
send_id,
send_at,
msg_receipt_time,
is_revoke,
revoke_at,
msg_status,
event_type,
STATUS,
attach,
custom_apns_text,
ext,
antispam,
yidun_res 
FROM
im_team_message 
WHERE
STATUS = 0 			
::: DataSources: slave1

成功!

问题记录

springboot2.1.5默认使用mysql-connECTOR-java8.x的版本,这个版本的驱动使用shardingsphere时会有bug,推荐使用mysql-connector-java5.1.47版本


欢迎加入Java猿社区!


免费领取我历年收集的所有学习资料哦!

欢迎加入Java猿社区.png

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144594.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • pytest 执行用例_测试用例一般执行多少次

    pytest 执行用例_测试用例一般执行多少次前言平常我们功能测试用例非常多时,比如有1千条用例,假设每个用例执行需要1分钟,如果单个测试人员执行需要1000分钟才能跑完当项目非常紧急时,会需要协调多个测试资源来把任务分成两部分,于是执行时间

  • Java中finalize方法

    Java中finalize方法前沿:在面试过程中我们可能会被问到final、finally、finalize的区别?本篇文章将介绍finalize的简单用法。Finalize()是Object类的方法。在回收垃圾对象之前调用此方法。finalize()方法将重写以处理系统资源,执行清理活动并最大程度地减少内存泄漏。简单来说可在释放对象前进行某些操作。代码举例:…

  • linux下的find文件查找命令与grep文件内容查找命令

    linux下的find文件查找命令与grep文件内容查找命令

    2021年10月14日
  • 回溯算法之N皇后问题[通俗易懂]

    回溯算法之N皇后问题[通俗易懂]问题描述什么是皇后问题八皇后问题(英文:Eightqueens),是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语

  • Lenovo windows 解决win键失灵

    Lenovo windows 解决win键失灵电脑突然win键就不能用了,实在太影响使用了!!!上网查了查,估计是把win键锁住了要解锁的话,好像不同的电脑不太一样我的电脑是lenovo的F9+Fn就能开关win键如果不可以的话,建议按住Fn键其他的组合键挨个试一下。…

  • 《JavaScript 模式》读书笔记(6)— 代码复用模式2「建议收藏」

    上一篇讲了最简单的代码复用模式,也是最基础的,我们普遍知道的继承模式,但是这种继承模式却有不少缺点,我们下面再看看其它可以实现继承的模式。四、类式继承模式#2——借用构造函数本模式解决了从子构造函

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号