CQRS mimari stiliCQRS architecture style

Komut ve Sorgu Sorumluluğu Ayrımı (CQRS), okuma işlemlerini yazma işlemlerinden ayıran bir mimari stilidir.Command and Query Responsibility Segregation (CQRS) is an architecture style that separates read operations from write operations.

CQRS mimari stili mantıksal diyagramı

Geleneksel mimarilerde, bir veritabanının sorgulanması ve güncelleştirilmesi için aynı veri modeli kullanılır.In traditional architectures, the same data model is used to query and update a database. Bu, basit bir işlemdir ve temel CRUD işlemleri için kullanışlıdır.That's simple and works well for basic CRUD operations. Ancak daha karmaşık uygulamalarda bu yaklaşım zahmetli hale gelebilir.In more complex applications, however, this approach can become unwieldy. Örneğin, okuma tarafında, uygulama birçok farklı sorgu gerçekleştirerek farklı şekillere sahip veri aktarımı nesneleri (DTO’lar) döndürebilir.For example, on the read side, the application may perform many different queries, returning data transfer objects (DTOs) with different shapes. Nesne eşleme karmaşık hale gelebilir.Object mapping can become complicated. Yazma tarafında ise modeli, karmaşık doğrulama ve iş mantığı uygulayabilir.On the write side, the model may implement complex validation and business logic. Sonuç olarak, çok fazla işlem gerçekleştiren aşırı karmaşık bir modelle karşı karşıya kalabilirsiniz.As a result, you can end up with an overly complex model that does too much.

Başka bir olası sorun, okuma ve yazma iş yüklerinin genellikle çok farklı performans ve ölçeklendirme gereksinimleriyle asimetrik olmasıdır.Another potential problem is that read and write workloads are often asymmetrical, with very different performance and scale requirements.

CQRS, verileri güncelleştirmek için komut kullanımı, verileri okumak için de sorgu kullanımı yoluyla, okuma ve yazma işlemlerini farklı modellere ayırarak bu sorunları giderir.CQRS addresses these problems by separating reads and writes into separate models, using commands to update data, and queries to read data.

  • Komutlar veri merkezli değil, görev tabanlı olmalıdır.Commands should be task based, rather than data centric. ("Book hotel room," not "set ReservationStatus to Reserved.") Komutlar zaman uyumlu olarak işlenmek yerine zaman uyumsuz işlemeye yönelik olarak bir sıraya yerleştirilebilir.("Book hotel room," not "set ReservationStatus to Reserved.") Commands may be placed on a queue for asynchronous processing, rather than being processed synchronously.

  • Sorgular, veritabanını hiçbir zaman değiştirmez.Queries never modify the database. Bir sorgu, herhangi bir etki alanı bilgisini kapsamayan bir DTO döndürür.A query returns a DTO that does not encapsulate any domain knowledge.

Daha büyük bir ayırma işlemi için okuma verilerini, yazma verilerinden fiziksel olarak ayırabilirsiniz.For greater isolation, you can physically separate the read data from the write data. Bu durumda, okuma veritabanı, sorgular için optimize edilmiş kendi veri şemasını kullanabilir.In that case, the read database can use its own data schema that is optimized for queries. Örneğin, karmaşık birleştirmelerden veya karmaşık O/RM eşlemelerinden kaçınmak için verilerin gerçekleştirilmiş bir görünümünü depolayabilir.For example, it can store a materialized view of the data, in order to avoid complex joins or complex O/RM mappings. Ayrıca farklı türde bir veri deposu bile kullanabilir.It might even use a different type of data store. Örneğin, yazma veritabanı ilişkisel olabilse de okuma veritabanı bir belge veritabanıdır.For example, the write database might be relational, while the read database is a document database.

Ayrı okuma ve yazma veritabanları kullanılıyorsa bunların eşitlenmiş halde tutulması gerekir. Genellikle bu yazma modeli, veritabanı her güncelleştirildiğinde bir olay yayımlaması sağlanarak gerçekleştirilir.If separate read and write databases are used, they must be kept in sync. Typically this is accomplished by having the write model publish an event whenever it updates the database. Veritabanının güncelleştirilmesi ve olayın yayımlanması tek bir işlem içinde gerçekleşmelidir.Updating the database and publishing the event must occur in a single transaction.

Bazı CQRS uygulamaları Olay Kaynağını Belirleme düzenini kullanır.Some implementations of CQRS use the Event Sourcing pattern. Bu düzenle uygulama durumu bir olay dizisi olarak depolanır.With this pattern, application state is stored as a sequence of events. Her olay, verilerdeki bir dizi değişikliği temsil eder.Each event represents a set of changes to the data. Geçerli durum, olaylar yeniden yürütülerek oluşturulur.The current state is constructed by replaying the events. CQRS bağlamında, Olay Kaynağını Belirleme işlevinin bir avantajı, diğer bileşenlere (özellikle okuma modeline) bildirimde bulunmak için aynı olayların kullanılabilmesidir.In a CQRS context, one benefit of Event Sourcing is that the same events can be used to notify other components — in particular, to notify the read model. Okuma modeli, geçerli durumun anlık görüntüsünü oluşturmak için olayları kullanır; bu, sorgular için daha etkilidir.The read model uses the events to create a snapshot of the current state, which is more efficient for queries. Ancak Olay Kaynağını Belirleme, tasarıma karmaşıklık ekler.However, Event Sourcing adds complexity to the design.

CQRS olayları

Bu mimarinin kullanılacağı durumlarWhen to use this architecture

Aynı verilere birden fazla kullanıcının eriştiği etki alanları için (özellikle okuma ve yazma iş yükleri asimetrik olduğunda) CQRS’yi kullanmayı deneyin.Consider CQRS for collaborative domains where many users access the same data, especially when the read and write workloads are asymmetrical.

CQRS, bir sistemin tamamı için geçerli olan üst düzey bir mimari değildir.CQRS is not a top-level architecture that applies to an entire system. CQRS’yi yalnızca okumayı ve yazmayı ayırmanın açıkça faydalı olacağı söz konusu alt sistemlerde uygulayın.Apply CQRS only to those subsystems where there is clear value in separating reads and writes. Aksi takdirde, hiçbir avantajı olmadan daha fazla karmaşıklık yaratmış olursunuz.Otherwise, you are creating additional complexity for no benefit.

AvantajlarBenefits

  • Bağımsız olarak ölçeklendirme.Independently scaling. CQRS, okuma ve yazma iş yüklerinin bağımsız olarak ölçeklendirilebilmesine olanak tanır ve daha az sayıda kilit çakışması oluşmasını sağlayabilir.CQRS allows the read and write workloads to scale independently, and may result in fewer lock contentions.
  • İyileştirilmiş veri şemaları.Optimized data schemas. Yazma tarafı, sorgular için en iyi duruma getirilmiş bir şemayı; yazma tarafı ise güncelleştirmeler için en iyi duruma getirilmiş bir şemayı kullanır.The read side can use a schema that is optimized for queries, while the write side uses a schema that is optimized for updates.
  • Güvenlik.Security. Veriler üzerinde yazma işlemini yalnızca uygun etki alanı varlıklarının gerçekleştirmesini sağlamak artık daha kolay.It's easier to ensure that only the right domain entities are performing writes on the data.
  • Görev ayrımı.Separation of concerns. Okuma ve yazma taraflarının ayrılması daha sürdürülebilir ve esnek modellerin oluşmasını sağlayabilir.Segregating the read and write sides can result in models that are more maintainable and flexible. Karmaşık iş mantığının büyük bir kısmı yazma modelinden geçer.Most of the complex business logic goes into the write model. Okuma modeli oldukça basit olabilir.The read model can be relatively simple.
  • Daha basit sorgular.Simpler queries. Uygulama, okuma veritabanında gerçekleştirilmiş bir görünüm depolayarak, sorgu oluşturma sırasında karmaşık birleştirme işlemlerinden kaçınabilir.By storing a materialized view in the read database, the application can avoid complex joins when querying.

ZorluklarChallenges

  • Karmaşıklık.Complexity. CQRS mantığı temel olarak basittir.The basic idea of CQRS is simple. Ancak özellikle Olay Kaynağını Belirleme düzeni dahilse bu, daha karmaşık bir uygulama tasarımına neden olabilir.But it can lead to a more complex application design, especially if they include the Event Sourcing pattern.

  • Mesajlaşma.Messaging. CQRS için mesajlaşma gerekli olmasa da komutları işlemek ve güncelleştirme olaylarını yayımlamak için yaygın olarak kullanılan bir işlevdir.Although CQRS does not require messaging, it's common to use messaging to process commands and publish update events. Bu durumda uygulamanın, ileti hatalarını veya yinelenen iletileri işlemesi gerekir.In that case, the application must handle message failures or duplicate messages.

  • Nihai tutarlılık.Eventual consistency. Okuma ve yazma veritabanlarını ayırıyorsanız okuma veritabanı eski olabilir.If you separate the read and write databases, the read data may be stale.

En iyi uygulamalarBest practices

Mikro hizmetlerde CQRSCQRS in microservices

CQRS özellikle mikro hizmet mimarisinde kullanışlı olabilir.CQRS can be especially useful in a microservices architecture. Mikro hizmetlere ilişkin ilkelerden biri, bir hizmetin başka bir hizmete ait veri deposuna doğrudan erişememesidir.One of the principles of microservices is that a service cannot directly access another service's data store.

Yanlış bir mikro hizmetler yaklaşımı diyagramı

Aşağıdaki diyagramda A Hizmeti bir veri deposuna yazar, B Hizmeti ise verilerin gerçekleştirilmiş görünümünü tutar.In the following diagram, Service A writes to a data store, and Service B keeps a materialized view of the data. A Hizmeti; bir olayın, veri deposundaki her yazma işleminde bu olayı yayımlar.Service A publishes an event whenever it writes to the data store. B Hizmeti olaya abone olur.Service B subscribes to the event.

Doğru bir mikro hizmetler yaklaşımı diyagramı