Tek Parça Kalıcılık Kötü ModeliMonolithic Persistence antipattern

Uygulamanın tüm verilerini tek bir veri deposuna yerleştirmek performansı olumsuz etkileyebilir çünkü bu kaynak çekişmesine yol açabilir veya veri deposu bazı verilere uygun olmayabilir.Putting all of an application's data into a single data store can hurt performance, either because it leads to resource contention, or because the data store is not a good fit for some of the data.

Sorun açıklamasıProblem description

Geçmişte, uygulamanın depolaması gereken farklı türde veriler dikkate alınmaksızın uygulamalar çoğunlukla tek veri deposu kullanırdı.Historically, applications have often used a single data store, regardless of the different types of data that the application might need to store. Genellikle bunun yapılmasının nedeni uygulama tasarımını basitleştirmek veya geliştirme ekibinin mevcut becerilerine uymasını sağlamaktı.Usually this was done to simplify the application design, or else to match the existing skillset of the development team.

Modern bulut tabanlı sistemlerin çoğunlukla işlevsel olan ve olmayan ek gereksinimleri vardır ve belgeler, resimler, önbelleğe alınmış veriler, kuyruğa alınmış iletiler, uygulama günlükleri ve telemetri gibi birçok heterojen veri türünü depolamaları gerekir.Modern cloud-based systems often have additional functional and nonfunctional requirements, and need to store many heterogenous types of data, such as documents, images, cached data, queued messages, application logs, and telemetry. Geleneksel yaklaşım benimsendiğinde ve bu bilgilerin tümü aynı veri deposuna yerleştirildiğinde, iki ana nedenle performans olumsuz etkilenebilir:Following the traditional approach and putting all of this information into the same data store can hurt performance, for two main reasons:

  • Büyük miktarlarda ilişkisiz verileri aynı veri deposuna yerleştirmek ve almak veri çekişmesine neden olabilir ve bu da yanıt sürelerinin uzamasına, bağlantı hatalarına yol açabilir.Storing and retrieving large amounts of unrelated data in the same data store can cause contention, which in turn leads to slow response times and connection failures.
  • Hangi veri deposu seçilirse seçilsin, tüm farklı veri türleri için en uygun depo olamaz veya uygulamanın gerçekleştirdiği işlemler için iyileştirilemez.Whichever data store is chosen, it might not be the best fit for all of the different types of data, or it might not be optimized for the operations that the application performs.

Aşağıdaki örnekte, veritabanına yeni kayıt ekleyen ve ayrı zamanda sonucu günlüğe kaydeden bir ASP.NET Web API denetleyicisi gösterilir.The following example shows an ASP.NET Web API controller that adds a new record to a database and also records the result to a log. Günlük, iş verileriyle aynı veritabanında tutulmaktadır.The log is held in the same database as the business data. Örneğin tamamını burada bulabilirsiniz.You can find the complete sample here.

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

Günlük kayıtlarının oluşturulma hızı, işle ilgili işlemlerin performansını büyük olasılıkla etkiler.The rate at which log records are generated will probably affect the performance of the business operations. Bir de uygulama işlem izleyicisi gibi başka bir bileşen günlük verilerini düzenli olarak okuyor ve işliyorsa, işle ilgili işlemler bundan da etkilenebilir.And if another component, such as an application process monitor, regularly reads and processes the log data, that can also affect the business operations.

Sorunun çözümüHow to fix the problem

Verileri kullanımlarına göre ayırın.Separate data according to its use. Her veri kümesi için, veri kümesinin kullanımına en uygun veri deposunu seçin.For each data set, select a data store that best matches how that data set will be used. Önceki örnekte, uygulamanın günlüğü iş verilerinin tutulduğu depodan ayrı bir depoda tutması gerekir:In the previous example, the application should be logging to a separate store from the database that holds business data:

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

Dikkat edilmesi gerekenlerConsiderations

  • Verileri kullanılma ve erişilme yöntemine göre ayırın.Separate data by the way it is used and how it is accessed. Örneğin, günlük bilgileriyle iş verilerini aynı veri deposuna yerleştirmeyin.For example, don't store log information and business data in the same data store. Bu tür verilerin gereksinimleri ve erişim desenleri birbirinden ciddi düzeyde farklıdır.These types of data have significantly different requirements and patterns of access. Günlük kayıtları doğaları gereği sıralı olurken, iş verileri daha çok rastgele erişim gerektirir ve sıklıkla ilişkiseldir.Log records are inherently sequential, while business data is more likely to require random access, and is often relational.

  • Her veri türü için veri erişim desenini göz önünde bulundurun.Consider the data access pattern for each type of data. Örneğin, biçimlendirilmiş raporları ve belgeleri Cosmos DB gibi bir belge veritabanında depolayın ama geçici verileri günlüğe almak için Azure Cache for Redis kullanın.For example, store formatted reports and documents in a document database such as Cosmos DB, but use Azure Cache for Redis to cache temporary data.

  • Bu yönergelere uyduğunuz hale yine de veritabanının sınırına ulaşırsanız, veritabanının ölçeğini büyütmeniz gerekebilir.If you follow this guidance but still reach the limits of the database, you may need to scale up the database. Ayrıca, yatay ölçeklemeyi ve yükü veritabanı sunucuları arasında bölümlemeyi de göz önünde bulundurun.Also consider scaling horizontally and partitioning the load across database servers. Öte yandan, bölümleme uygulamanın yeniden tasarlanmasını gerektirebilir.However, partitioning may require redesigning the application. Daha fazla bilgi için bkz: Veri bölümleme.For more information, see Data partitioning.

Sorunu algılamaHow to detect the problem

Sistemin veritabanı bağlantıları gibi kaynakları tükendikçe, sistem ciddi düzeyde yavaşlar ve sonunda başarısız olur.The system will likely slow down dramatically and eventually fail, as the system runs out of resources such as database connections.

Nedeni belirlemenize yardımcı olması için aşağıdaki adımları gerçekleştirebilirsiniz.You can perform the following steps to help identify the cause.

  1. Ana performans istatistiklerini kaydetmek için sistemi işaretleyin.Instrument the system to record the key performance statistics. Her işlemin zamanlama bilgilerini ve ayrıca uygulamanın verileri okuduğu ve yazdığı noktaları yakalayın.Capture timing information for each operation, as well as the points where the application reads and writes data.
  2. Mümkünse, sistemin nasıl kullanıldığını gösteren gerçek bir görünüm elde etmek için üretim ortamında çalışırken birkaç gün süreyle sistemi izleyin.If possible, monitor the system running for a few days in a production environment to get a real-world view of how the system is used. Bu mümkün değilse, tipik işlem serileri gerçekleştiren gerçekçi bir sanal kullanıcı hacmiyle betikleştirilmiş yük testleri çalıştırın.If this is not possible, run scripted load tests with a realistic volume of virtual users performing a typical series of operations.
  3. Telemetri verilerini kullanarak düşük performans dönemlerini belirleyin.Use the telemetry data to identify periods of poor performance.
  4. Bu dönemlerde hangi veri depolarına erişildiğini belirleyin.Identify which data stores were accessed during those periods.
  5. Çekişme yaşanıyor olabilecek veri depolama kaynaklarını belirleyin.Identify data storage resources that might be experiencing contention.

Örnek tanılamaExample diagnosis

Aşağıdaki bölümlerde, bu adımlar daha önce açıklanan örnek uygulamaya uygulanmıştır.The following sections apply these steps to the sample application described earlier.

Sistemi işaretleme ve izlemeInstrument and monitor the system

Aşağıdaki grafikte, daha önce açıklanan örnek uygulamanın yük testinin sonuçları gösterilmektedir.The following graph shows the results of load testing the sample application described earlier. Testte 1000 eşzamanlı kullanıcıya kadar ulaşan bir adım yüklemesi kullanılmıştır.The test used a step load of up to 1000 concurrent users.

SQL tabanlı denetleyici için yük testi performans sonuçları

Yük 700 kullanıcı kadar artarken, aktarım hızı da artar.As the load increases to 700 users, so does the throughput. Ancak bu noktada, aktarım hızının artışı durur ve sistem kapasite üst sınırında çalışıyor gibi görünür.But at that point, throughput levels off, and the system appears to be running at its maximum capacity. Kullanıcı yüküyle birlikte ortalama yanıt süresi de aşamalı olarak artar ve bu da sistemin talebe ayak uyduramadığını gösterir.The average response gradually increases with user load, showing that the system can't keep up with demand.

Düşük performans dönemlerini belirlemeIdentify periods of poor performance

Üretim sistemini izliyorsanız, desenleri fark edebilirsiniz.If you are monitoring the production system, you might notice patterns. Örneğin, her gün aynı saatte yanıt süreleri önemli ölçüde uzuyor olabilir.For example, response times might drop off significantly at the same time each day. Bunun nedeni düzenli bir iş yükü ve zamanlanmış bir toplu iş olabileceği gibi, yalnızca belirli saatlerde sistemde daha fazla kullanıcı bulunması da olabilir.This could be caused by a regular workload or scheduled batch job, or just because the system has more users at certain times. Bu olaylar için telemetri verilerine odaklanmalısınız.You should focus on the telemetry data for these events.

Artan yanıt süreleriyle artan veritabanı etkinliği veya paylaşılan kaynaklardaki G/Ç arasında bağıntılar olup olmadığına bakın.Look for correlations between increased response times and increased database activity or I/O to shared resources. Bağıntılar varsa, bu veritabanında bir performans sorunu olduğu anlamına gelebilir.If there are correlations, it means the database might be a bottleneck.

Bu dönemlerde hangi veri depolarına erişildiğini belirleyinIdentify which data stores are accessed during those periods

Sonraki grafikte, yük testi sırasında veritabanı işleme birimlerinin (DTU) kullanımı gösterilir.The next graph shows the utilization of database throughput units (DTU) during the load test. (DTU kullanılabilir kapasite ölçüsüdür ve CPU kullanımı, bellek ayırma, G/Ç hızının bir bileşimidir.) DTU'ların kullanımı hızla %100'e ulaşmıştır.(A DTU is a measure of available capacity, and is a combination of CPU utilization, memory allocation, I/O rate.) Utilization of DTUs quickly reached 100%. Bu kabaca önceki örnekte aktarım hızının zirveye ulaştığı noktadır.This is roughly the point where throughput peaked in the previous graph. Test bitene kadar veritabanı kullanımı çok yüksek düzeyde kalmıştır.Database utilization remained very high until the test finished. Sona doğru, azalma, veritabanı bağlantılarına yönelik rekabet veya başka faktörlerin neden olabileceği hafif bir düşüş olmuştur.There is a slight drop toward the end, which could be caused by throttling, competition for database connections, or other factors.

Klasik Azure portalında veritabanının kaynak kullanımını gösteren veritabanı izlemesi

Veri depoları için telemetriyi inceleyinExamine the telemetry for the data stores

Etkinliğin alt düzey ayrıntılarını yakalamak için veri depolarını işaretleyin.Instrument the data stores to capture the low-level details of the activity. Örnek uygulamada, veri erişim istatistikleri hem PurchaseOrderHeader tablosunda hem de MonoLog tablosunda büyük hacimli ekleme işlemleri yapıldığını gösterir.In the sample application, the data access statistics showed a high volume of insert operations performed against both the PurchaseOrderHeader table and the MonoLog table.

Örnek uygulama için veri erişim istatistikleri

Kaynak çekişmesini tanımlamaIdentify resource contention

Bu noktada, kaynak kodu gözden geçirebilir ve uygulamanın çekişmeli kaynaklara eriştiği noktalara odaklanabilirsiniz.At this point, you can review the source code, focusing on the points where contended resources are accessed by the application. Şöyle durumları bulun:Look for situations such as:

  • Mantıksal olarak birbirinden ayrı olan verilerin aynı depoya yazılması.Data that is logically separate being written to the same store. Günlükler, raporlar ve kuyruğa alınmış iletiler gibi veriler, iş bilgileriyle aynı veritabanında tutulmamalıdır.Data such as logs, reports, and queued messages should not be held in the same database as business information.
  • Veri deposu seçimiyle veri türü arasında bir uyuşmazlık (örneğin, ilişkisel bir veritabanında büyük bloblar veya XML belgeleri).A mismatch between the choice of data store and the type of data, such as large blobs or XML documents in a relational database.
  • Kullanım desenleri önemli ölçüde farklı olup aynı depoyu paylaşan veriler (örneğin, yüksek-okuma/düşük-yazma verilerinin düşük-yazma/yüksek-okuma verileriyle birlikte depolanması).Data with significantly different usage patterns that share the same store, such as high-write/low-read data being stored with low-write/high-read data.

Çözümü uygulama ve sonucu doğrulamaImplement the solution and verify the result

Uygulama, günlükleri ayrı bir veri deposuna yazacak şekilde değiştirilmiştir.The application was changed to write logs to a separate data store. Yük testi sonuçlarını şunlardır:Here are the load test results:

Polyglot denetleyicisi kullanılarak yük testi performans sonuçları

Aktarım hızının deseni önceki grafikle benzerdir, aman performansın zirveye ulaştığı nokta saniyede yaklaşık 500 istek kadar yüksektir.The pattern of throughput is similar to the earlier graph, but the point at which performance peaks is approximately 500 requests per second higher. Ortalama yanıt süresi çok az düşüktür.The average response time is marginally lower. Ancak, bu istatistikler hikayenin tamamını göstermez.However, these statistics don't tell the full story. İş veritabanına ilişkin telemetri DTU kullanımının %100 yerine %75 dolayında zirve yaptığını gösterir.Telemetry for the business database shows that DTU utilization peaks at around 75%, rather than 100%.

Klasik Azure portalında çok yönlü bir senaryoda veritabanının kaynak kullanımını gösteren veritabanı izlemesi

Benzer biçimde, günlük veritabanının DTU kullanımı üst sınırı yalnızca %70 dolayındadır.Similarly, the maximum DTU utilization of the log database only reaches about 70%. Veritabanları artık sistem performansını sınırlayan faktör değildir.The databases are no longer the limiting factor in the performance of the system.

Klasik Azure portalında çok yönlü bir senaryoda günlük veritabanının kaynak kullanımını gösteren veritabanı izlemesi