ShardingSphere分库分表实战

  • ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。 他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。
  • ShardingSphere定位为关系型数据库中间件,旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。 它与NoSQL和NewSQL是并存而非互斥的关系。NoSQL和NewSQL作为新技术探索的前沿,放眼未来,拥抱变化,是非常值得推荐的。反之,也可以用另一种思路看待问题,放眼未来,关注不变的东西,进而抓住事物本质。 关系型数据库当今依然占有巨大市场,是各个公司核心业务的基石,未来也难于撼动,我们目前阶段更加关注在原有基础上的增量,而非颠覆
     

 

  • sharding-jdbc 定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
  • 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer和PostgreSQL
     

三. 项目实战

本项目基于 Spring Boot 2.1.5 使用sharding-sphere + Mybatis-Plus 实现分库分表

1. pom.xml引入依赖


<?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.1.5.RELEASE</version><relativePath/></parent><groupId>com.xd</groupId><artifactId>spring-boot-sharding-table</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-boot-sharding-table</name><description>基于 Spring Boot 2.1.5 使用sharding-sphere + Mybatis-Plus 实现分库分表</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--Mybatis-Plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.1</version></dependency><!--shardingsphere start--><!-- for spring boot --><dependency><groupId>io.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>3.1.0</version></dependency><!-- for spring namespace --><dependency><groupId>io.shardingsphere</groupId><artifactId>sharding-jdbc-spring-namespace</artifactId><version>3.1.0</version></dependency><!--shardingsphere end--><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  1.  

2. 创建数据库和表

 
ds0├── user_0└── user_1ds1├── user_0└── user_1

既然是分库分表 库结构与表结构一定是一致的

数据库: ds0

 
  1. CREATE DATABASE IF NOT EXISTS `ds0` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;USE `ds0`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for user_0 ------------------------------DROP TABLE IF EXISTS `user_0`;CREATE TABLE `user_0` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- ------------------------------ Table structure for user_1 ------------------------------DROP TABLE IF EXISTS `user_1`;CREATE TABLE `user_1` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;SET FOREIGN_KEY_CHECKS = 1;

     

数据库: ds1

 
  1. CREATE DATABASE IF NOT EXISTS `ds1` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;USE `ds1`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for user_0 ------------------------------DROP TABLE IF EXISTS `user_0`;CREATE TABLE `user_0` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- ------------------------------ Table structure for user_1 ------------------------------DROP TABLE IF EXISTS `user_1`;CREATE TABLE `user_1` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;SET FOREIGN_KEY_CHECKS = 1;

     

3. application.properties (重点)基本是在这个文件配置的

 
  1. # 数据源 ds0,ds1sharding.jdbc.datasource.names=ds0,ds1# 第一个数据库sharding.jdbc.datasource.ds0.type=com.zaxxer.hikari.HikariDataSourcesharding.jdbc.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driversharding.jdbc.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/ds0?characterEncoding=utf-8&&serverTimezone=GMT%2B8sharding.jdbc.datasource.ds0.username=rootsharding.jdbc.datasource.ds0.password=root# 第二个数据库sharding.jdbc.datasource.ds1.type=com.zaxxer.hikari.HikariDataSourcesharding.jdbc.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driversharding.jdbc.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/ds1?characterEncoding=utf-8&&serverTimezone=GMT%2B8sharding.jdbc.datasource.ds1.username=rootsharding.jdbc.datasource.ds1.password=root# 水平拆分的数据库(表) 配置分库 + 分表策略 行表达式分片策略# 分库策略sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=idsharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=ds$->{id % 2}# 分表策略 其中user为逻辑表 分表主要取决于age行sharding.jdbc.config.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..1}sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=age# 分片算法表达式sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{age % 2}# 主键 UUID 18位数 如果是分布式还要进行一个设置 防止主键重复#sharding.jdbc.config.sharding.tables.user.key-generator-column-name=id# 打印执行的数据库以及语句sharding.jdbc.config.props..sql.show=truespring.main.allow-bean-definition-overriding=true

     

  2.  

我这次使用配置文件方式实现分库以及分表
以上配置说明:

逻辑表 user

水平拆分的数据库(表)的相同逻辑和数据结构表的总称。例:用户数据根据主键尾数拆分为2张表,分别是user0到user1,他们的逻辑表名为user。

真实表

    在分片的数据库中真实存在的物理表。即上个示例中的user0到user1

分片算法:

    Hint分片算法
    对应HintShardingAlgorithm,用于处理使用Hint行分片的场景。需要配合HintShardingStrategy使用。

分片策略:

    行表达式分片策略 对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: user$->{id % 2} 表示user表根据id模2,而分成2张表,表名称为user0到user_1。

自增主键生成策略

    通过在客户端生成自增主键替换以数据库原生自增主键的方式,做到分布式主键无重复。 采用UUID.randomUUID()的方式产生分布式主键。或者 SNOWFLAKE

4. 实体类

 
  1. package com.zhang.shardingtable.entity;import com.baomidou.mybatisplus.annotation.TableName;import com.baomidou.mybatisplus.extension.activerecord.Model;import groovy.transform.EqualsAndHashCode;import lombok.Data;import lombok.experimental.Accessors;/*** @Classname User* @Description 用户实体类* @Author 章国文 13120739083@163.com* @Date 2019-06-28 17:24* @Version 1.0*/@Data@EqualsAndHashCode(callSuper = true)@Accessors(chain = true)@TableName("user")public class User extends Model<User> {/*** 主键Id*/private int id;/*** 名称*/private String name;/*** 年龄*/private int age;}

     

5. dao层

 
  1. package com.zhang.shardingtable.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.zhang.shardingtable.entity.User;/*** user dao层* @author lihaodong*/public interface UserMapper extends BaseMapper<User> {}

     

6. service层以及实现类

UserService

 
package com.zhang.shardingtable.service;import com.baomidou.mybatisplus.extension.service.IService;import com.zhang.shardingtable.entity.User;import java.util.List;/*** @Classname UserService* @Description 用户服务类* @Author 章国文 13120739083@163.com* @Date 2019-06-28 17:31* @Version 1.0*/public interface UserService extends IService<User> {/*** 保存用户信息* @param entity* @return*/@Overrideboolean save(User entity);/*** 查询全部用户信息* @return*/List<User> getUserList();}
  1.  

UserServiceImpl

 
  1. package com.zhang.shardingtable.service.Impl;import com.baomidou.mybatisplus.core.toolkit.Wrappers;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.zhang.shardingtable.entity.User;import com.zhang.shardingtable.mapper.UserMapper;import com.zhang.shardingtable.service.UserService;import org.springframework.stereotype.Service;import java.util.List;/*** @Classname UserServiceImpl* @Description 用户服务实现类* @Author 章国文 13120739083@163.com* @Date 2019-06-28 17:32* @Version 1.0*/@Servicepublic class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic boolean save(User entity) {return super.save(entity);}@Overridepublic List<User> getUserList() {return baseMapper.selectList(Wrappers.<User>lambdaQuery());}}

     

  2.  

7. 控制类

 
  1. package com.zhang.shardingtable.controller;import com.zhang.shardingtable.entity.User;import com.zhang.shardingtable.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @Classname UserController* @Description 用户测试控制类* @Author 章国文 13120739083@163.com* @Date 2019-06-28 17:36* @Version 1.0*/@RestControllerpublic class UserController {@Autowiredprivate UserService userService;@GetMapping("/select")public List<User> select() {return userService.getUserList();}@GetMapping("/insert")public Boolean insert(User user) {return userService.save(user);}}

     

  2.  

四. 测试

启动项目
打开浏览器 分别访问:

http://localhost:8080/insert?id=1&name=lhd&age=12    
http://localhost:8080/insert?id=2&name=lhd&age=13    
http://localhost:8080/insert?id=3&name=lhd&age=14    
http://localhost:8080/insert?id=4&name=lhd&age=15

可以在控制台看到如下展示,表示插入成功了

根据分片算法和分片策略 不同的id以及age取模落入不同的库表 达到了分库分表的结果

有的人说 查询的话 该怎么做呢 其实也帮我们做好了 打开浏览器 访问:
http://localhost:8080/select

 

分别从ds0数据库两张表和ds1两张表查询结果 然后汇总结果返回

    之前有朋友问我单表数据量达千万,想做水平分割,不分库,也可以的吧?
    是完全可以的 只要修改配置文件的配置即可 非常灵活

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386548.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

灵魂拷问!细数Android开发者的艰辛历程,成功入职阿里

什么是中年危机 根据权威数据显示&#xff0c;国内IT程序员鼎盛时期是在25-27岁左右&#xff0c;30岁对于程序员而言完全是一个38线&#xff0c;接着就是转业转岗的事情&#xff0c;这一点在业界也算是一个共识了。 大学毕业步入IT行业普遍年龄也是在22岁左右&#xff0c;然而…

JMM模型到并发编程

电脑&#xff1a;内存 L1 L2 L3 缓存 CPU ctrlatldel就可以看到 Java 有线程内存&#xff0c;在执行线程的时候&#xff0c;会从主内存把变量加载到工作内存&#xff08;缓存&#xff09;&#xff0c;所以&#xff0c;在多线程同时改变一个静态变量时候&#xff0c;实际是分开…

焦虑的移动互联网开发者如何破局?专题解析

尴尬的35岁 不知道是哪个人提出的职场35岁就要面临被淘汰的定律&#xff0c;因为35岁定律本来就是个伪命题&#xff0c;尤其是在IT行业! 现在年八九百万的大学生毕业&#xff0c;他们虽然年轻活力&#xff0c;但是很多企业也将之“拒之门外”。 35岁的不要&#xff0c;二十几…

17.前端路由router-07keep-alive

keep-alive是Vue提供的一个抽象组件&#xff0c;用来对组件进行缓存&#xff0c;从而节省性能&#xff0c; 由于是一个抽象组件&#xff0c;所以在v页面渲染完毕后不会被渲染成一个DOM元素 当组件在keep-alive内被切换时组件的activated、deactivated这两个生命 周期钩子函数会…

使用IDEA创建Maven项目和Maven使用入门(配图详解)

本文详解的讲解了使用IDEA创建Maven项目&#xff0c;及Maven的基础入门。 1、打开IDEA&#xff0c;右上角选择File->New->Project 2、如图中所示选择Maven&#xff08;可按自己所需添加&#xff0c;否则加载时速度很慢&#xff09; 3、添加项目所需Groupld,ArtifactId,Ve…

jvisualvm安装Visual GC插件

给jdk自带的jvisualvm安装Visual GC插件&#xff0c;遇到Were sorry the java.net site has closed&#xff08;我们很抱歉java.net网站已经关闭&#xff09; 1、找到新的更新地址 visualvm新访问地址&#xff1a;https://visualvm.github.io/index.html 进入“Plugins”&…

来自阿里巴巴佛系安卓程序员的指南,专题解析

开头 中国互联网发展的这些年&#xff0c;如今90后程序员是中国程序员的主力军&#xff0c;互联网的热潮也让一批批00后蠢蠢欲动&#xff0c;尝试涌入互联网圈。 当程序员容易&#xff0c;当一个优秀的程序员需要不断学习&#xff0c;从初级程序员到高级程序员&#xff0c;从…

C#在WinForm中打开控制台显示

引用&#xff1a; namespace 测试使用 {public partial class Form1 : Form{[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError true)][return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bo…

Redis+AQS

前言 对于java的单进程应用来说&#xff0c;存在资源竞争的场景可以使用synchronized关键字和Lock来对资源进行加锁&#xff0c;使整个操作具有原子性。但是对于多进程或者分布式的应用来说&#xff0c;上面提到的锁不共享&#xff0c;做不到互相通讯&#xff0c;所以就需要分…

disruptor 介绍

一、背景 1.来源 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列&#xff0c;研发的初衷是解决内部的内存队列的延迟问题&#xff0c;而不是分布式队列。基于Disruptor开发的系统单线程能支撑每秒600万订单&#xff0c;2010年在QCon演讲后&#xff0c;获得了业界关注。…

算法题+JVM+自定义View,详细的Android学习指南

前言 想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样~。 学算法真的很痛苦&#xff0c;虽然大数据现在很火&#xff0c;但找到适合自己定位的职业也未尝不是一种合理选择。 投百度的经历非…

用过的前端插件合集

用过的前端插件合集 FontAwesome字体 Font Awesome详细用法参见上述站点的Examples。 SweetAlert系列 SweetAlertSweetAlert2SweetAlert 到 SweetAlert2 升级指南示例&#xff1a; 基本使用&#xff1a; swal("标题","内容","success);使用SweetAlert…

CAS和AQS

CAS 全称&#xff08;Compare And Swap&#xff09;,比较交换 Unsafe类是CAS的核心类&#xff0c;提供硬件级别的原子操作。 // 对象、对象的地址、预期值、修改值 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);缺点&#xf…

系统盘点Android开发者必须掌握的知识点,全网疯传

最近在知乎上&#xff0c;有许多人在邀请我去回答“Android前景怎么样、是不是要凉了、是不是应该考虑要转行&#xff1f;”等一系列的问题。 想着可能有很多人都有这样的担心&#xff0c;于是就赶紧写篇文章&#xff0c;来跟你们谈下Android开发的前景到底怎么样&#xff1f;…

数据库操作DDL

show database; 查看所有数据库 drop database db_name; 删除数据库 create database db_name;创建数据库 一个数据库对应一个文件夹 create database if not exists db_name; show warnings; 查看所有警告 show create databae db_name;查看创建的数据库 create database if n…

细数Android开发者的艰辛历程,已拿offer附真题解析

笼统来说&#xff0c;中年程序员容易被淘汰的原因其实不外乎三点。 1、输出能力已到顶点。这个人奋斗十来年了&#xff0c;依旧碌碌无为&#xff0c;很明显这人的天花板就这样了&#xff0c;说白了&#xff0c;天赋就这样。 2、适应能力越来越差。年纪大&#xff0c;有家庭&…

原子操作类AtomicInteger详解

为什么需要AtomicInteger原子操作类&#xff1f; 对于Java中的运算操作&#xff0c;例如自增或自减&#xff0c;若没有进行额外的同步操作&#xff0c;在多线程环境下就是线程不安全的。num解析为numnum1&#xff0c;明显&#xff0c;这个操作不具备原子性&#xff0c;多线程并…

移动端Rem之讲解总结

日妈常说的H5页面&#xff0c;为啥叫H5页面嘛&#xff0c;不就是手机上展示的页面吗&#xff1f;那是因为啊手机兼容所有html5新特性&#xff0c;所以跑在手机上的页面也叫h5页面&#xff0c;跨平台&#xff08;安装ios),基于webview&#xff0c;它就是终端开发的一个组件&…

终于有人把安卓程序员必学知识点全整理出来了,送大厂面经一份!

除了Bug&#xff0c;最让你头疼的问题是什么&#xff1f;单身&#xff1f;秃头&#xff1f;996?面试造火箭&#xff0c;工作拧螺丝&#xff1f; 作为安卓开发者&#xff0c;除了Bug&#xff0c;经常会碰到下面这些问题&#xff1a; 应用卡顿&#xff0c;丢帧&#xff0c;屏幕画…

mq引入以后的缺点

系统可用性降低? 一旦mq不能使用以后,系统A不能发送消息到mq,系统BCD无法从mq中获取到消息.整个系统就崩溃了. 如何解决: 系统复杂程度增加? 加入mq以后,mq引入来的问题很多,然后导致系统的复杂程度增加. 如何解决 系统的一致性降低? 有人给系统A发送了一个请求,本来这个请求…