Dela via


Monolitisk beständighetsantipattern

Att placera alla ett programs data i ett enda datalager kan försämra prestandan, antingen för att det leder till resurskonkurrens eller för att datalagret inte passar bra för vissa data.

Kontext och problem

Tidigare använde program ett enda datalager, oavsett de olika typer av data som programmet kan behöva lagra. Organisationer använde den här metoden för att förenkla programdesignen eller för att matcha utvecklingsteamets befintliga kompetensuppsättning.

Moderna molnbaserade system har ofta extra funktionella och icke-funktionella krav. Dessa system måste lagra många heterogena typer av data, till exempel dokument, bilder, cachelagrade data, köade meddelanden, programloggar och telemetri. Att följa den traditionella metoden och placera all denna information i samma datalager kan försvaga prestandan av två huvudsakliga skäl:

  • Lagring och hämtning av stora mängder orelaterade data i samma datalager kan orsaka konkurrens, vilket leder till långsamma svarstider och anslutningsfel.
  • Oavsett vilket datalager som väljs kanske det inte passar bäst för alla typer av data. Eller så kanske den inte är optimerad för de åtgärder som programmet utför.

I följande exempel visas en ASP.NET webb-API-kontrollant som lägger till en ny post i en databas och även registrerar resultatet i en logg. Loggen lagras i samma databas som affärsdata.

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();
    }
}

Den hastighet med vilken loggposter genereras kan påverka verksamhetens prestanda. Och om en annan komponent, till exempel en programprocessövervakare, regelbundet läser och bearbetar loggdata, kan det även påverka verksamheten.

Lösning

Avgränsa data enligt dess användning. För varje datauppsättning väljer du ett datalager som bäst matchar hur du använder den datauppsättningen. I föregående exempel ska programmet logga till ett separat arkiv från databasen som innehåller affärsdata:

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();
    }
}

Problem och överväganden

  • Separera data baserat på hur du använder och kommer åt dem. Lagra till exempel inte logginformation och affärsdata i samma datalager. Dessa typer av data har olika krav och mönster för åtkomst. Loggposter är i sig sekventiella, medan affärsdata är mer benägna att kräva slumpmässig åtkomst och ofta är relationella.

  • Överväg dataåtkomstmönstret för varje typ av data. Du kan till exempel lagra formaterade rapporter och dokument i en dokumentdatabas, till exempel Azure Cosmos DB. Använd Azure Cache for Redis för att cachelagra temporära data.

  • Skala upp databasen om du följer den här vägledningen men ändå når databasens gränser. Överväg också att skala horisontellt och partitionera belastningen mellan databasservrar. Partitionering kan dock kräva omdesign av programmet. Mer information finns i Datapartitionering.

Identifiera problemet

Systemet kan sakta ned dramatiskt och så småningom misslyckas när systemet får slut på resurser, till exempel databasanslutningar.

Du kan göra följande för att identifiera orsaken:

  1. Instrumentera systemet för att registrera nyckelprestandastatistiken. Samla in tidsinformation för varje åtgärd. Och samla in de punkter där programmet läser och skriver data.

  2. Övervaka systemet i några dagar i en produktionsmiljö för att få en verklig vy över hur systemet används. Om du inte kan göra den här processen kör du skriptbaserade belastningstester med en realistisk mängd virtuella användare som utför en typisk serie åtgärder.

  3. Använd telemetridata för att identifiera perioder med dåliga prestanda.

  4. Identifiera vilka datalager som användes under dessa perioder.

  5. Identifiera datalagringsresurser som kan uppleva konkurrens.

Exempeldiagnos

I följande avsnitt används stegen på exempelprogrammet som beskrivs ovan.

Instrumentera och övervaka systemet

Följande diagram visar resultatet av belastningstestning av exempelprogrammet som beskrevs tidigare. Testet använder en stegbelastning på upp till 1 000 samtidiga användare.

Diagram som visar prestandaresultat för belastningstest för den SQL-baserade styrenheten.

När belastningen ökar till 700 användare ökar även dataflödet. Men vid den tidpunkten stabiliseras dataflödet, och systemet verkar köras på sin maximala kapacitet. Det genomsnittliga svaret ökar gradvis med användarbelastningen, vilket visar att systemet inte kan hålla jämna steg med efterfrågan.

Identifiera perioder med dåliga prestanda

Om du övervakar produktionssystemet kan du märka mönster. Svarstiderna kan sjunka avsevärt vid samma tidpunkt varje dag. En vanlig arbetsbelastning eller ett schemalagt batchjobb kan orsaka den här fluktuationen. Eller så kan systemet ha fler användare vid vissa tidpunkter. Du bör fokusera på telemetridata för dessa händelser.

Leta efter korrelationer mellan ökade svarstider och ökad databasaktivitet eller indata/utdata (I/O) till delade resurser. Om det finns korrelationer innebär det att databasen kan vara en flaskhals.

Identifiera vilka datalager som används under dessa perioder

Nästa diagram visar användningen av databasdataflödesenheter (DTU:er) under belastningstestet. En DTU är ett mått på tillgänglig kapacitet. Det är en kombination av CPU-användning, minnesallokering och I/O-hastighet. Användningen av DTUs når snabbt 100%. I föregående diagram nådde dataflödet en topp vid den här tidpunkten. Databasanvändningen är fortfarande hög tills testet har slutförts. Det finns en liten minskning mot slutet, vilket kan bero på begränsning, konkurrens om databasanslutningar eller andra faktorer.

Diagram som visar databasövervakaren i den klassiska Azure-portalen som visar resursanvändning för databasen.

Granska telemetrin för datalager

Instrumentera datalager för att samla in information på låg nivå om aktiviteten. I exempelprogrammet visar dataåtkomststatistiken en stor mängd infogningsåtgärder som utförs mot både PurchaseOrderHeader tabellen och MonoLog tabellen.

Diagram som visar dataåtkomststatistik för exempelprogrammet.

Identifiera resurskonkurration

Nu kan du granska källkoden med fokus på de punkter där programmet har åtkomst till resurser som används. Leta efter situationer som:

  • Data som är logiskt åtskilt skrivs till samma lagring. Data som loggar, rapporter och köade meddelanden ska inte lagras i samma databas som affärsinformation.
  • Ett matchningsfel mellan valet av datalager och typen av data, till exempel stora blobbar eller XML-dokument i en relationsdatabas.
  • Data med olika användningsmönster men som använder samma lagring. Ett exempel inkluderar data med hög skrivfrekvens och lågläsfrekvens som lagras med data med låg skrivfrekvens och högläsfrekvens.

Implementera lösningen och verifiera resultatet

I det här exemplet uppdateras programmet för att skriva loggar till ett separat datalager. I följande diagram visas resultatet av belastningstestet.

Diagram som visar prestandaresultatet för belastningstestet med hjälp av Polyglot-styrenheten.

Dataflödets mönster liknar det tidigare diagrammet, men den punkt där prestandatopparna är cirka 500 begäranden per sekund högre. Den genomsnittliga svarstiden är marginellt lägre. Den här statistiken berättar dock inte hela historien. Telemetri för affärsdatabasen visar att DTU-användningen når en topp på cirka 75%i stället för 100%.

Diagram som visar databasövervakaren i den klassiska Azure-portalen som visar resursanvändningen för databasen i polyglotscenariot.

På samma sätt når den maximala DTU-användningen av loggdatabasen bara cirka 70%. Databaserna är inte längre den begränsande faktorn i systemets prestanda.

Diagram som visar databasövervakaren i den klassiska Azure-portalen som visar resursanvändningen för loggdatabasen i polyglotscenariot.