• 正文
  • 推薦器件
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

面試問:“你為啥自研路由組件,咋不用sharding-jdbc”

2024/04/24
2552
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

作者:小傅哥,博客:https://bugstack.cn

面試問:“你為什么要自研,市面不是有嗎,怎么回答?” 可以從以下3個點解答;

    維護性;市面的路由組件比如 shardingsphere 但過于龐大,還需要隨著版本做一些升級,市面上已經(jīng)有很多版本了。而我們需要更少的維護成本。
    擴展性;結(jié)合自身的業(yè)務(wù)需求,我們的路由組件可以分庫分表、自定義路由協(xié)議,掃描指定庫表數(shù)據(jù)等各類方式。研發(fā)擴展性好,簡單易用。
    安全性;自研的組件更好的控制了安全問題。當(dāng)然,我們的組件主要是為了更好的適應(yīng)目前系統(tǒng)的訴求,所以使用自研的方式處理。甚至各個大廠也都自研一整套分布式服務(wù),來讓自己的系統(tǒng)更加穩(wěn)定可控。

接著問,你們?yōu)槭裁捶謳旆直恚?/strong>

我們分庫分表用的非常熟。但不能為了等到系統(tǒng)到了200萬數(shù)據(jù),才拆。那么工作量會非常大

我們的做法是,因為有成熟方案,所以前期就分庫分表了。但,為了解釋服務(wù)器空間。所以把分庫分表的庫,用服務(wù)器虛擬出來機器安裝。這樣即不過多的占用服務(wù)器資源,也方便后續(xù)數(shù)據(jù)量真的上來了,好拆分。

同時,Xxx系統(tǒng),是瞬時峰值較高的系統(tǒng),歷史數(shù)據(jù)不一定多。所以我們希望,用戶可以快速的檢索到個人數(shù)據(jù),做最優(yōu)響應(yīng)。因為大家都知道,Xxx這東西,push發(fā)完,基本就1~3分鐘結(jié)束,10分鐘人都沒了。所以我們這也是做了分庫分表的理由。


不過用和不用是一方面,會和不會是另外一方面。不能因為不會所以不用,不用是因為不同場景的所需。像 Apache ShardingSphere 在很多大的場景還是非常好用的,所以我們需要學(xué)習(xí)積累。積累不同的思想和設(shè)計,以及積累技術(shù)的運用。


小傅哥帶著大家做項目,下個項目就要用 ShardingSphere。玩的就是一個綜合實力!

那么,為了讓更多的小伙伴,學(xué)習(xí)起編程項目更加容易上手。小傅哥把各項在項目所需的分布式技術(shù)棧,都拆解成了碎片化的知識,讓大家可以一個個案例的學(xué)習(xí)。今天我們要講到 sharding-jdbc 了!

    碎片知識:https://bugstack.cn/md/road-map/road-map.html實戰(zhàn)項目:https://bugstack.cn/md/zsxq/introduce.html

本文的宗旨在于通過簡單干凈實踐的方式教會讀者,快速 Easy 的使用上 sharding-jdbc 這個笨重的大家伙!—— 這篇文章并不復(fù)雜,但市面上的案例,還真的很少有能拿過來就能運行起來的!

之所以說"笨重",是因為 Apache ShardingSphere 不只是簡單意義上的路由組件,而是一款分布式 SQL 事務(wù)和查詢引擎,可通過數(shù)據(jù)分片、彈性伸縮、加密等能力對任意數(shù)據(jù)庫進行增強。同時它又在迭代過程中,衍生出了很多的版本,以及對應(yīng)了不同的使用方式。并在 ShardingSphere 5.3 以后又做了不小的架構(gòu)調(diào)整。所以很多伙伴在使用的時候,經(jīng)常是找了一上午的資料,到下午下班還沒對接上。

本文涉及的工程:

    xfg-dev-tech-shardingjdbc:https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-shardingjdbc官網(wǎng):https://shardingsphere.apache.org/index_zh.html

一、路由本質(zhì)

分庫分表的本質(zhì)是數(shù)據(jù)的散列,分攤數(shù)據(jù)庫資源壓力。如把原本在一臺機器上的數(shù)據(jù)庫存放1000萬數(shù)據(jù),分攤到n臺機上,拆分這1000萬的數(shù)據(jù)和后續(xù)的增量。讓每個數(shù)據(jù)庫資源來分攤原本需要一臺數(shù)據(jù)庫所提供的服務(wù)。

    • 當(dāng)使用分庫分表以后,并確定如使用

用戶ID

    作為路由分片鍵。那么所做的CRUD操作,都是需要使用到這個用戶ID,并根據(jù)ID做路由庫表計算。在大廠中,開發(fā)項目。并不會說目前這個業(yè)務(wù)需求規(guī)模不大,就不使用分庫分表,而是分庫分表都是非常成熟的方案,并不會因為使用了就降低很大的開發(fā)效率。所以基本就是默認就使用了。那么使用了分庫分表,就會很占用資源嗎。也不會,因為剛開始業(yè)務(wù)體量不大的時候,都是虛擬機交叉使用,你的1臺物理機虛出來10個虛擬機,大家交叉使用主備。這樣你只是使用了分庫分表,但庫表的實際資源沒占用那么多。

二、使用案例

    jdk 1.8 +ShardingSphere 5.4.1
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/shardingsphere-jdbc-core -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core</artifactId>
    <version>5.4.1</version>
</dependency>
 <!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.33</version>
</dependency>
    因為需要解析 yaml 但默認的 SpringBoot 提供版本不支持 shardingsphere-jdbc-core 使用。

1. 工程結(jié)構(gòu)

    工程中,提供了 docker 配置數(shù)據(jù)庫環(huán)境操作,并提供了對應(yīng)的建表測試語句。如果你本機已經(jīng)安裝了數(shù)據(jù)庫,那么只做庫表語句導(dǎo)入以及 yml 配置數(shù)據(jù)庫連接信息就可以。sharding-jdbc-dev.yaml 配置了詳細的分庫分表路由信息,在 algorithms 下配置的是庫表的路由算法。這里的算法要根據(jù)實際自己使用中庫表數(shù)量來設(shè)置&設(shè)計,避免發(fā)生較大的數(shù)據(jù)偏移。配置完 sharding-jdbc-dev.yaml 需要在 application-dev.yml 中配置上 sharding-jdbc-dev.yaml 路徑,這樣才能正確加載。如果你還需要定義出自己特定的路由算法,它還支持自己寫個實現(xiàn)類的方式處理。

2. 算法配置

sharding/sharding-jdbc-dev.yaml

#?https://shardingsphere.apache.org/index_zh.html
mode:
??#?運行模式類型??蛇x配置:內(nèi)存模式 Memory、單機模式 Standalone、集群模式 Cluster -?目前為單機模式
??type:?Standalone

dataSources:
??ds_0:
????dataSourceClassName:?com.zaxxer.hikari.HikariDataSource
????driverClassName:?com.mysql.cj.jdbc.Driver
????jdbcUrl:?jdbc:mysql://127.0.0.1:13306/xfg_dev_tech_db_00?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
????username:?root
????password:?123456
????connectionTimeoutMilliseconds:?30000
????idleTimeoutMilliseconds:?60000
????maxLifetimeMilliseconds:?1800000
????maxPoolSize:?15
????minPoolSize:?5

??ds_1:
????dataSourceClassName:?com.zaxxer.hikari.HikariDataSource
????driverClassName:?com.mysql.cj.jdbc.Driver
????jdbcUrl:?jdbc:mysql://127.0.0.1:13306/xfg_dev_tech_db_01?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
????username:?root
????password:?123456
????connectionTimeoutMilliseconds:?30000
????idleTimeoutMilliseconds:?60000
????maxLifetimeMilliseconds:?1800000
????maxPoolSize:?15
????minPoolSize:?5

rules:
??-?!SHARDING
????#?庫的路由
????defaultDatabaseStrategy:
??????standard:
????????shardingColumn:?user_id
????????shardingAlgorithmName:?database_inline
????#?表的路由
????tables:
??????user_order:
????????actualDataNodes:?ds_$->{0..1}.user_order_$->{0..3}
????????tableStrategy:
??????????standard:
????????????shardingColumn:?user_id
????????????shardingAlgorithmName:?user_order_inline
????#?路由算法
????shardingAlgorithms:
??????#?庫-路由算法 2是兩個庫,庫的數(shù)量。庫的數(shù)量用哈希模2來計算。
??????database_inline:
????????type:?INLINE
????????props:
??????????algorithm-expression:?ds_$->{Math.abs(user_id.hashCode())?%?2}

??????#?表-路由算法 4是一個庫里,表的數(shù)量。4 - 1 為了獲得?011 這樣的二進制值。不推薦 user_order_$->{Math.abs(user_id.hashCode())?% 2}?作為表的路由
??????user_order_inline:
????????type:?INLINE
????????props:
??????????algorithm-expression:?user_order_$->{(user_id.hashCode()?^?(user_id.hashCode())?>>>?16)?&?(4?-?1)}

props:
??#?是否在日志中打印 SQL。
??#?打印 SQL 可以幫助開發(fā)者快速定位系統(tǒng)問題。日志內(nèi)容包含:邏輯 SQL,真實 SQL 和 SQL 解析結(jié)果。
??#?如果開啟配置,日志將使用 Topic ShardingSphere-SQL,日志級別是 INFO。false
??sql-show:?true
??#?是否在日志中打印簡單風(fēng)格的 SQL。false
??sql-simple:?true
??#?用于設(shè)置任務(wù)處理線程池的大小。每個 ShardingSphereDataSource 使用一個獨立的線程池,同一個 JVM 的不同數(shù)據(jù)源不共享線程池。
??executor-size:?20
??#?查詢請求在每個數(shù)據(jù)庫實例中所能使用的最大連接數(shù)。1
??max-connections-size-per-query:?1
??#?在程序啟動和更新時,是否檢查分片元數(shù)據(jù)的結(jié)構(gòu)一致性。
??check-table-metadata-enabled:?false
??#?在程序啟動和更新時,是否檢查重復(fù)表。false
??check-duplicate-table-enabled:?false
    mode:運行模式,默認就單機模式。dataSources:數(shù)據(jù)庫連接信息。rules:路由算法。defaultDatabaseStrategy 庫的路由、tables 表的路由。之后在 shardingAlgorithms 中配置具體的路由算法。這里的名稱都是關(guān)聯(lián)的,不要配置錯。props:一些屬性信息,包括是否打印日志等。

與這個對比,如果你使用的路由功能并不那么大,其實自研會更加簡單。當(dāng)然你也可以想辦法,簡化 sharding-jdbc 的配置。

3. 配置引入

application-dev.yml

spring:
??datasource:
????driver-class-name:?org.apache.shardingsphere.driver.ShardingSphereDriver
????url:?jdbc:shardingsphere:classpath:sharding/sharding-jdbc-dev.yaml
    和之前的一些 sharding 版本不同,這里是需要使用具體的 ShardingSphereDriver 和 url 地址,才能加載上我們配置的路由信息。

三、測試驗證

    基于工程中 docs/dev-ops/mysql/sql 創(chuàng)建庫表。已經(jīng)提供了庫名、表和測試數(shù)據(jù)。無論你使用哪種方式,都可以安裝MySql 并使用可視化工具鏈接。這里小傅哥用的是 Sequel Ace

1. 寫入數(shù)據(jù)

@Test
public?void?test_insert()?{
????for?(int?i?=?0;?i?<?1000;?i++)?{
????????UserOrderPO?userOrderPO?=?UserOrderPO.builder()
????????????????.userName("小傅哥")
????????????????.userId("xfg_"?+?RandomStringUtils.randomAlphabetic(6))
????????????????.userMobile("+86?13521408***")
????????????????.sku("13811216")
????????????????.skuName("《手寫MyBatis:漸進式源碼實踐》")
????????????????.orderId(RandomStringUtils.randomNumeric(11))
????????????????.quantity(1)
????????????????.unitPrice(BigDecimal.valueOf(128))
????????????????.discountAmount(BigDecimal.valueOf(50))
????????????????.tax(BigDecimal.ZERO)
????????????????.totalAmount(BigDecimal.valueOf(78))
????????????????.orderDate(new?Date())
????????????????.orderStatus(0)
????????????????.isDelete(0)
????????????????.uuid(UUID.randomUUID().toString().replace("-",?""))
????????????????.ipv4("127.0.0.1")
????????????????.ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334".getBytes())
????????????????.extData("{"device":?{"machine":?"IPhone?14?Pro",?"location":?"shanghai"}}")
????????????????.build();
????????userOrderDao.insert(userOrderPO);
????}
}
    測試數(shù)據(jù)寫入,你可以寫入1000條數(shù)據(jù),觀察散列效果。并可以在這個過程中,調(diào)試修改 sharding-jdbc-dev.yaml 文件對庫表路由的計算方式。

2. 查詢數(shù)據(jù)

@Test
public?void?test_selectByUserId()?{
????List<UserOrderPO>?list?=?userOrderDao.selectByUserId("xfg_PrmgwQ");
????log.info("測試結(jié)果:{}",?JSON.toJSONString(list));
}
    查詢的用戶ID是已經(jīng)寫入到數(shù)據(jù)庫表里的數(shù)據(jù),查詢的時候會根據(jù)用戶ID繼續(xù)路由計算。

3. 散列算法

@Test
public?void?test_idx()?{
????for?(int?i?=?0;?i?<?50;?i++)?{
????????String?user_id?=?"xfg_"?+?RandomStringUtils.randomAlphabetic(6);
????????log.info("測試結(jié)果?{}",?(user_id.hashCode()?^?(user_id.hashCode())?>>>?16)?&?3);
????}
}
    你可以嘗試驗證和編寫新的散列算法,最終目的都是讓數(shù)據(jù)盡可能散列到庫表。此外,關(guān)于算法的好壞,可以基于雪崩測試計算

因為很多項目都要用到云服務(wù)器部署,通過實戰(zhàn)來鍛煉。所以如果有需要,可以這樣配合使用,會更加實惠。當(dāng)然也可以選擇3年款的。地址:https://3.cn/1K-cfT7D

- END -

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
MBRS260T3G 1 onsemi Schottky Power Rectifier, Surface Mount, 2.0 A, 60 V, SMB Package, SMB, 2500-REEL

ECAD模型

下載ECAD模型
$0.22 查看
C0603C102K5RAC 1 Cornell Dubilier Electronics Inc Capacitor, Ceramic, Chip, General Purpose, 1000pF, 50V, ±10%, X7R, 0603, 0.035"T, -55o ~ +125oC, 7" Reel
$0.1 查看
BSS123 1 North American Philips Discrete Products Div Power Field-Effect Transistor, N-Channel, Metal-oxide Semiconductor FET,
$0.15 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

作者小傅哥多年從事一線互聯(lián)網(wǎng)Java開發(fā),從19年開始編寫工作和學(xué)習(xí)歷程的技術(shù)匯總,旨在為大家提供一個較清晰詳細的核心技能學(xué)習(xí)文檔。如果本文能為您提供幫助,請給予支持(關(guān)注、點贊、分享)!