news 2026/5/6 5:36:07

【ShardingJDBC 】【实战】----- SpringBoot3 整合 ShardingJDBC 做分库分表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【ShardingJDBC 】【实战】----- SpringBoot3 整合 ShardingJDBC 做分库分表

文章目录

  • Spring Boot 3 整合 Sharding-JDBC 分库分表实现
    • Nacos配置中心配置
    • Sharding-JDBC 配置类
    • SysMessage 实体类
    • mapper类
    • 服务接口类
    • 服务接口
    • 实现说明

基于spring boot3 + lombok 1.18.30 + mybatis plus 3.5.5 +nacos

Spring Boot 3 整合 Sharding-JDBC 分库分表实现

根据需求,我们需要实现两个核心功能:

  1. 分库:将聊天记录库和用户业务库分离 (提高主业务吞吐量)
  2. 分表:聊天记录表按用户ID(deviceId)分为10个表 (保证单表不超过500万数据量)

下面是核心配置和业务代码实现:

Nacos配置中心配置

在Nacos中需要添加以下配置(dataId可以是application-dev.yml等):

spring:shardingsphere:# 数据源配置datasource:# 定义所有数据源名称,多个用逗号分隔names:user_db,message_db# 用户数据库配置user_db:type:com.zaxxer.hikari.HikariDataSource# 使用Hikari连接池driver-class-name:com.mysql.cj.jdbc.Driver# MySQL驱动类url:jdbc:mysql://localhost:3306/user_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai# 数据库连接地址username:root# 数据库用户名password:root# 数据库密码# 消息数据库配置message_db:type:com.zaxxer.hikari.HikariDataSource# 使用Hikari连接池driver-class-name:com.mysql.cj.jdbc.Driver# MySQL驱动类url:jdbc:mysql://localhost:3306/message_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai# 数据库连接地址username:root# 数据库用户名password:root# 数据库密码# 分片规则配置rules:sharding:# 表级别的分片配置tables:# 逻辑表名称:sys_messagesys_message:# 实际数据节点:由数据库名+表名表达式组成,这里表示message_db库中的sys_message_0到sys_message_9表actual-data-nodes:message_db.sys_message_${0..9}# 表分片策略table-strategy:# 标准分片策略standard:sharding-column:deviceId# 分片键:使用deviceId字段进行分片sharding-algorithm-name:sys_message_inline# 引用的分片算法名称# 分片算法配置sharding-algorithms:# 与上面引用的算法名称保持一致sys_message_inline:type:INLINE# 算法类型:INLINE表示使用行表达式分片算法props:# 分片算法表达式:# 1. 先计算deviceId的哈希值对10取模# 2. 处理可能出现的负数情况(当哈希值为负数时,取模结果可能为负)# 3. 确保最终结果在0-9之间,对应sys_message_0到sys_message_9表algorithm-expression:sys_message_${deviceId.hashCode() % 10 + 10 >= 10 ? deviceId.hashCode() % 10:deviceId.hashCode() % 10 + 10}

Sharding-JDBC 配置类

packagecom.zgb.config;importorg.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;importorg.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;importorg.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;importorg.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;importorg.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importcom.alibaba.nacos.api.config.annotation.NacosValue;importjavax.sql.DataSource;importjava.sql.SQLException;importjava.util.HashMap;importjava.util.Map;importjava.util.Properties;/** * Sharding-JDBC 配置类,用于配置分库分表规则 * 从Nacos配置中心获取数据源和分片规则配置 */@ConfigurationpublicclassShardingJdbcConfig{/** * 用户业务库数据源配置,从Nacos获取 */@NacosValue("${spring.shardingsphere.datasource.user.url}")privateStringuserDbUrl;@NacosValue("${spring.shardingsphere.datasource.user.username}")privateStringuserDbUsername;@NacosValue("${spring.shardingsphere.datasource.user.password}")privateStringuserDbPassword;@NacosValue("${spring.shardingsphere.datasource.user.driver-class-name}")privateStringuserDbDriverClassName;/** * 聊天记录库数据源配置,从Nacos获取 */@NacosValue("${spring.shardingsphere.datasource.message.url}")privateStringmessageDbUrl;@NacosValue("${spring.shardingsphere.datasource.message.username}")privateStringmessageDbUsername;@NacosValue("${spring.shardingsphere.datasource.message.password}")privateStringmessageDbPassword;@NacosValue("${spring.shardingsphere.datasource.message.driver-class-name}")privateStringmessageDbDriverClassName;/** * 配置ShardingSphere数据源 * * @return 配置好的ShardingSphere数据源 * @throws SQLException 数据库配置异常 */@BeanpublicDataSourcedataSource()throwsSQLException{// 1. 配置数据源Map<String,DataSource>dataSources=newHashMap<>(2);dataSources.put("user_db",createDataSource(userDbUrl,userDbUsername,userDbPassword,userDbDriverClassName));dataSources.put("message_db",createDataSource(messageDbUrl,messageDbUsername,messageDbPassword,messageDbDriverClassName));// 2. 配置分片规则ShardingRuleConfigurationshardingRuleConfig=newShardingRuleConfiguration();// 2.1 配置消息表分表规则shardingRuleConfig.getTables().add(getSysMessageTableRuleConfiguration());// 2.2 配置分库策略(按业务类型)shardingRuleConfig.setDefaultDatabaseShardingStrategy(newStandardShardingStrategyConfiguration("database_type","db_inline"));// 2.3 配置分片算法shardingRuleConfig.getShardingAlgorithms().put("table_inline",newAlgorithmConfiguration("INLINE",getTableShardingAlgorithmProperties()));shardingRuleConfig.getShardingAlgorithms().put("db_inline",newAlgorithmConfiguration("INLINE",getDbShardingAlgorithmProperties()));// 3. 创建并返回ShardingSphere数据源returnShardingSphereDataSourceFactory.createDataSource(dataSources,shardingRuleConfig,newProperties());}/** * 配置sys_message表的分表规则 * * @return 消息表的分片规则配置 */privateShardingTableRuleConfigurationgetSysMessageTableRuleConfiguration(){ShardingTableRuleConfigurationtableRuleConfig=newShardingTableRuleConfiguration("sys_message","message_db.sys_message_${0..9}");// 按deviceId进行分表tableRuleConfig.setTableShardingStrategy(newStandardShardingStrategyConfiguration("deviceId","table_inline"));returntableRuleConfig;}/** * 创建数据源 * * @param url 数据库连接地址 * @param username 数据库用户名 * @param password 数据库密码 * @param driverClassName 数据库驱动类名 * @return 配置好的数据源 */privateDataSourcecreateDataSource(Stringurl,Stringusername,Stringpassword,StringdriverClassName){com.zaxxer.hikari.HikariConfigconfig=newcom.zaxxer.hikari.HikariConfig();config.setJdbcUrl(url);config.setUsername(username);config.setPassword(password);config.setDriverClassName(driverClassName);returnnewcom.zaxxer.hikari.HikariDataSource(config);}/** * 获取表分片算法属性配置 * 按deviceId哈希后取模10,分为10个表 * * @return 表分片算法属性 */privatePropertiesgetTableShardingAlgorithmProperties(){Propertiesprops=newProperties();props.setProperty("algorithm-expression","sys_message_${deviceId.hashCode() % 10 + 10 >= 10 ? deviceId.hashCode() % 10 : deviceId.hashCode() % 10 + 10}");returnprops;}/** * 获取库分片算法属性配置 * 按业务类型区分用户库和消息库 * * @return 库分片算法属性 */privatePropertiesgetDbShardingAlgorithmProperties(){Propertiesprops=newProperties();props.setProperty("algorithm-expression","${database_type == 'message' ? 'message_db' : 'user_db'}");returnprops;}}

SysMessage 实体类

package com.zgb.entity;importcom.baomidou.mybatisplus.annotation.IdType;importcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableField;importcom.baomidou.mybatisplus.annotation.TableName;importlombok.Data;importjava.time.LocalDateTime;/** * 人与AI对话消息实体类 * 对应分表后的sys_message_0到sys_message_9表 */@Data @TableName(value="sys_message",autoResultMap=true)publicclassSysMessage{/** * 消息ID,主键,自增 */@TableId(type=IdType.AUTO)privateLong messageId;/** * 设备ID,用于分表的关键字段 */@TableField("deviceId")privateString deviceId;/** * 会话ID */@TableField("sessionId")privateString sessionId;/** * 消息发送方:user-用户,assistant-人工智能 */privateString sender;/** * AI扮演的角色ID */privateLong roleId;/** * 消息内容 */privateString message;/** * 消息类型 */privateString messageType;/** * 语音文件路径 */privateString audioPath;/** * 状态:1-有效,0-删除 */privateString state;/** * 消息发送时间 */privateLocalDateTime createTime;/** * 数据库类型标识,用于分库的关键字段 * 不在数据库表中,仅用于分库路由 */@TableField(exist=false)privateString databaseType="message";}

mapper类

package com.zgb.mapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.zgb.entity.SysMessage;importorg.apache.ibatis.annotations.Mapper;importjava.util.List;/** * 消息表数据访问层接口 * 继承MyBatis Plus的BaseMapper,提供基本CRUD操作 */@Mapperpublicinterface SysMessageMapper extends BaseMapper<SysMessage>{/** * 根据设备ID查询消息列表 * * @param deviceId 设备ID * @return 该设备的消息列表 */List<SysMessage>selectByDeviceId(String deviceId);/** * 根据会话ID查询消息列表 * * @param sessionId 会话ID * @return 该会话的消息列表 */List<SysMessage>selectBySessionId(String sessionId);/** * 批量插入消息 * * @param messages 消息列表 * @return 插入成功的记录数 */intbatchInsert(List<SysMessage>messages);}

服务接口类

package com.zgb.service.impl;importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl;importcom.zgb.entity.SysMessage;importcom.zgb.mapper.SysMessageMapper;importcom.zgb.service.SysMessageService;importlombok.RequiredArgsConstructor;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importjava.util.List;/** * 消息服务实现类 * 实现消息的CRUD及相关业务操作 */@Service @RequiredArgsConstructorpublicclassSysMessageServiceImplextends ServiceImpl<SysMessageMapper,SysMessage>implements SysMessageService{privatefinalSysMessageMapper sysMessageMapper;/** * 保存消息 * * @param message 消息实体,必须包含deviceId用于分表路由 * @return 保存成功返回true,否则返回false */@OverridepublicbooleansaveMessage(SysMessage message){// 设置数据库类型为message,确保路由到消息库message.setDatabaseType("message");returnsave(message);}/** * 根据设备ID查询消息 * * @param deviceId 设备ID,用于分表路由 * @return 该设备的消息列表 */@OverridepublicList<SysMessage>getMessagesByDeviceId(String deviceId){returnsysMessageMapper.selectByDeviceId(deviceId);}/** * 根据会话ID查询消息 * Sharding-JDBC会根据SQL中的deviceId进行路由 * * @param sessionId 会话ID * @return 该会话的消息列表 */@OverridepublicList<SysMessage>getMessagesBySessionId(String sessionId){returnsysMessageMapper.selectBySessionId(sessionId);}/** * 批量保存消息 * * @param messages 消息列表,每条消息必须包含deviceId用于分表路由 * @return 保存成功的数量 */@Override @Transactional(rollbackFor=Exception.class)publicintbatchSaveMessages(List<SysMessage>messages){// 设置数据库类型为message,确保路由到消息库messages.forEach(message->message.setDatabaseType("message"));returnsysMessageMapper.batchInsert(messages);}}

服务接口

packagecom.zgb.service;importcom.baomidou.mybatisplus.extension.service.IService;importcom.zgb.entity.SysMessage;importjava.util.List;/** * 消息服务接口 * 提供消息的CRUD及相关业务操作 */publicinterfaceSysMessageServiceextendsIService<SysMessage>{/** * 保存消息 * * @param message 消息实体 * @return 保存成功返回true,否则返回false */booleansaveMessage(SysMessagemessage);/** * 根据设备ID查询消息 * * @param deviceId 设备ID * @return 消息列表 */List<SysMessage>getMessagesByDeviceId(StringdeviceId);/** * 根据会话ID查询消息 * * @param sessionId 会话ID * @return 消息列表 */List<SysMessage>getMessagesBySessionId(StringsessionId);/** * 批量保存消息 * * @param messages 消息列表 * @return 保存成功的数量 */intbatchSaveMessages(List<SysMessage>messages);}

实现说明

  1. 分库策略

    • 通过databaseType字段区分,聊天记录相关表路由到message_db,用户业务表路由到user_db
    • 在消息实体类中默认设置databaseType = "message",确保消息表操作都路由到消息库
  2. 分表策略

    • 聊天记录表sys_messagedeviceId的哈希值取模10分为10个表(sys_message_0sys_message_9
    • 使用INLINE算法实现分片,确保相同设备的消息保存在同一个表中,便于查询
  3. 核心优势

    • 分片规则配置在Nacos中,可动态调整,无需重启服务
    • 使用MyBatis Plus简化数据库操作,开发者无需关心具体操作的是哪个分表
    • 分库分表逻辑对业务代码透明,降低开发复杂度

以上实现满足了将聊天记录与用户业务分离存储,并按用户ID水平拆分聊天记录表的需求,适合高并发、大数据量的聊天场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 4:32:13

【MyCat】第4章 ----垂直拆分——分库

文章目录 4.1 如何划分表4.2 实现分库1、 修改 schema 配置文件2、 新增两个空白库3、 启动 Mycat4、 访问 Mycat 进行分库 一个数据库由很多表的构成&#xff0c;每个表对应着不同的业务&#xff0c;垂直切分是指按照业务将表进行分类&#xff0c;分布到不同 的数据库上面&…

作者头像 李华
网站建设 2026/4/17 18:27:09

专科生必看!10个高效降aigc工具推荐,避坑指南来啦

专科生必看&#xff01;10个高效降aigc工具推荐&#xff0c;避坑指南来啦 AI降重工具&#xff0c;让论文更“自然” 随着人工智能技术的不断发展&#xff0c;越来越多的专科生在撰写论文时开始依赖AI辅助工具。然而&#xff0c;AI生成的内容往往带有明显的痕迹&#xff0c;导致…

作者头像 李华
网站建设 2026/4/20 21:33:28

人群仿真软件:Vadere_(11).Vadere与其他仿真软件的比较

Vadere与其他仿真软件的比较 在人群仿真软件领域&#xff0c;Vadere并不是唯一的选择。了解Vadere与其他仿真软件的差异和优势&#xff0c;可以帮助用户更好地选择适合自己需求的工具。本节将重点比较Vadere与其他流行的仿真软件&#xff0c;如AnyLogic、Simulink、Viswalk和M…

作者头像 李华
网站建设 2026/4/24 3:41:36

【课程设计/毕业设计】基于SpringBoot与Vue的机器人健康预警系统设计与实现基于springboot的机器人健康预警系统【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/25 8:03:18

无损音乐下载工具!歌曲一键搜索,母带音质在线听歌,音频文件批量下载保存到本地!支持收藏、歌单导入

软件下载 夸克&#xff1a;https://pan.quark.cn/s/ccbd57f7b60b 其他网盘 软件介绍 支持下载无损音乐的二级&#xff0c;只支持win系统 软件特点 只支持win系统&#xff0c;其他系统不支持支持歌单导入支持再在线搜索歌曲&#xff0c;并且下载支持无损音质下载不需要下载…

作者头像 李华
网站建设 2026/5/2 8:00:15

别再问了,Sealos 私有化部署就这几步

最近被问私有化部署的问题快问麻了&#xff0c;干脆写一篇彻底说清楚。顺便拉几个"老朋友"出来比比&#xff0c;你们自己看哪个更适合。先说说市面上都有谁私有化部署云平台这条赛道&#xff0c;玩家其实不少&#xff1a;Rancher、KubeSphere、OpenShift。每个都说自…

作者头像 李华