Sharding-Jdbc水平分庫

在這裏插入圖片描述

創建數據庫

將原有order_db庫拆分爲order_db_1、order_db_2,數據庫腳本在上篇博客。

分片規則配置

由於數據庫拆分了兩個,這裏需要配置兩個數據源。分庫需要配置分庫的策略,和分表策略的意義類似,通過分庫策略實現數據操作針對分庫的數據庫進行操作。

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 = 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://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
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}

# 指定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_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}

# 打開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

分庫策略定義方式如下:

#分庫策略,如何將一個邏輯表映射到多個數據源
spring.shardingsphere.sharding.tables.<邏輯表名稱>.database‐strategy.<分片策略>.<分片策略屬性名>= #
分片策略屬性值
#分表策略,如何將一個邏輯表映射爲多個實際表
spring.shardingsphere.sharding.tables.<邏輯表名稱>.table‐strategy.<分片策略>.<分片策略屬性名>= #分
片策略屬性值

Sharding-JDBC支持以下幾種分片策略:
不管理分庫還是分表,策略基本一樣。

  • standard:標準分片策略,對應StandardShardingStrategy。提供對SQL語句中的=, IN和BETWEEN AND的
    分片操作支持。StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。PreciseShardingAlgorithm是必選的,用於處理=和IN的分片。
    RangeShardingAlgorithm是可選的,用於處理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。

  • complex:符合分片策略,對應ComplexShardingStrategy。複合分片策略。提供對SQL語句中的=, IN和
    BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片鍵,由於多分片鍵之間的關係復
    雜,因此並未進行過多的封裝,而是直接將分片鍵值組合以及分片操作符透傳至分片算法,完全由應用開發
    者實現,提供最大的靈活度。

  • inline:行表達式分片策略,對應InlineShardingStrategy。使用Groovy的表達式,提供對SQL語句中的=和
    IN的分片操作支持,只支持單分片鍵。對於簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發,如: t_user_$->{u_id % 8} 表示t_user表根據u_id模8,而分成8張表,表名稱爲t_user_0 到t_user_7 。

  • hint:Hint分片策略,對應HintShardingStrategy。通過Hint而非SQL解析的方式分片的策略。對於分片字段
    非SQL決定,而由其他外置條件決定的場景,可使用SQL Hint靈活的注入分片字段。例:內部系統,按照員工登錄主鍵分庫,而數據庫中並無此字段。SQL Hint支持通過Java API和SQL註釋(待實現)兩種方式使用。
    none:不分片策略,對應NoneShardingStrategy。不分片的策略。

目前例子中都使用inline分片策略,若對其他分片策略細節若感興趣,請查閱官方文檔:
https://shardingsphere.apache.org

插入測試

修改testInsertOrder方法,插入數據中包含不同的user_id

    @Test
    public void testInsertOrder(){
        for (int i = 0 ; i<10; i++){
            orderDao.insertOrder(new BigDecimal((i+1)*5),1L,"WAIT_PAY");
        }
        for (int i = 0 ; i<10; i++){
            orderDao.insertOrder(new BigDecimal((i+1)*10),2L,"WAIT_PAY");
        }
    }

執行testInsertOrder:

在這裏插入圖片描述
通過日誌可以看出,根據user_id的奇偶不同,數據分別落在了不同數據源,達到目標。

查詢測試

調用selectOrderbyIds

    @Test
    public void testSelectOrderbyIds(){
        List<Long> ids = new ArrayList<>();
        ids.add(448193675814502400L);
        ids.add(448193675889999873L);

        List<Map> maps = orderDao.selectOrderbyIds(ids);
        System.out.println(maps);
    }  

通過日誌發現,sharding-jdbc將sql路由到m1和m2:

在這裏插入圖片描述
由於查詢語句中並沒有使用分片鍵user_id,所以sharding-jdbc將廣播路由到每個數據結點。
下邊我們在sql中添加分片鍵進行查詢。
在OrderDao中定義接口:

@Select({"<script>",
            " select",
            " * ",
            " from t_order t ",
            "where t.order_id in",
            "<foreach collection='orderIds' item='id' open='(' separator=',' close=')'>",
            "#{id}",
            "</foreach>",
            " and t.user_id = #{userId} ",
            "</script>"
    })
    List<Map> selectOrderbyUserAndIds(@Param("userId") Integer userId,@Param("orderIds")List<Long>
            orderIds);

編寫測試方法:

    @Test
    public void testSelectOrderbyUserAndIds(){
        List<Long> orderIds = new ArrayList<>();
        ids.add(448193675273437184L);
        ids.add(448193676187795456L);
        //查詢條件中包括分庫的鍵user_id
        int user_id = 2;
        List<Map> orders = orderDao.selectOrderbyUserAndIds(user_id,orderIds);
    }


執行testSelectOrderbyUserAndIds:

在這裏插入圖片描述

查詢條件user_id爲1,根據分片策略m$->{user_id % 2 + 1}計算得出m2,此sharding-jdbc將sql路由到m2,見上
圖日誌。

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