Sharding-Jdbc水平分庫及公共表

在這裏插入圖片描述

前言

垂直分庫是指按照業務將表進行分類,分佈到不同的數據庫上面,每個庫可以放在不同的服務器
上,它的核心理念是專庫專用。接下來看一下如何使用Sharding-JDBC實現垂直分庫。

創建數據庫

創建數據庫user_db

CREATE DATABASE `user_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

在user_db中創建t_user表

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`user_id` bigint(20) NOT NULL COMMENT '用戶id',
`fullname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用戶姓名',
`user_type` char(1) DEFAULT NULL COMMENT '用戶類型',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

分片規則配置


server.port=56081

spring.application.name = fast-common-sharding-horizontal-subdivision

server.servlet.context-path = /fast-common-sharding-horizontal-subdivision
spring.http.encoding.enabled = true
spring.http.encoding.charset = UTF-8
spring.http.encoding.force = true

spring.main.allow-bean-definition-overriding = true

mybatis.configuration.map-underscore-to-camel-case = true

#sharding-jdbc分片規則配置
#數據源
spring.shardingsphere.datasource.names = m0,m1,m2

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://192.168.56.121:33065/user_db?useUnicode=true
spring.shardingsphere.datasource.m0.username = root
spring.shardingsphere.datasource.m0.password = root


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://192.168.56.121:33065/order_db_1?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = root

spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver‐class‐name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://192.168.56.121:33065/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = root

# 指定t_order表的數據分佈情況,配置數據節點 m1.t_order_1,m1.t_order_2,m2.t_order_1,m2.t_order_2
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m$->{1..2}.t_order_$->{1..2}
#spring.shardingsphere.sharding.tables.t_user.actual-data-nodes = m$->{0}.t_user
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes = m$->{0}.t_user

# 指定t_order表的主鍵生成策略爲SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE

# 指定t_order表的分片策略,分片策略包括分片鍵和分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column = order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression = t_order_$->{order_id % 2 + 1}

# 分庫策略,以user_id爲分片鍵,分片策略爲user_id % 2 + 1,user_id爲偶數操作m1數據源,否則操作m2。
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

# 打開sql輸出日誌
spring.shardingsphere.props.sql.show = true

swagger.enable = true

logging.level.root = info
logging.level.org.springframework.web = info
fast.cloud.nacos.horizontal.subdivision = debug
logging.level.druid.sql = debug

數據操作

新增UserDao:


@Mapper
@Component
public interface UserDao {
    /**
     * 新增用戶
     * @param userId 用戶id
     * @param fullname 用戶姓名
     * @return
     */
    @Insert("insert into t_user(user_id, fullname) value(#{userId},#{fullname})")
    int insertUser(@Param("userId")Long userId, @Param("fullname")String fullname);
    /**
     * 根據id列表查詢多個用戶
     * @param userIds 用戶id列表
     * @return
     */
    @Select({"<script>",
            " select",
            " * ",
            " from t_user t ",
            " where t.user_id in",
            "<foreach collection='userIds' item='id' open='(' separator=',' close=')'>",
            "#{id}",
            "</foreach>",
            "</script>"
    })
    List<Map> selectUserbyIds(@Param("userIds") List<Long> userIds);
}

測試

@Test
    public void testInsertUser(){
        for (int i = 0 ; i<10; i++){
            Long id = i + 1L;
            userDao.insertUser(id,"姓名"+ id );
        }
    }

    @Test
    public void testSelectUserbyIds(){
        List<Long> userIds = new ArrayList<>();
        userIds.add(1L);
        userIds.add(2L);
        List<Map> users = userDao.selectUserbyIds(userIds);
        System.out.println(users);
    }

執行testInsertUser:
在這裏插入圖片描述

通過日誌可以看出t_user表的數據被落在了m0數據源,達到目標。
執行testSelectUserbyIds:

在這裏插入圖片描述

通過日誌可以看出t_user表的查詢操作被落在了m0數據源,達到目標。

公共表

公共表屬於系統中數據量較小,變動少,而且屬於高頻聯合查詢的依賴表。參數表、數據字典表等屬於此類型。可以將這類表在每個數據庫都保存一份,所有更新操作都同時發送到所有分庫執行。接下來看一下如何使用
Sharding-JDBC實現公共表。

創建數據庫

分別在user_db、order_db_1、order_db_2中創建t_dict表:


CREATE TABLE `t_dict` (
`dict_id` bigint(20) NOT NULL COMMENT '字典id',
`type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典類型',
`code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典編碼',
`value` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典值',
PRIMARY KEY (`dict_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

在Sharding-JDBC規則中修改

# 指定t_dict爲公共表
spring.shardingsphere.sharding.broadcast‐tables=t_dict

數據操作

新增DictDao:

@Mapper
@Component
public interface DictDao {
    /**
     * 新增字典
     *
     * @param type  字典類型
     * @param code  字典編碼
     * @param value 字典值
     * @return
     */
    @Insert("insert into t_dict(dict_id,type,code,value) value(#{dictId},#{type},#{code},# {value})")
    int insertDict(@Param("dictId") Long dictId, @Param("type") String type, @Param("code") String
            code, @Param("value") String value);

    /**
     * 刪除字典
     *
     * @param dictId 字典id
     * @return
     */
    @Delete("delete from t_dict where dict_id = #{dictId}")
    int deleteDict(@Param("dictId") Long dictId);
}

字典操作測試

新增單元測試方法:

    @Test
    public void testInsertDict(){
        dictDao.insertDict(1L,"user_type","0","管理員");
        dictDao.insertDict(2L,"user_type","1","操作員");
    }
    @Test
    public void testDeleteDict(){
        dictDao.deleteDict(1L);
        dictDao.deleteDict(2L);
    }

執行testInsertDict:

在這裏插入圖片描述

通過日誌可以看出,對t_dict的表的操作被廣播至所有數據源。
測試刪除字典,觀察是否把所有數據源中該 公共表的記錄刪除。

github地址:https://github.com/fafeidou/fast-cloud-nacos/tree/master/fast-common-examples/fast-common-sharding-vertial-subdivision

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章