共用方式為


整合式持續性反模式

將所有應用程式的數據放入單一數據存放區可能會損害效能,可能是因為它會導致資源爭用,或因為數據存放區不適合某些數據。

問題說明

在過去,應用程式通常會使用單一數據存放區,不論應用程式可能需要儲存的不同數據類型為何。 這通常是為了簡化應用程式設計,或符合開發小組的現有技能集。

新式雲端式系統通常具有額外的功能和非功能性需求,而且需要儲存許多異質類型的數據,例如檔、影像、快取數據、佇列訊息、應用程式記錄和遙測。 遵循傳統方法,並將所有這些資訊放入相同的數據存放區可能會損害效能,原因有兩個主要原因:

  • 在相同的數據存放區中儲存和擷取大量數據可能會導致爭用,進而導致響應時間變慢和連線失敗。
  • 無論選擇哪一個數據存放區,它可能不適合所有不同類型的數據,或可能無法針對應用程式執行的作業進行優化。

下列範例顯示 ASP.NET Web API 控制器,將新記錄新增至資料庫,並將結果記錄至記錄檔。 記錄會保留在與商務數據相同的資料庫中。 您可以在這裡找到完整的範例

public class MonoController : ApiController
{
    private static readonly string ProductionDb = ...;

    public async Task<IHttpActionResult> PostAsync([FromBody]string value)
    {
        await DataAccess.InsertPurchaseOrderHeaderAsync(ProductionDb);
        await DataAccess.LogAsync(ProductionDb, LogTableName);
        return Ok();
    }
}

產生記錄檔記錄的速率可能會影響商務作業的效能。 如果另一個元件,例如應用程式進程監視器,定期讀取和處理記錄數據,這也可能會影響商務作業。

如何修正問題

根據數據的使用來分隔數據。 針對每個數據集,選取最符合該數據集使用方式的數據存放區。 在上述範例中,應用程式應該記錄到與保存商務數據之資料庫的個別存放區:

public class PolyController : ApiController
{
    private static readonly string ProductionDb = ...;
    private static readonly string LogDb = ...;

    public async Task<IHttpActionResult> PostAsync([FromBody]string value)
    {
        await DataAccess.InsertPurchaseOrderHeaderAsync(ProductionDb);
        // Log to a different data store.
        await DataAccess.LogAsync(LogDb, LogTableName);
        return Ok();
    }
}

考量

  • 使用數據的方式和存取方式來分隔數據。 例如,請勿將記錄資訊和商務數據儲存在相同的數據存放區中。 這些類型的數據具有截然不同的需求和存取模式。 記錄記錄本質上是循序的,而商務數據更可能需要隨機存取,而且通常是關係型。

  • 請考慮每種數據類型的數據存取模式。 例如,將格式化的報表和文件儲存在文件資料庫中,例如 Azure Cosmos DB,但使用 Azure Cache for Redis 快取暫存數據。

  • 如果您遵循此指引,但仍達到資料庫的限制,您可能需要相應增加資料庫。 也請考慮水平調整,並將負載分割到資料庫伺服器。 不過,數據分割可能需要重新設計應用程式。 如需詳細資訊,請參閱 數據分割

如何偵測問題

系統可能會大幅降低速度,最終會失敗,因為系統用盡了資料庫連線等資源。

您可以執行下列步驟來協助識別原因。

  1. 檢測系統以記錄關鍵效能統計數據。 擷取每個作業的計時資訊,以及應用程式讀取和寫入數據的點。
  2. 可能的話,請監視在生產環境中執行幾天的系統,以取得系統使用方式的實際檢視。 如果無法執行此動作,請以實際數量執行虛擬使用者執行一系列作業的腳本式負載測試。
  3. 使用遙測數據來識別效能不佳的期間。
  4. 識別在這些期間存取哪些數據存放區。
  5. 識別可能發生爭用的數據記憶體資源。

診斷範例

下列各節會將這些步驟套用至稍早所述的範例應用程式。

檢測和監視系統

下圖顯示稍早所述的範例應用程式負載測試結果。 測試使用了最多 1000 個並行使用者的步驟負載。

SQL 型控制器的負載測試效能結果

當負載增加至 700 位使用者時,輸送量也會增加。 但此時,輸送量層級會關閉,而且系統似乎在其最大容量上執行。 平均回應隨著使用者負載逐漸增加,顯示系統無法跟上需求。

識別效能不佳的期間

如果您要監視生產系統,您可能會注意到模式。 例如,回應時間可能會每天大幅下降。 這可能是由一般工作負載或排程的批次作業所造成,或只是因為系統在特定時間有更多的使用者。 您應該專注於這些事件的遙測數據。

尋找增加回應時間與資料庫活動增加或共用資源的 I/O 之間的相互關聯。 如果有相互關聯,表示資料庫可能是瓶頸。

識別在這些期間存取哪些數據存放區

下一個圖表顯示負載測試期間資料庫輸送量單位 (DTU) 的使用率。 (DTU 是可用容量的量值,而且是 CPU 使用率、記憶體配置、I/O 速率的組合。DTU 使用率迅速達到100%。 這是大致上一個圖表中輸送量尖峰的點。 資料庫使用率仍然很高,直到測試完成為止。 結尾略有下降,可能是因為節流、資料庫連線競爭或其他因素所造成。

Azure 傳統入口網站中的資料庫監視器,其中顯示資料庫的資源使用率

檢查數據存放區的遙測

檢測數據存放區以擷取活動的低階詳細數據。 在範例應用程式中,數據存取統計數據會顯示針對 PurchaseOrderHeader 數據表和 MonoLog 數據表執行的大量插入作業。

範例應用程式的數據存取統計數據

識別資源爭用

此時,您可以檢閱原始程式碼,專注於應用程式存取競爭資源的位置。 尋找下列情況:

  • 以邏輯方式分隔寫入相同存放區的數據。 記錄、報表和佇列訊息等數據不應保留在與商務資訊相同的資料庫中。
  • 數據存放區選擇與數據類型不符,例如關係資料庫中的大型 Blob 或 XML 檔。
  • 共用相同存放區具有明顯不同使用模式的數據,例如使用低寫入/高讀取數據儲存的高寫入/低讀取數據。

實作解決方案並驗證結果

應用程式已變更為將記錄寫入個別的數據存放區。 以下是負載測試結果:

使用 Polyglot 控制器負載測試效能結果

輸送量模式與先前的圖表類似,但效能尖峰的時間點大約是每秒 500 個要求。 平均回應時間略低。 不過,這些統計數據不會說明完整的故事。 商務資料庫的遙測顯示 DTU 使用率尖峰約為 75%,而不是 100%。

Azure 傳統入口網站中的資料庫監視器,顯示 Polyglot 案例中資料庫的資源使用率

同樣地,記錄資料庫的最大 DTU 使用率只會達到大約 70%。 資料庫不再是系統效能的限制因素。

Azure 傳統入口網站中的資料庫監視器,顯示 Polyglot 案例中記錄資料庫的資源使用率