Wzorzec podziału odpowiedzialności polecenia i zapytania (CQRS)Command and Query Responsibility Segregation (CQRS) pattern

Wzorzec segregacji odpowiedzialność za polecenia i kwerendy (CQRS) oddziela operacje odczytu i aktualizacji dla magazynu danych.The Command and Query Responsibility Segregation (CQRS) pattern separates read and update operations for a data store. Implementacja CQRS w aplikacji może zmaksymalizować jego wydajność, skalowalność i bezpieczeństwo.Implementing CQRS in your application can maximize its performance, scalability, and security. Elastyczność utworzona przez migrację do CQRS pozwala systemowi lepiej ewoluować w czasie i zapobiega polecenia aktualizacji z przyczyną konfliktów scalania na poziomie domeny.The flexibility created by migrating to CQRS allows a system to better evolve over time and prevents update commands from causing merge conflicts at the domain level.

ProblemThe problem

W tradycyjnych architekturach ten sam model danych jest używany do wysyłania zapytań do bazy danych i aktualizowania jej.In traditional architectures, the same data model is used to query and update a database. Jest to proste i dobrze się sprawdza w przypadku podstawowych operacji CRUD.That's simple and works well for basic CRUD operations. Jednak w bardziej złożonych aplikacjach ta metoda może stać się niewydolna.In more complex applications, however, this approach can become unwieldy. Na przykład po stronie odczytu aplikacja może wykonywać wiele różnych zapytań zwracających obiekty transferu danych (DTO, data transfer object) o różnych kształtach.For example, on the read side, the application may perform many different queries, returning data transfer objects (DTOs) with different shapes. Mapowanie obiektu może stać się skomplikowane.Object mapping can become complicated. Po stronie zapisu model może wdrażać złożoną walidację i logikę biznesową.On the write side, the model may implement complex validation and business logic. W efekcie możesz uzyskać zbyt skomplikowany model, który wykonuje zbyt dużo działań.As a result, you can end up with an overly complex model that does too much.

Obciążenia odczytu i zapisu są często asymetryczne, z bardzo różnymi wymaganiami dotyczącymi wydajności i skali.Read and write workloads are often asymmetrical, with very different performance and scale requirements.

Tradycyjna architektura CRUD

  • Często występuje niezgodność między odczytu i zapisu reprezentacje danych, takich jak dodatkowe kolumny lub właściwości, które muszą być aktualizowane poprawnie, nawet jeśli nie są one wymagane w ramach operacji.There is often a mismatch between the read and write representations of the data, such as additional columns or properties that must be updated correctly even though they aren't required as part of an operation.

  • Rywalizacja o dane może wystąpić, gdy operacje są wykonywane równolegle na tym samym zestawie danych.Data contention can occur when operations are performed in parallel on the same set of data.

  • Tradycyjne podejście może mieć negatywny wpływ na wydajność ze względu na obciążenie w warstwie magazynu danych i dostępu do danych oraz złożoność zapytań wymaganych do pobierania informacji.The traditional approach can have a negative effect on performance due to load on the data store and data access layer, and the complexity of queries required to retrieve information.

  • Zarządzanie zabezpieczeniami i uprawnieniami może stać się złożone, ponieważ każda jednostka podlega zarówno operacji odczytu i zapisu, które mogą uwidaczniać dane w niewłaściwym kontekście.Managing security and permissions can become complex, because each entity is subject to both read and write operations, which might expose data in the wrong context.

RozwiązanieSolution

CQRS oddziela odczyty i zapisuje w różnych modelach, za pomocą poleceń do aktualizacji danych i kwerend do odczytu danych.CQRS separates reads and writes into different models, using commands to update data, and queries to read data.

  • Polecenia powinny być oparte na zadaniach, a nie skoncentrowane na danych.Commands should be task based, rather than data centric. ("Zarezerwuj pokój hotelowy", a nie "ustaw Status Rezerwacji na Zarezerwowany").("Book hotel room", not "set ReservationStatus to Reserved").
  • Polecenia mogą być umieszczane w kolejce do przetwarzania asynchronicznie, a nie przetwarzane synchronicznie.Commands may be placed on a queue for asynchronous processing, rather than being processed synchronously.
  • Zapytania nigdy nie modyfikują bazy danych.Queries never modify the database. Zapytanie zwraca obiekt DTO, który nie hermetyzuje żadnej wiedzy domeny.A query returns a DTO that does not encapsulate any domain knowledge.

Modele mogą być następnie izolowane, jak pokazano na poniższym diagramie, chociaż nie jest to bezwzględne wymaganie.The models can then be isolated, as shown in the following diagram, although that's not an absolute requirement.

Podstawowa architektura CQRS

Posiadanie oddzielnych modeli zapytań i aktualizacji upraszcza projektowanie i implementację.Having separate query and update models simplifies the design and implementation. Jednak jedną wadą jest to, że kod CQRS nie może być automatycznie generowany ze schematu bazy danych przy użyciu mechanizmów szkieletu, takich jak narzędzia O/RM.However, one disadvantage is that CQRS code can't automatically be generated from a database schema using scaffolding mechanisms such as O/RM tools.

Aby uzyskać większą izolację, możesz fizycznie oddzielić odczyt danych od zapisu danych.For greater isolation, you can physically separate the read data from the write data. W takim przypadku baza danych odczytu może używać własnego schematu danych zoptymalizowanego dla zapytań.In that case, the read database can use its own data schema that is optimized for queries. Na przykład może ona przechowywać zmaterializowany widok danych, aby uniknąć złożonych połączeń lub złożonych mapowań obiektowo-relacyjnych.For example, it can store a materialized view of the data, in order to avoid complex joins or complex O/RM mappings. Może ona nawet używać innego typu magazynu danych.It might even use a different type of data store. Na przykład baza danych zapisu może być relacyjna, natomiast baza danych odczytu może być bazą danych dokumentów.For example, the write database might be relational, while the read database is a document database.

Jeśli używane są oddzielne bazy danych odczytu i zapisu, muszą być synchronizowane. Zazwyczaj jest to realizowane przez model zapisu opublikować zdarzenie, gdy aktualizuje bazę danych.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. Aktualizacja bazy danych i publikowanie zdarzenia muszą nastąpić w ramach jednej transakcji.Updating the database and publishing the event must occur in a single transaction.

Architektura CQRS z oddzielnymi magazynami odczytu i zapisu

Magazyn odczytu może być repliką tylko do odczytu magazynu zapisu lub magazyny odczytu i zapisu mogą mieć całkowicie inną strukturę.The read store can be a read-only replica of the write store, or the read and write stores can have a different structure altogether. Za pomocą wielu replik tylko do odczytu można zwiększyć wydajność kwerendy, szczególnie w scenariuszach rozproszonych, gdzie repliki tylko do odczytu znajdują się w pobliżu wystąpień aplikacji.Using multiple read-only replicas can increase query performance, especially in distributed scenarios where read-only replicas are located close to the application instances.

Rozdzielenie magazynów odczytu i zapisu zapewnia każdemu z nich możliwość odpowiedniego skalowania w celu dopasowania do obciążenia.Separation of the read and write stores also allows each to be scaled appropriately to match the load. Na przykład magazyny odczytu są zazwyczaj znacznie bardziej obciążone niż magazyny zapisu.For example, read stores typically encounter a much higher load than write stores.

Niektóre implementacje podejścia CQRS używają wzorca określania źródła zdarzeń.Some implementations of CQRS use the Event Sourcing pattern. Za pomocą tego wzorca stan aplikacji jest przechowywany jako sekwencja zdarzeń.With this pattern, application state is stored as a sequence of events. Każde zdarzenie reprezentuje zestaw zmian danych.Each event represents a set of changes to the data. Bieżący stan jest tworzony przez ponowne odtwarzanie zdarzeń.The current state is constructed by replaying the events. W kontekście CQRS korzyścią określania źródła zdarzeń jest to, że te same zdarzenia mogą być używane do powiadamiania innych składników — w szczególności modelu odczytu.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. Model odczytu używa zdarzeń do tworzenia migawki bieżącego stanu, co jest bardziej wydajne dla zapytań.The read model uses the events to create a snapshot of the current state, which is more efficient for queries. Jednak określanie źródła zdarzeń zwiększa złożoność projektu.However, Event Sourcing adds complexity to the design.

Korzyści z CQRS obejmują:Benefits of CQRS include:

  • Niezależne skalowanie.Independent scaling. Podejście CQRS umożliwia niezależne skalowanie obciążeń odczytu oraz zapisu i może skutkować mniejszą liczbą blokad rywalizacji.CQRS allows the read and write workloads to scale independently, and may result in fewer lock contentions.
  • Zoptymalizowane schematy danych.Optimized data schemas. Strona odczytu może używać schematu zoptymalizowanego dla zapytań, a strona zapisu — schematu zoptymalizowanego dla aktualizacji.The read side can use a schema that is optimized for queries, while the write side uses a schema that is optimized for updates.
  • Bezpieczeństwo.Security. Łatwiej jest zapewnić możliwość wykonywania operacji zapisu względem danych tylko przez właściwe jednostki domeny.It's easier to ensure that only the right domain entities are performing writes on the data.
  • Separacja problemów.Separation of concerns. Oddzielenie stron odczytu i zapisu może doprowadzić do modeli, które są łatwiejsze w obsłudze i bardziej elastyczne.Segregating the read and write sides can result in models that are more maintainable and flexible. Większość złożonej logiki biznesowej przechodzi do modelu zapisu.Most of the complex business logic goes into the write model. Model odczytu może być stosunkowo prosty.The read model can be relatively simple.
  • Prostsze zapytania.Simpler queries. Zapisując zmaterializowany widok w bazie danych odczytu, aplikacja może uniknąć złożonych połączeń podczas wykonywania zapytania.By storing a materialized view in the read database, the application can avoid complex joins when querying.

Problemy i zagadnienia związane z wdrażaniemImplementation issues and considerations

Niektóre wyzwania związane z wdrożeniem tego wzorca obejmują:Some challenges of implementing this pattern include:

  • Złożoność.Complexity. Podstawowa koncepcja CQRS jest prosta.The basic idea of CQRS is simple. Jednak może ona prowadzić do bardziej złożonego projektu aplikacji zwłaszcza wtedy, gdy zawiera wzorzec określania źródła zdarzeń.But it can lead to a more complex application design, especially if they include the Event Sourcing pattern.

  • Wiadomości .Messaging. Chociaż podejście CQRS nie wymaga obsługi komunikatów, jest ona często używana do przetwarzania poleceń i publikowania zdarzeń aktualizacji.Although CQRS does not require messaging, it's common to use messaging to process commands and publish update events. W takim przypadku aplikacja musi obsługiwać błędy komunikatów lub zduplikowane komunikaty.In that case, the application must handle message failures or duplicate messages.

  • Spójność ostateczna.Eventual consistency. Jeśli oddzielisz bazy danych odczytu i zapisu, dane odczytu mogą być nieaktualne.If you separate the read and write databases, the read data may be stale. Magazyn modeli odczytu musi zostać zaktualizowany w celu odzwierciedlenia zmian w magazynie modeli zapisu i może być trudne do wykrycia, gdy użytkownik wydał żądanie na podstawie starych odczytu danych.The read model store must be updated to reflect changes to the write model store, and it can be difficult to detect when a user has issued a request based on stale read data.

Kiedy używać tego wzorcaWhen to use this pattern

Należy wziąć pod uwagę CQRS dla następujących scenariuszy:Consider CQRS for the following scenarios:

  • Domeny współpracy, w których wielu użytkowników uzyskuje równocześnie dostęp do tych samych danych.Collaborative domains where many users access the same data in parallel. CQRS pozwala zdefiniować polecenia z wystarczającą szczegółowością, aby zminimalizować konflikty scalania na poziomie domeny, a konflikty, które powstają mogą być scalane przez polecenie.CQRS allows you to define commands with enough granularity to minimize merge conflicts at the domain level, and conflicts that do arise can be merged by the command.

  • Oparte na zadaniach interfejsy użytkownika, gdzie użytkownicy są prowadzeni przez złożony proces w szeregu kroków lub za pomocą złożonych modeli domeny.Task-based user interfaces where users are guided through a complex process as a series of steps or with complex domain models. Model zapisu ma pełny stos przetwarzania poleceń z logiką biznesową, sprawdzanie poprawności danych wejściowych i sprawdzanie poprawności biznesowej.The write model has a full command-processing stack with business logic, input validation, and business validation. Model zapisu może traktować zestaw skojarzonych obiektów jako pojedynczą jednostkę dla zmian danych (agregacja, w terminologii DDD) i upewnij się, że te obiekty są zawsze w stanie spójnym.The write model may treat a set of associated objects as a single unit for data changes (an aggregate, in DDD terminology) and ensure that these objects are always in a consistent state. Model odczytu nie ma logiki biznesowej ani stosu sprawdzania poprawności i po prostu zwraca DTO do użycia w modelu widoku.The read model has no business logic or validation stack, and just returns a DTO for use in a view model. Model odczytu jest ostatecznie spójny z modelem zapisu.The read model is eventually consistent with the write model.

  • Scenariusze, w których wydajność odczytów danych musi być dostrojony oddzielnie od wydajności zapisów danych, zwłaszcza gdy liczba odczytów jest znacznie większa niż liczba zapisów.Scenarios where performance of data reads must be fine tuned separately from performance of data writes, especially when the number of reads is much greater than the number of writes. W tym scenariuszu można skalować w poziomie modelu odczytu, ale uruchomić model zapisu na tylko kilka wystąpień.In this scenario, you can scale out the read model, but run the write model on just a few instances. Mała liczba wystąpień modelu zapisu pomaga też w zminimalizowaniu występowania konfliktów scalania.A small number of write model instances also helps to minimize the occurrence of merge conflicts.

  • Scenariusze, w których jeden zespół deweloperów może skupić się na złożonym modelu domeny będącym częścią modelu zapisu, a inny zespół może skupić się na modelu odczytu i interfejsach użytkownika.Scenarios where one team of developers can focus on the complex domain model that is part of the write model, and another team can focus on the read model and the user interfaces.

  • Scenariusze, w których system ma podlegać ewolucji w czasie i może zawierać wiele wersji modelu lub w których reguły biznesowe są regularnie zmieniane.Scenarios where the system is expected to evolve over time and might contain multiple versions of the model, or where business rules change regularly.

  • Integracja z innymi systemami, zwłaszcza w połączeniu z określaniem źródła zdarzeń, gdzie błąd czasowy jednego podsystemu nie powinien wpływać na dostępność innych.Integration with other systems, especially in combination with event sourcing, where the temporal failure of one subsystem shouldn't affect the availability of the others.

Ten wzorzec nie jest zalecany, gdy:This pattern isn't recommended when:

  • Domena lub reguły biznesowe są proste.The domain or the business rules are simple.

  • Wystarczy prosty interfejs użytkownika w stylu CRUD i operacje dostępu do danych.A simple CRUD-style user interface and data access operations are sufficient.

Rozważ stosowanie podejścia CQRS do ograniczonych sekcji systemu, gdzie będzie ono najbardziej przydatne.Consider applying CQRS to limited sections of your system where it will be most valuable.

Określanie źródła zdarzeń i podejście CQRSEvent Sourcing and CQRS

Wzorzec CQRS jest często używany wraz ze wzorcem określania źródła zdarzeń.The CQRS pattern is often used along with the Event Sourcing pattern. Systemy oparte na wzorcu CQRS używają oddzielnych modeli odczytu i zapisu danych, a każdy z nich jest dostosowany do odpowiednich zadań i często znajduje się w fizycznie oddzielonych magazynach.CQRS-based systems use separate read and write data models, each tailored to relevant tasks and often located in physically separate stores. W przypadku użycia ze wzorcem pozyskiwanie zdarzeńmagazyn zdarzeń jest modelem zapisu i jest oficjalnym źródłem informacji.When used with the Event Sourcing pattern, the store of events is the write model, and is the official source of information. Model odczytu systemu opartego na podejściu CQRS udostępnia zmaterializowane widoki danych zwykle jako widoki w wysokim stopniu zdenormalizowane.The read model of a CQRS-based system provides materialized views of the data, typically as highly denormalized views. Widoki te są dostosowane do interfejsów i wyświetlają wymagania dotyczące aplikacji, które pomagają w zmaksymalizowaniu wydajności zarówno wyświetlania, jak i zapytań.These views are tailored to the interfaces and display requirements of the application, which helps to maximize both display and query performance.

Używanie strumienia zdarzeń jako magazynu zapisu, a nie rzeczywistych danych w punkcie w czasie, pozwala uniknąć konfliktów aktualizacji dla jednej wartości zagregowanej oraz maksymalizuje wydajność i skalowalność.Using the stream of events as the write store, rather than the actual data at a point in time, avoids update conflicts on a single aggregate and maximizes performance and scalability. Zdarzenia mogą służyć do asynchronicznego generowania zmaterializowanych widoków danych, które są używane do zapełnienia magazynu odczytu.The events can be used to asynchronously generate materialized views of the data that are used to populate the read store.

Ponieważ magazyn zdarzeń jest oficjalnym źródłem informacji, istnieje możliwość usunięcia zmaterializowanych widoków i odtworzenia wszystkich wcześniejszych zdarzeń, aby utworzyć nową reprezentację bieżącego stanu, gdy system ewoluuje lub gdy model odczytu należy zmienić.Because the event store is the official source of information, it is possible to delete the materialized views and replay all past events to create a new representation of the current state when the system evolves, or when the read model must change. Zmaterializowane widoki są w zasadzie trwałą pamięcią podręczną umożliwiającą tylko odczyt danych.The materialized views are in effect a durable read-only cache of the data.

W razie używania podejścia CQRS w połączeniu z wzorcem określania źródła zdarzeń należy rozważyć następujące kwestie:When using CQRS combined with the Event Sourcing pattern, consider the following:

  • Podobnie jak w przypadku każdego systemu, gdzie magazyny zapisu i odczytu są oddzielone, systemy oparte na tym wzorcu są spójne tylko ostatecznie.As with any system where the write and read stores are separate, systems based on this pattern are only eventually consistent. Będzie istnieć pewne opóźnienie między generowanym zdarzeniem i aktualizowanym magazynem danych.There will be some delay between the event being generated and the data store being updated.

  • Wzorzec zwiększa złożoność, ponieważ musi zostać utworzony kod do inicjowania i obsługi zdarzeń oraz łączenia albo aktualizowania odpowiednich widoków lub obiektów wymaganych przez zapytania lub modele odczytu.The pattern adds complexity because code must be created to initiate and handle events, and assemble or update the appropriate views or objects required by queries or a read model. Złożoność wzorca CQRS, gdy jest on używany ze wzorcem określania źródła zdarzeń, może utrudnić pomyślne wdrożenie i wymaga innego podejścia do projektowania systemów.The complexity of the CQRS pattern when used with the Event Sourcing pattern can make a successful implementation more difficult, and requires a different approach to designing systems. Jednak określanie źródła zdarzeń może ułatwić modelowanie domeny i uprościć przebudowę widoków lub tworzenie nowych, ponieważ cel zmian w danych jest zachowany.However, event sourcing can make it easier to model the domain, and makes it easier to rebuild views or create new ones because the intent of the changes in the data is preserved.

  • Generowanie zmaterializowanych widoków do użycia w modelu odczytu lub projekcji danych przez odtwarzanie i obsługę zdarzeń dla określonych obiektów lub kolekcji obiektów może wymagać znacznego czasu przetwarzania i wykorzystania zasobów.Generating materialized views for use in the read model or projections of the data by replaying and handling the events for specific entities or collections of entities can require significant processing time and resource usage. Dotyczy to zwłaszcza sytuacji, w których jest wymagane sumowanie lub analiza wartości w długim okresie, ponieważ może być konieczne zbadanie wszystkich skojarzonych zdarzeń.This is especially true if it requires summation or analysis of values over long periods, because all the associated events might need to be examined. Rozwiąż ten problem, wprowadzając migawki danych w zaplanowanych odstępach czasu, takie jak licznik łącznej liczby określonych akcji, które wystąpiły, lub bieżący stan obiektu.Resolve this by implementing snapshots of the data at scheduled intervals, such as a total count of the number of a specific action that have occurred, or the current state of an entity.

PrzykładExample

Poniższy kod pokazuje pewne fragmenty przykładu wdrożenia podejścia CQRS, które używają różnych definicji modeli odczytu i zapisu.The following code shows some extracts from an example of a CQRS implementation that uses different definitions for the read and the write models. Interfejsy modelu nie wymagają żadnych funkcji podstawowych magazynów danych oraz mogą ewoluować i mogą być niezależnie strojone, ponieważ te interfejsy są rozdzielone.The model interfaces don't dictate any features of the underlying data stores, and they can evolve and be fine-tuned independently because these interfaces are separated.

Poniższy kod przedstawia definicję modelu odczytu.The following code shows the read model definition.

// Query interface
namespace ReadModel
{
  public interface ProductsDao
  {
    ProductDisplay FindById(int productId);
    ICollection<ProductDisplay> FindByName(string name);
    ICollection<ProductInventory> FindOutOfStockProducts();
    ICollection<ProductDisplay> FindRelatedProducts(int productId);
  }

  public class ProductDisplay
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal UnitPrice { get; set; }
    public bool IsOutOfStock { get; set; }
    public double UserRating { get; set; }
  }

  public class ProductInventory
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public int CurrentStock { get; set; }
  }
}

System pozwala użytkownikom oceniać produkty.The system allows users to rate products. Kod aplikacji realizuje to przy użyciu polecenia RateProduct pokazanego w poniższym kodzie.The application code does this using the RateProduct command shown in the following code.

public interface ICommand
{
  Guid Id { get; }
}

public class RateProduct : ICommand
{
  public RateProduct()
  {
    this.Id = Guid.NewGuid();
  }
  public Guid Id { get; set; }
  public int ProductId { get; set; }
  public int Rating { get; set; }
  public int UserId {get; set; }
}

System używa klasy ProductsCommandHandler do obsługi poleceń wysyłanych przez aplikację.The system uses the ProductsCommandHandler class to handle commands sent by the application. Klienci wysyłają zazwyczaj polecenia do domeny za pośrednictwem systemu obsługi komunikatów, takiego jak kolejka.Clients typically send commands to the domain through a messaging system such as a queue. Procedura obsługi poleceń akceptuje te polecenia i wywołuje metody interfejsu domeny.The command handler accepts these commands and invokes methods of the domain interface. Stopień szczegółowości każdego polecenia pozwala zmniejszyć prawdopodobieństwo żądań powodujących konflikt.The granularity of each command is designed to reduce the chance of conflicting requests. Poniższy kod przedstawia zarys klasy ProductsCommandHandler.The following code shows an outline of the ProductsCommandHandler class.

public class ProductsCommandHandler :
    ICommandHandler<AddNewProduct>,
    ICommandHandler<RateProduct>,
    ICommandHandler<AddToInventory>,
    ICommandHandler<ConfirmItemShipped>,
    ICommandHandler<UpdateStockFromInventoryRecount>
{
  private readonly IRepository<Product> repository;

  public ProductsCommandHandler (IRepository<Product> repository)
  {
    this.repository = repository;
  }

  void Handle (AddNewProduct command)
  {
    ...
  }

  void Handle (RateProduct command)
  {
    var product = repository.Find(command.ProductId);
    if (product != null)
    {
      product.RateProduct(command.UserId, command.Rating);
      repository.Save(product);
    }
  }

  void Handle (AddToInventory command)
  {
    ...
  }

  void Handle (ConfirmItemsShipped command)
  {
    ...
  }

  void Handle (UpdateStockFromInventoryRecount command)
  {
    ...
  }
}

Podczas implementowania tego wzorca są przydatne następujące wzorce i wskazówki:The following patterns and guidance are useful when implementing this pattern:

  • Podkład spójności danych.Data Consistency Primer. Opisuje problemy, które zazwyczaj występują z powodu spójności ostatecznej między magazynami danych odczytu i zapisu podczas używania wzorca CQRS, i sposoby rozwiązywania tych problemów.Explains the issues that are typically encountered due to eventual consistency between the read and write data stores when using the CQRS pattern, and how these issues can be resolved.

  • Data Partitioning Guidance (Wskazówki dotyczące partycjonowania danych).Data Partitioning Guidance. W tym artykule opisano najlepsze rozwiązania dotyczące dzielenia danych na partycje, które mogą być zarządzane i dostępne oddzielnie, aby poprawić skalowalność, zmniejszyć rywalizację i zoptymalizować wydajność.Describes best practices for dividing data into partitions that can be managed and accessed separately to improve scalability, reduce contention, and optimize performance.

  • Wzór źródła zdarzeń.Event Sourcing pattern. Bardziej szczegółowo opisuje sposób używania określania źródła zdarzeń ze wzorcem CQRS w celu uproszczenia zadań w złożonych domenach oraz jednoczesnego zwiększenia wydajności, skalowalności i elastyczności.Describes in more detail how Event Sourcing can be used with the CQRS pattern to simplify tasks in complex domains while improving performance, scalability, and responsiveness. Ponadto przedstawia sposób zapewniania spójności danych transakcyjnych przy zachowaniu pełnego dziennika inspekcji i historii umożliwiającej akcje kompensacyjne.As well as how to provide consistency for transactional data while maintaining full audit trails and history that can enable compensating actions.

  • Zmaterializowany widok wzoru.Materialized View pattern. Model odczytu implementacji CQRS może zawierać zmaterializowane widoki danych modelu zapisu lub może on służyć do generowania zmaterializowanych widoków.The read model of a CQRS implementation can contain materialized views of the write model data, or the read model can be used to generate materialized views.

  • Przewodnik po wzorcach i rozwiązaniach CQRS Journey (Podróż CQRS).The patterns & practices guide CQRS Journey. W szczególności wprowadzenie wzorca segregacji odpowiedzialność kwerendy polecenia eksploruje wzorzec i gdy jest to przydatne i Epilog: Wyciągnięte wnioski pomaga zrozumieć niektóre problemy, które pojawiają się podczas korzystania z tego wzorca.In particular, Introducing the Command Query Responsibility Segregation pattern explores the pattern and when it's useful, and Epilogue: Lessons Learned helps you understand some of the issues that come up when using this pattern.

  • Wpis CQRS Martina Fowlera, który objaśnia podstawy wzorca i zawiera linki do innych przydatnych zasobów.The post CQRS by Martin Fowler, which explains the basics of the pattern and links to other useful resources.