日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
詳解數(shù)據(jù)庫分片,大幅提升SpringBoot查詢MySQL性能

背景

微服務項目中通常包含各種服務。其中一項服務與存儲用戶相關(guān)的數(shù)據(jù)有關(guān)。我們使用Spring Boot作為后端,使用MySQL數(shù)據(jù)庫。

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務,包含不限于成都做網(wǎng)站、成都網(wǎng)站設計、芝罘網(wǎng)絡推廣、重慶小程序開發(fā)、芝罘網(wǎng)絡營銷、芝罘企業(yè)策劃、芝罘品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務,您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學生創(chuàng)業(yè)者提供芝罘建站搭建服務,24小時服務熱線:18980820575,官方網(wǎng)址:www.cdcxhl.com

目標

隨著用戶基數(shù)的增長,服務性能受到了影響,延遲也上升了。由于只有一個數(shù)據(jù)庫和一張表,許多查詢和更新由于鎖異常返回錯誤。此外,隨著數(shù)據(jù)庫的規(guī)模不斷擴大,性能進一步下降。因此,需要一種解決方案來處理不斷增長的用戶基數(shù)。

解決方案

表格分片

圖片

第一種方法是在單個數(shù)據(jù)庫中創(chuàng)建多個類似的表,并使用user_id作為分片鍵。

我們在user_id列出現(xiàn)的任何地方創(chuàng)建了每個表的10個副本。因此,代碼中需要進行兩個更改。第一個更改是獲取用戶請求中的user_id。第二個更改是替換由Hibernate生成的查詢中的表名。

關(guān)于第一個更改,獲取user_id很容易,因為我們已經(jīng)在請求標頭中獲取了user_id。

對于第二個更改,我們擴展了Hibernate的EmptyInterceptor類,并覆蓋了onPrepareStatement方法,該方法在準備SQL字符串時調(diào)用。該方法有一個字符串參數(shù),即SQL語句。該SQL語句中也包含表名。因此,這里根據(jù)請求頭中存在的user_id用所需的表名替換表名。例如,如果user_id為77。我們?nèi)∷?0的模得到7,并將表名user_profile替換為user_profile_7,因為我們已經(jīng)在數(shù)據(jù)庫中創(chuàng)建了10個副本。以下是擴展EmptyInterceptor類的代碼。如果您使用的是spring boot 3,則EmptyInterceptor已經(jīng)棄用,你可以使用StatementInspector接口,并覆蓋inspect方法,并將邏輯從onPrepareStatement方法移動到inspect方法中。

public class DynamicTableNameSharding extends EmptyInterceptor {
    @Override
    public String onPrepareStatement(String sql) {
        // 替換表名
        if (Boolean.parseBoolean(DatabaseEnvironment.TABLE_SHARDING_ENABLED.label)) {
            for (String tableName : SHARDED_TABLES) {
                if(sql.contains(tableName)) {
                    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                    String shardingNumber = getSharding(attr);
                    sql = sql.replace(tableName, tableName + shardingNumber);
                    // 這里不要使用break,因為一條查詢可以包含多個表,因此需要更改所有已啟用分片的表的名稱
                }
            }
        }
        return super.onPrepareStatement(sql);
    }
}

在上述函數(shù)中,SHARDED_TABLES是已啟用分片的表的列表。getSharding方法根據(jù)請求頭中傳遞的用戶ID返回分片號。由于在單個查詢中存在多個表(例如連接或復雜邏輯),因此我們使用for循環(huán)來正確替換查詢中出現(xiàn)的所有表。

我們還通過擴展DefaultVisitListener類,在某些操作中使用了JOOQ。

數(shù)據(jù)庫分片

圖片

雖然通過表格分片提升了一定性能,但還有進一步改進的空間,我們進一步對數(shù)據(jù)庫進行分片。與創(chuàng)建表副本類似,我們創(chuàng)建10個數(shù)據(jù)庫服務器/實例的副本,每個服務器都有10個表的副本??偣灿?00個表副本。

因此,同時保持10個數(shù)據(jù)庫服務器運行也需要路由查詢到正確的數(shù)據(jù)庫。

首先,在的Spring Boot應用程序中創(chuàng)建了10個數(shù)據(jù)源,每個數(shù)據(jù)源都有不同的數(shù)據(jù)庫URL?,F(xiàn)在,我們需要一種方法將數(shù)據(jù)庫連接路由到正確的數(shù)據(jù)源。因此,我們使用了AbstractRoutingDataSource,它是一個路由getConnection()調(diào)用到其中一個多個目標數(shù)據(jù)源的抽象DataSource實現(xiàn),這個目標數(shù)據(jù)源基于一個查找鍵。然后,我們重寫了這個方法determineCurrentLookupKey。

因此,這個方法返回一個鍵,用于標識我們已定義的10個數(shù)據(jù)源中的一個特定數(shù)據(jù)源。因此,我們也更改了一些用于確定表和數(shù)據(jù)庫的邏輯。我們使用個位數(shù)字標識數(shù)據(jù)庫服務器,使用十位數(shù)來標識表。例如,用戶ID為447將被路由到第7個數(shù)據(jù)庫服務器及該服務器上的第4個表副本。因此,我們在10個數(shù)據(jù)庫服務器上有100個表,這大大提高了性能。

結(jié)論

在這個例子中,我們既使用了表分片又使用了數(shù)據(jù)庫分片。除此以外,我們可以進一步提高性能,方法是在單個服務器中增加更多的數(shù)據(jù)庫,可能總共有1000個表的副本。


文章名稱:詳解數(shù)據(jù)庫分片,大幅提升SpringBoot查詢MySQL性能
鏈接分享:http://www.dlmjj.cn/article/cddsdoh.html