栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ShardingSphere

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ShardingSphere

概述(what)

它是一套开源的分布式数据库中间件解决方案,合理的在分布式环境下使用关系型数据库操作。它分为3个部分。分别是ShardingSphere-JDBC、ShardingSphere-Proxy以及未来的ShardingSphere-Sidecar。本文主要介绍ShardingSphere-JDBC 现存的问题(question)

数据库的数量是不可控的,随着时间和业务的发展,会导致表的数据越来越多,这样子对表进行CRUD操作的时候,性能会很慢。

解决的思路(solution)

可以从两个方面来思考,一是硬件层次,增加硬件,例如CPU、内存、硬盘等。但是这种方法治标不治本。二是软件层次,出现上述问题,首先考虑缓存处理、读写分离、使用索引等方式提高性能。最后考虑对数据库进行分表分库操作。而ShardingSphere则是一个优秀的分布式数据库框架,可以简化对分库分表之后数据的相关操作。

分库分表概念(水平垂直搭配分库分表)

分库分表有两种方式,分别是水平切分和垂直切分。基于分库分表操作,又可以分为4种。接下来一一介绍。

垂直分表:针对数据库的某张表,将这表中的某些字段存储到另外一张表中。例如:有一张课程表,字段有课程名称、课程封面、课程价格、课程描述信息。将课程名称、课程封面和课程价格作为一张课程基本表中的字段存储,将课程描述信息作为另外一张表的字段存储。垂直分库:针对不同的业务,创建不同的数据库,完成专库专表。例如现有业务是用户下单购买课程。原始思路是将订单表和课程表创建在同一个库中。垂直分库是将订单表和课程表分别存储在不同的数据库中。水平分库:一般是经过了垂直分库以后,数据量仍然很大。根据业务需求,也无法进行垂直分表分库操作。可以将数据分为几个部分,存储在不同的数据库中。原来数据库中有100w行记录,现在将这些数据分别存储在两个数据库中,这样一个数据库中数据只有50w行记录。水平分表:针对一个库中数据库仍然很庞大,可以考虑将数据分开存储在不同的表中。例如原来数据库表中有50w条信息,现在可以分为5张表存储,一张表存储10w的数据量。 ShardingSphere-JDBC

它是一个轻量级的java框架,是增强版的JDBC驱动。主要用于简化数据库分库分表之后的数据的操作。例如:数据库分为2个,要求数据的主键id为奇数增加该记录到 第一个库中,否则增加到第2个库中。之前的思路是根据不同的主键id,从而进行不同的CRUD操作。现在有了ShardingSphere-JDBC,通过配置文件配置,再加上一个正常的CRUD操作,即可完成。

demo解析(水平分表)

demo

1.构建Project,导入依赖
  
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-test
        

        
            com.alibaba
            druid-spring-boot-starter
            1.1.20
        
        
            mysql
            mysql-connector-java
            8.0.15
        
        
            org.apache.shardingsphere
            sharding-jdbc-spring-boot-starter
            4.0.0-RC1
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.0.5
        

        
            org.projectlombok
            lombok
        
    
2.建数据库,新增实体类


@Data
@NoArgsConstructor
@AllArgsConstructor
public class Course {
    private Long cid;
    private String cname;
    private Long userId;
    private String cstatus;
}
3.使用mp对数据库进行操作。
@Mapper
public interface CourseMapper extends baseMapper {
}
4.编写配置类
# shardingjdbc分片策略
# 配置数据源,给数据源起名称 水平分表的配置类
spring.shardingsphere.datasource.names=m1

#配置数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/course_db?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456

#指定course表的分布情况,配置表在哪个数据库里面,表的名称都是什么 
# m1.course_1 , m1.course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{1..2}

#指定course表里面主键cid 生成策略 SNOWFLAKE
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE

#指定分片策略 约定cid值偶数添加到course_1表,如果cid是奇数,则添加到course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}

#打开sql的输出日志
spring.shardingsphere.props.sql.show=true
# 一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true
5.测试
@SpringBootTest
class ShardingjdbcdemoApplicationTests {
	 //注入Mapper
    @Autowired
    private CourseMapper courseMapper;
      //测试水平分表
    @Test
    void addCourse1() {
        for (int i = 0; i < 10; i++) {
            Course course = new Course();
            course.setCname("java"+i);
            course.setUserId(100L);
            course.setCstatus("Normal"+i);
            courseMapper.insert(course);
        }
    }
    @Test
    void select1(){
        QueryWrapper queryWrapper = new QueryWrapper<>();
        //根据自己数据库里面内容进行简单的查询测试
        queryWrapper.eq("cid", 709063885038026752L);
        Course course = courseMapper.selectOne(queryWrapper);
        System.out.println(course.toString());
    }
}
水平分库



还是使用那个course类进行测试,只不过创建两个不同的数据库,然后根据cid和user_id的奇偶数来判断存储到哪张表中。
只需要修改application.properties文件即可

# shardingjdbc分片策略
# 配置数据源,给数据源起名称,水平分库+水平分表
spring.shardingsphere.datasource.names=m1,m2

#配置第一个数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/edu_db_1?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456

#配置第二个数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=123456

# 指定数据库分布情况,数据库里面表的分布情况
# m1,m2 course_1 course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}

#指定course表里面主键cid 生成策略 SNOWFLAKE
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE

#指定表的分片策略 约定cid值偶数添加到course_1表,如果cid是奇数,则添加到course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}

#指定库分片策略 约定user_id值偶数添加到m1表,如果user_id是奇数,则添加到m2表
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

# 也可以指定库分片策略
#spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
#spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

#打开sql的输出日志
spring.shardingsphere.props.sql.show=true
# 一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true
编写测试代码
  //测试水平分库
    @Test
    void addCourse2() {
        Course course = new Course();
        course.setCname("javademo1");
        //分库根据 user_id
        course.setUserId(100L);
        course.setCstatus("Normal1");
        courseMapper.insert(course);
    }
    @Test
    void select2(){
        QueryWrapper wrapper = new QueryWrapper<>();
        //设置 userid 值 own
        wrapper.eq("user_id ",100L);
        //设置 cid 值 own
        wrapper.eq("cid",709073553256873985L);
        Course course = courseMapper.selectOne(wrapper);
        System.out.println(course);
    }
垂直分库


@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "t_user")  //指定对应表
public class User {
    private Long userId;
    private String username;
    private String ustatus;
}
@Mapper
public interface UserMapper extends baseMapper {
}
# 配置数据源,给数据源起名称,垂直分库
spring.shardingsphere.datasource.names=m1,m2,m0
#垂直分表
#配置第三个数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123456

# 指定数据库分布情况,数据库里面表的分布情况
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=m$->{0}.t_user

#指定t_user表里面主键user_id 生成策略 SNOWFLAKE
spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE

#指定表的分片策略 约定cid值偶数添加到course_1表,如果cid是奇数,则添加到course_2表
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user
测试
 //测试垂直分库
    @Test
    public void add3() {
        User user = new User();
        user.setUsername("lucy");
        user.setUstatus("a");
        userMapper.insert(user);
    }
    @Test
    void select3(){
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",709083354305134593L);
        User user = userMapper.selectOne(wrapper);
        System.out.println(user);
    }
配置公共表

公共表定义:存储固定数据的表,表数据很少发生变化,查询的时候经常会关联。在每个需要的数据库创建相同结构的表结构。

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "t_udict")
public class Udict {
    private Long dictid;
    private String ustatus;
    private String uvalue;
}
@Mapper
public interface UdictMapper extends baseMapper {
}
# shardingjdbc分片策略
# 配置数据源,给数据源起名称,公共表配置
spring.shardingsphere.datasource.names=m1,m2,m0

#配置第一个数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/edu_db_1?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456

#配置第二个数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://localhost:3306/edu_db_2?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=123456


# 指定数据库分布情况,数据库里面表的分布情况
# m1,m2 course_1 course_2
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}

#指定course表里面主键cid 生成策略 SNOWFLAKE
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE

#指定表的分片策略 约定cid值偶数添加到course_1表,如果cid是奇数,则添加到course_2表
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid % 2 + 1}

##指定库分片策略 约定user_id值偶数添加到m1表,如果user_id是奇数,则添加到m2表
#spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
#spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

# 也可以指定库分片策略
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}

#打开sql的输出日志
spring.shardingsphere.props.sql.show=true
# 一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true

#垂直分表
#配置第三个数据源的具体内容,包含连接池,驱动,地址,用户名和密码
spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123456

# 指定数据库分布情况,数据库里面表的分布情况
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=m$->{0}.t_user

#指定t_user表里面主键user_id 生成策略 SNOWFLAKE
spring.shardingsphere.sharding.tables.t_user.key-generator.column=user_id
spring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE

#指定表的分片策略 约定cid值偶数添加到course_1表,如果cid是奇数,则添加到course_2表
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user

#配置公共表
spring.shardingsphere.sharding.broadcast-tables=t_udict
spring.shardingsphere.sharding.tables.t_udict.key-generator.column=dictid
spring.shardingsphere.sharding.tables.t_udict.key-generator.type=SNOWFLAKE

测试
  @Test
    public void addDict() {
        Udict udict = new Udict();
        udict.setUstatus("a");
        udict.setUvalue("已启用");
        udictMapper.insert(udict);
    }

    @Test
    public void deleteDict() {
        QueryWrapper wrapper = new QueryWrapper<>();
        //设置 userid 值
        wrapper.eq("dictid",709088530961268737L);
        udictMapper.delete(wrapper);
    }
读写分离(概念)

为了确保数据库产品的稳定性,很多数据库具备双机热备功能。也就是有2台数据库服务器,一台负责对外的CUD操作,一台负责对外的R操作。主服务器负责处理增、删、改操作。从库负责查询操作,减少数据的访问量。

原理

主从复制:当主服务器有CUD操作时,从服务器自动获取主服务器的操作,并更新自己的从库。
读写分离:主CUD,从R

mysql的主从复制原理是通过binlog日志来完成,主服务器会将CUD操作记录形成binlog日志,从服务器实时监控主服务器,读取并解析日志,完成主从复制。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/763374.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号