SpringBoot+Sharding-JDBC custom sharding rules + custom primary key generation strategy to achieve horizontal sharding

Sharding-JDBC implements sub-table

Perform operations such as sharding the database in accordance with the rules in the form of configuration

Hello World

Implement horizontal table splitting through Sharding-JDBC: use user_1 and user_2 in the database to split horizontally through the primary key, the id is an odd number into the user_1 table, and the id is an even number into the user_2 table

1 Create a database and table

create database sharding character set = utf8;
use sharding;

create table user_1(
 id int primary key auto_increment,
 name varchar(20),
 age int,
 birthday datetime,
 cmd varchar(200)
);

create table user_2(
 id int primary key auto_increment,
 name varchar(20),
 age int,
 birthday datetime,
 cmd varchar(200)
);

2 Create a SpringBoot project

Sharding-jdbc provides us with a starter that integrates springBoot, which is very simple to configure

<!-- 数据库连接驱动 -->
<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.4.1</version>
</dependency>


<!-- sharding-jdbc 数据库分库分表 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

<!-- 数据库连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.8</version>
</dependency>
<!-- reids 依赖(这里主要用于生成主键) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3 configure the application.properties file

##基本配置(正常操作)
server.port=8998

# mybatis-plus 配置
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
mybatis-plus.type-aliases-package=com.mt.bean
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

spring.redis.host=120.25.227.88
spring.redis.password=123456


#sharding-jdbc的配置 ps:官网有详细的配置文件介绍:https://shardingsphere.apache.org/document/legacy/4.x/document/cn/manual/sharding-jdbc/configuration/config-spring-boot/

#声明一个数据库(虚拟的)
spring.shardingsphere.datasource.names=db1

#声明虚拟数据库对应的连接,驱动,用户名,密码,连接池等信息
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/sharding?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource


#声明 表存放在对应的数据库 $->{0..1} 就是行内表达式
#这里的意思是db1库内有user虚拟表指向 user_1和user_2
spring.shardingsphere.sharding.tables.user.actual-data-nodes=db1.user_$->{1..2}

#设置主键字段
spring.shardingsphere.sharding.tables.user.key-generator.column=id
# 设置主键生成策略 可选内置的 SNOWFLAKE(雪花算法)/UUID 
#也可以自定义(实现ShardingKeyGenerator,并配置META-INF/services/org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator) 
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE

#设置 根据哪个字段进行分片
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
#分片规则奇数存入user_1  偶数存入user_2
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id % 2 != 0 ? 1:2}

spring.shardingsphere.props.sql.show=true

4 write the corresponding object

bean:

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
    
    

    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private Date birthday;
    private String cmd;
}

mapper:

public interface UserMapper extends BaseMapper<User> {
    
    }

Test class:

@SpringBootTest
class ShardingSphereApplicationTests {
    
    

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
    
    
        User user1 = new User();
        user1.setAge(10);
        user1.setName("张三");
        user1.setBirthday(new Date());
        user1.setCmd("张三今年10岁");
        
        User user2 = new User();
        user2.setAge(20);
        user2.setName("李四");
        user2.setBirthday( new Date() );
        user2.setCmd("李四今年20岁");
        
        userMapper.insert( user2 );
    }

}

After testing, user Zhang San was added to user_1, and Li Si was added to user_2

Custom primary key generation strategy

Sharding-jdbc provides us with 2 default generation strategies:

  • SNOWFLAKE: Snowflake algorithm (corresponding to the database bigint type and java Long type)
  • UUID: uuid generation strategy (varchar and String types)

These two types alone cannot meet our needs, so sharding-jdbc provides us with an ShardingKeyGeneratorinterface to allow us to customize the primary key generation strategy.

Implementation: Here is an auto-incremented primary key generated by redis

1 Implement the ShardingKeyGenerator interface

@Component
@Slf4j
public class KeyGenerator implements ShardingKeyGenerator, ApplicationContextAware {
    
    
    @Getter
    @Setter
    private Properties properties;

    //必须设置为静态,否则为null
    public static RedisTemplate redisTemplate;


    @Override
    public Comparable<?> generateKey() {
    
    
        ValueOperations valueOp = redisTemplate.opsForValue();
        return  valueOp.increment("id");
    }


    //设置在yaml内的名字
    @Override
    public String getType() {
    
    
        return "auto_increment";
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
        redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
    }
}

2 Configure the class just created

We need to create files under resource

META-INF\services\org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator

And configure the host generator we just wrote

com.mt.config.Sharding.KeyGenerator

3 use

Just specify the name of the generator just in the configuration file

spring.shardingsphere.sharding.tables.user.key-generator.type=auto_increment

Custom table fragmentation strategy

Demonstrated above sub-table strategy is sharding-jdbc provides us with the inlinefragmentation of the rules, you can write 行表达式simple table partitioning strategy, for example, according to the modulo id, according to gender classification. But for some more complex partitioning strategies, row expressions may not meet our requirements, so we need to customize the table fragmentation strategy

Case: According to the current year, month and minute, insert data into different tables. For example, there are order_202001, order_202002, etc. in the database. We need to dynamically store the date generated by the order into different tables:

1 Create a database table

create table `order_202001`(
 id int primary key auto_increment,
 date datetime,
 price decimal(10,2),
 cmd varchar(200)
);

create table `order_202002`(
 id int primary key auto_increment,
 date datetime,
 price decimal(10,2),
 cmd varchar(200)
);

create table `order_202003`(
 id int primary key auto_increment,
 date datetime,
 price decimal(10,2),
 cmd varchar(200)
);

2 Create an entity object

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("`order`")
public class Order {
    
    

    @TableId(type = IdType.AUTO)
    private Integer id;
    private Date date;
    private BigDecimal price;
    private String cmd;
}

3 Create a sharding logic class

@Component
public class OrderTableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
    
    

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {
    
    
        
		//preciseShardingValue就是当前插入的字段值
        //collection 内就是所有的逻辑表
        //获取字段值
        Date time = preciseShardingValue.getValue();

        if(time == null){
    
    
            throw new UnsupportedOperationException("prec is null");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String year =sdf.format(time);

        for (String tableName : collection) {
    
    //循环表名已确定使用哪张表
            String name = tableName.substring(tableName.length() - 6);
            if(year.equals(name)){
    
    
                return tableName;//返回要插入的逻辑表
            }
        }
        return null;
    }

}
#声明虚拟表
spring.shardingsphere.sharding.tables.order.actual-data-nodes=db1.order_$->{2000..2099}0$->{1..9},db1.order_$->{2000..2099}1$->{0..2}
#声明表内的主键
spring.shardingsphere.sharding.tables.order.key-generator.column=id
#声明主键生成策略
spring.shardingsphere.sharding.tables.order.key-generator.type=order_auto_increment

#声明根据哪个字段进行分片
spring.shardingsphere.sharding.tables.order.table-strategy.standard.sharding-column=date
#自定义分片规则类
spring.shardingsphere.sharding.tables.order.table-strategy.standard.precise-algorithm-class-name=com.mt.config.Sharding.OrderTableShardingAlgorithm

4 Add operation through mybatis-plus

@RestController
@RequestMapping("order")
public class OrderController {
    
    

    @Autowired
    private OrderMapper orderMapper;

    @GetMapping("add")
    public String add(Order order){
    
    
        orderMapper.insert(order);
        return "success";
    }
}

Guess you like

Origin blog.csdn.net/dndndnnffj/article/details/109870883