成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳解數據庫分片,大幅提升Spring Boot查詢MySQL性能

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

背景

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

目標

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

解決方案

表格分片

圖片圖片

第一種方法是在單個數據庫中創建多個類似的表,并使用user_id作為分片鍵。

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

關于第一個更改,獲取user_id很容易,因為我們已經在請求標頭中獲取了user_id。

對于第二個更改,我們擴展了Hibernate的EmptyInterceptor類,并覆蓋了onPrepareStatement方法,該方法在準備SQL字符串時調用。該方法有一個字符串參數,即SQL語句。該SQL語句中也包含表名。因此,這里根據請求頭中存在的user_id用所需的表名替換表名。例如,如果user_id為77。我們取它10的模得到7,并將表名user_profile替換為user_profile_7,因為我們已經在數據庫中創建了10個副本。以下是擴展EmptyInterceptor類的代碼。如果您使用的是spring boot 3,則EmptyInterceptor已經棄用,你可以使用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);
    }
}

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

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

數據庫分片

圖片圖片

雖然通過表格分片提升了一定性能,但還有進一步改進的空間,我們進一步對數據庫進行分片。與創建表副本類似,我們創建10個數據庫服務器/實例的副本,每個服務器都有10個表的副本。總共有100個表副本。

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

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

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

結論

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


責任編輯:武曉燕 來源: Java學研大本營
相關推薦

2024-04-29 18:55:16

緩存Spring性能

2011-04-19 11:02:57

數據庫分頁

2009-03-30 14:19:26

優化數據庫MySQL

2024-11-19 13:11:19

2023-04-10 09:15:25

Vite 4.3SWC 插件

2024-06-25 10:57:08

2010-10-28 15:37:36

高可用架構

2015-05-04 14:17:16

數據庫架構高可用

2013-03-29 09:28:41

2023-11-09 08:46:24

2011-03-28 15:44:45

惠普數據庫Oracle數據庫

2024-03-14 10:10:03

MySQL優化事務

2009-05-11 14:19:55

Oracle性能優化數據庫

2023-11-26 09:04:10

Vue性能

2015-04-28 10:44:09

分片MySQL

2020-11-10 08:38:43

數據庫HugePages內存

2010-08-17 09:22:34

2021-01-31 17:50:41

數據庫查詢程序員

2011-04-18 09:03:36

數據庫查詢

2024-12-10 00:00:05

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕在线视频一区二区三区 | 日本久久www成人免 成人久久久久 | av中文字幕在线播放 | 国产一区二区三区久久久久久久久 | 日韩在线一区二区三区 | 天天操操操操操 | 日韩在线中文 | 一区二区在线不卡 | 日韩字幕一区 | 久久精品免费 | 特黄特色大片免费视频观看 | 丝袜美腿av | 精品免费看 | 国产精品一区二区久久久久 | 国产免费一区二区 | 中文字幕精品一区 | 欧美视频1 | av一二三区 | 欧美5区 | 黄色一级大片在线免费看产 | 欧美一级黄色片免费观看 | 欧美日韩不卡合集视频 | 99r在线| 天天综合网永久 | 国产在线小视频 | 国产区在线免费观看 | 91精品一区二区三区久久久久久 | 国产1区2区在线观看 | 国产精品爱久久久久久久 | 麻豆久久久久久久久久 | 久久99国产精品久久99果冻传媒 | 国产一区在线免费观看视频 | 日韩国产三区 | 狠狠插狠狠操 | 久久久久久久久久久久一区二区 | 免费观看av网站 | 国产精品免费在线 | 成人高清在线 | 亚洲高清一区二区三区 | 精品久久久久久久 | 久久成人精品一区二区三区 |