<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>${sharding.version}</version>
</dependency>
根據未來兩年的業務量,估算兩年的業務總量M,單表資料量不能超過N(需要看具體業務場景,欄位少的可以適量多一些,可與架構師及部門經驗豐富的同事探討,最大不要超過1000W);
總的分表數量K≥M/N,且K值向上取接近的最小2的次冪。
例如業務總量M=10億,單表數量N≤700W,則M/N≈143,向上取最小的2次冪為:143<2的8次方=256,故總的分表數量為256。
可將分表數設定的儘可能的小,一臺伺服器存放多個庫,業務增長後,磁碟不足時,可將該伺服器上的整個庫的資料遷移到新的伺服器。
如總的分表數量為1024,可分為32個庫:db0~db31,每個庫分32張表:tb0~tb31,共16臺伺服器:server0~server15。
具體劃分如下:
- server0上有db0庫和db16庫
- server1上有db1庫和db17庫
- ……
- server15上有db15庫和db31庫
如果業務發展一段時間後出現磁碟不足,可在申請16臺伺服器:server16~server31
- server0上的db16庫遷移至server16
- server1上的db17庫遷移至server17
- ……
- server15上的db31庫遷移至server31
遷移後磁碟釋放50%空間
分片鍵的選擇一定要具有明顯的業務特徵,具體表現為:
目前專案裡使用的分片鍵為商家編碼,並統一為大寫,因為:
inline: Groovy的Inline表示式,可以支援SQL語句中的=和IN的操作,InlineShardingStrategy只支援單分片鍵;這種方式是最常用的,也是目前專案中在使用的。
其他分片策略參考:Sharding-JDBC分片策略
以32個庫為例:Math.abs(庫分片鍵.toUpperCase().hashCode()) % 32,將分片鍵商家編碼統一大寫後,取hashCode的絕對值,對32取模,32為分庫數;
通用公式為:Math.abs(庫分片鍵.toUpperCase().hashCode()) % 分庫數
以每個庫32張表為例:(Math.abs(表分片鍵.toUpperCase().hashCode()) % 1024).intdiv(32),要保證分到某個庫的資料,均勻分佈到該庫的每個表;
注意:此處不能直接用分庫的公式,因為某個商家計算後分配到第i庫,如果分表用同樣的公式,則也只能落到第i表,導致一個庫中只有一個表有資料。因此,需要先對一個較大的數取模,該較大的數為分庫數*分表數,記為m,本例中=32*32=1024,將hash後的值分散到0-1023之間,在除以32,則最終結果被分配到0-31之間。
通用公式為:(Math.abs(表分片鍵.toUpperCase().hashCode()) % 分庫數*分表數).intdiv(分庫數)
分庫分表,要求主鍵全域性唯一,因為存在資料彙總的場景,如存放到ES、巨量資料等;因此不能使用資料庫自增方式,需要一種全域性唯一的主鍵生成方式;
1. 新增maven依賴
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-self-id-generator</artifactId>
<version>1.4.2</version>
</dependency>
2. 在@Configuration類中建立Bean物件
@Bean
public IdGenerator getIdGenerator() {
return new CommonSelfIdGenerator();
}
3. 使用
@Autowired
private IdGenerator idGenerator;
@Test
public void generateId(){
long id = idGenerator.generateId().longValue();
......
}
很多外掛如sharding-jdbc, mybatis-plus提供了雪花演演算法生成器,目前常用的是這種方式,生產的id時間上基本是有序的,使用很方便。
不允許沒有分片鍵的查庫操作;
查詢或更新庫操作條件裡必須有分片鍵,否則就需要將分庫分表資料存放到ES或建立查詢條件與分片鍵的中間表;
ES或分片鍵中間表是為個別場景如頁面多條件查詢,使用者獲取不到分片鍵時採取的折中方案,絕大多數場景是能獲取到分片鍵的,如果獲取不到則可認為分片鍵的選取是不合理的,需要根據實際場景調整分片鍵。