In the commonly used three-tier architecture, the data access layer is usually used to modify or query data, and general modifications and queries use the same entity. There may be no problems with some simple systems of business logic, but as the system logic becomes more complex and users increase, there are some performance problems with this design. Although some of the design of read-write separation can be done on db, there are still some problems in the business if they are mixed together in reading and writing.
This article describes the command query duty separation mode, which responsibility SEGREGATION,CQRS from the Business (command, add, delete, change, modify the system state) and queries (query, check, Behavior that does not modify the state of the system. So that the logic is more clear and convenient for different parts of the targeted optimization. This paper first briefly introduces the problems of the traditional crud mode, then introduces the CQRS mode, and finally demonstrates how to implement the CQRS mode with a simple online diary system. To talk about reading and writing, let's first look at the traditional crud problem.
The problem of a crud way
In a previous management system, commands (command, typically used to update data, manipulate DB) and queries (query) typically used entity objects in the repository in the data access layer (these objects are mappings to tables in db), These entities may be a row of data in SQL Server or multiple tables.
Typically, the increase in db execution, delete, change, check (CRUD) are the entity objects for the system. such as through the data access layer to obtain data, and then through the Transfer object DTO to the performance layer. Alternatively, the user needs to update the data, pass the data to model through the Dto object, and then write the database back through the data access layer, all of the interactions in the system are related to data query and storage, which can be considered data-driven (Data-driven), as shown in the following illustration:
For some simpler systems, the use of this crud is designed to meet the requirements. Especially through some code generation tools and ORM, etc. can be very convenient and fast implementation of functions.
But there are some problems with the traditional crud approach:
Using the same object entity for database reading and writing can be too rough, in most cases, such as editing, you may need to update individual fields, but you need to wear the entire object, and some fields do not need to be updated. You may need only individual fields at the presentation level at the time of the query, but you need to query and return the entire entity object. When you use the same entity object to read and write the same data, you may encounter resource competition, often to deal with the problem of locks, when writing data, need to lock. You need to determine whether dirty reads are allowed when reading data. This increases the logic and complexity of the system and can have an impact on the growth of system throughput. Synchronized, interacting directly with the database can affect performance and responsiveness, and may result in performance bottlenecks, in the case of simultaneous access to large amounts of data. Because the same entity object is used in read-write operations, the administration of security and permissions becomes more complex.
Here is a very important question is that the frequency of reading and writing in the system is biased to read, or biased, as the general data structure in the search and modify the time complexity is not the same, in the design of the structure of the system also need to consider such a problem. The solution is that we often use the database to read and write separation. Let the main database handle the transactional increase, delete, change operation (Insert,update,delete) operation, let the query operation from the database (select operation), database replication is used to synchronize the changes caused by transactional operations to the cluster from the database. This only handles read and write separation from the DB perspective, but reads and writes from the business or system are still stored together. They are all using the same entity object.
The separation of read and write from the business is the next step in the command query duty separation mode.
Two what is CQRS
CQRS first came from Betrand Meyer (Eiffel language father, open-closed principle OCP author) in object-oriented Software construction This book refers to a command query separation (commands query SEPARATION,CQS) concept. The basic idea is that the methods of any one object can be divided into two main categories:
Command: Does not return any results (void), but changes the state of the object. Query: Returns the result, but does not change the state of the object and has no side effects on the system.
According to CQS, any method can be divided into two parts: command and query.
private int i = 0;
private int increase (int value)
{
i + = value;
return i;
}
In this way, we execute a command that adds the variable I, and executes a query that returns the value of I, which, if followed by CQS, can be split into command and query two methods, as follows:
private void Increasecommand (int value)
{
i + = value;
}
private int QueryValue ()
{return
i;
}
The separation of operations and queries allows us to better grasp the details of the object and to better understand which operations will change the state of the system. Of course, CQS also has some drawbacks, such as the code needs to handle multithreading situation.
CQRS is a simple model for further improvement of the CQS model. It was by Greg Young in Cqrs, Task Based UIs, Event Sourcing agh! Presented in this article. "CQRS is simply going to create an object before it is split into two objects, which is based on the principle of whether the method executes the command or executes the query (this is consistent with the CQS definition)."
CQRS separates data query Operations (Queries) from data modification Operations (Commands) using a decoupled interface, which means that the data model used in the query and update process is also different. So the logic of reading and writing is separated.