A text interpretation CQRS (rpm)

CQRS start talking, CQRS stands for Command Query Responsibility Segregation, translated into Chinese called the command query separation of duties. Literally can see, this model requires the developer accordance with the responsibilities of the method is a command or query separation, what is the command? What is a query? We continue to look down.

Query & Command

What is the command? What is a query?

  • Command (Command): no results are returned (void), but will change the state of the object.
  • Query (Query): returns the result, but does not change the state of the object, no side effects on the system.

State of the object What does it mean?

State of the subject, we can understand its properties into, for example, we define a Person class, defined as follows:

Copy
public class Person {
    public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } public void Say(string word) { Console.WriteLine($"{Name} Say: {word}"); } }

In the Person class:

  • Name, Age: attributes (state)
  • Say (string): Method (behavior)

Then back to the content discussed in this section, is not a good understanding of it? When I define a method to change the Name or Age Person instances when this method belongs Command; if a given method, only queries Person information about instances when this method belongs to Query. When we would Command and Query separation of duties in accordance with, you just use the CQRS mode.

In fact, this is all the CQRS.

A friend may say, and if that's all CQRS also too simple, right? Yes, Road to Jane!

Separate read and write

When we were separated according to CQRS, you are not already seen this stuff too suitable for a separate read and write? When our database is master-slave mode, when the main library is responsible for writing, from the library is responsible for reading, exact match Command and Query, just perfect. So we are going to say about the separate read and write.

Mainstream database now supports master-slave mode, the main benefit from the convenient mode is I do failover, when the primary database goes down, they can quickly be enabled from the library, thereby reducing the system unavailable time.

When we use the database when the master-slave mode, if the application is not separate read and write, you will find basically useless from the library, main library busy dying every day, both responsible for writing, but also responsible for querying, accessing met a large amount of CPU time surge is common. However, from the library too busy, in addition to the main library to receive change records do data synchronization, and then nothing else to do, no matter how much pressure the main library, the library has been like with the CPU electrocardiogram 0-1-0-1. .. when we separate read and write, is responsible for writing the main library, from the library is responsible for reading the code to how to change it? We only need to define two Repository on it:

Copy
public interface IWritablePersonRepository {
    //写入数据的方法 } public interface IReadonlyPersonRepository { //读取数据的方法 } 

Connecting the main use of the library in IWritablePersonRepository, IReadonlyPersonRepository connection from the library used. Then, using the Command inside IWritablePersonRepository, used in the Query IReadonlyPersonRepository inside, so that in the application layer of the separate read and write.

CRUD and EventSourcing

Speaking CQRS, inevitably comes to the operation of these two data models. Why say data manipulation model it? Because data manipulation seriously affect the performance, and our separation is an important aim is to improve performance.

CRUD

CRUD (Create, Read, Update, Delete) is a data-oriented, it will be divided into operations on the data to create, update, delete, and read the four categories, which may correspond to our four operating SQL statement insert, select, update , delete, very intuitive, its existence is the operating data.

Because there is a reasonable, we can not say one-sided CRUD is good or bad, here only briefly about its problems:

  • Concurrency conflicts: This is a big problem, when A and B while updating a row, your transaction inevitable error.
  • Loss of context data manipulation: the problem is not small, for developers, we usually know when and by whom the data is what has been done to update, but CURD only stores the final state, the context of data manipulation nothing know.

Well, the more problems no longer listed, one is "concurrency conflicts" This is a problem, do not apply in a highly concurrent environments. Since CRUD NA, when we build high-performance applications, we can only hope the ES.

Event Souring

Event Souring, translated called event traceability. What does that mean? It objects to create, modify, delete and other operations as a series of events ( note: there is the difference between an event and command, will be mentioned later ), when only the persistent store events, media store event called EventStore, when to get the latest status of an object, the object retrieved by EventStore all Event and reload to get the latest state of the object. EventStore can be a database, disk files, MongoDB, etc., due to the Event of memory are added, concurrency issues so there is no conflict.

Command and Event

In CQRS + ES scheme, we have to face these two concepts, commands and events.

  • Command: describes the user's intent.
  • Event: describes the state of the object changes.

We give an example, say you want to update your profile, such as the Age of 35 revised to 18, then the corresponding command is:

Copy
public class PersonUpdateCommand {
    public string Id { get; set; } public int Age{ get; set; } public PersonUpdateCommand(string id, int age){ this.Id = id; this.Age = age; } }

PersonUpdateCommand is a command, which describes the intent of users to update personal information. When the program receives this command, it is necessary to change the data, causing the state change data, generating Event:

Copy
public class PersonAgeChangeEvent {
    public string Id { get; private set; } public int Age{ get; private set; } public PersonAgeChangeEvent(string id, int age){ this.Id = id; this.Age = age; } } public class PersonUpdateCommandHandler { private PersonUpdateCommand Command; public PersonUpdateCommandHandler(PersonUpdateCommand command) { this.Command = command; } public void Handle() { var person = GetPersonById(Command.Id); if(person.Age != Command.Age) { //生成并发送事件 var @event = new PersonAgeChangeEvent(Command.Id, Command.Age); EventBus.Send(@event); } } }

Data consistency

Common data consistency model in two ways: strong consistency and eventual consistency.

  • Strong Consistency: all users at any time or to query process is the most recent successful update data.
  • Eventual consistency: consistency and relatively strong, at some point the user to query or process data may be different, but the ultimate success of the updated data will be queried to all users or processes.

When it comes to the issue of consistency, we have to say about the CAP theorem.

CAP theorem

In 1998, a computer scientist at the University of California, Eric Brewer proposed a distributed system has three indicators.

  • Consistency: consistency
  • Availability: Availability
  • Partition tolerance: Fault-tolerant partition

They are the first letter C, A, P, these three indicators simultaneously impossible. This conclusion is called CAP theorem.

For distributed systems, constrained CAP theorem, eventual consistency became the only choice. To achieve eventual consistency, consider the following questions:

  • After the distributed system, we can not guarantee that every operation can be successfully implemented, such as network outages, downtime and other temporary server error, will lead the operation fails, then we will wait for Recovery: retry strategy retry. Retry operation for the system may cause some side effects, such as when the network you are paying interrupted, this time you do not know whether the payment is successful, retry again after the network, might result in a duplicate charge. If you want the system to avoid the harm caused by the retry, it is necessary to design a power operation and other operations.
    • Idempotency: simply put, it is a result of the execution time and perform multiple operations are created the same, does not produce side effects.
  • Withdrawal strategy: to retry strategy corresponding to determine if a final operation fails, then we need to undo this operation will restore the system to the state before the execution of the operation. Undo There are two, one is the direct object is modified to state before the execution, this situation will result in data auditing inconsistencies; the other is red-operate on similar financial, add a command to wash away on operation, to ensure data integrity and to meet the requirements of the audit data.

Messaging

Through the above description, we already know that in a system that all changes are based on operations and events generated by the operation triggered. The message may be a Command, it can also be a Event. When we realized based on message CQRS commands and event publishing, our system will be more flexible and scalable.

If your message based system, then I guess you can not do without the message bus, I was "purely a hand line and CQRS achieve" wrote a realization CommandBus memory-based, and interested friends can take a look in, CommandBus the codes are defined as follows:

Copy
public class CommandBus : ICommandBus
{
    private readonly ICommandHandlerFactory handlerFactory; public CommandBus(ICommandHandlerFactory handlerFactory) { this.handlerFactory = handlerFactory; } public void Send<T>(T command) where T : ICommand { var handler = handlerFactory.GetHandler<T>(); if (handler == null) { throw new Exception("未找到对应的处理程序"); } handler.Execute(command); } }

Memory-based message bus can only be used for the development environment, in a production environment can not meet the needs of our distributed deployment, this time on the need-based message queue ways to achieve. There are many message queue, such as Redis subscription publication, RabbitMQ, etc., realize the message bus, there are many excellent open source frameworks, such as Rebus, Masstransit, etc., you choose a familiar framework can be.

Data Auditing

Data auditing is CQRS brings us to another convenience. Since we store all the events, when we want to get the object change records, records only need to EventStore query out, you can see the whole life cycle. This operation is simply this clarity than even opened your adolescent diary.

Of course, if you want to know how the operation audit log objects do? By the same token, we record all of Command on it. All that query log it? Haha, not naughty. The more record something, the greater your store, if your storage space allows, of course, the more detailed the better, mainly to see the business needs.

If we recorded all Command, we can also carry out targeted analysis, which command a large amount, which commands execution time. . These data will provide data to support our expansion.

Packet deployment

In a distributed system, using a proportional Command and Query is not the same, between the Command and Command, right between the Query and Query heavy there are also differences, if simple average of the deployment of these services on each node, that purely messing around. A more reliable practice to different weights Command and Query group, and then targeted deployment.

to sum up

CQRS very simple, CQRS How good is the key. CQRS more like a thought that gives us a basic idea of ​​the separation system, combined with ES, Messaging and other models, provides a good theoretical basis for building distributed highly available and scalable system.

There are many garden delve CQRS + ES predecessors, this paper draws on their articles and ideas for their share!

Any inaccuracy in the article or the wrong place, please let us know! Welcome to the discussion!

Reference Documents

CQRS start talking, CQRS stands for Command Query Responsibility Segregation, translated into Chinese called the command query separation of duties. Literally can see, this model requires the developer accordance with the responsibilities of the method is a command or query separation, what is the command? What is a query? We continue to look down.

Query & Command

What is the command? What is a query?

  • Command (Command): no results are returned (void), but will change the state of the object.
  • Query (Query): returns the result, but does not change the state of the object, no side effects on the system.

State of the object What does it mean?

State of the subject, we can understand its properties into, for example, we define a Person class, defined as follows:

Copy
public class Person {
    public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } public void Say(string word) { Console.WriteLine($"{Name} Say: {word}"); } }

In the Person class:

  • Name, Age: attributes (state)
  • Say (string): Method (behavior)

Then back to the content discussed in this section, is not a good understanding of it? When I define a method to change the Name or Age Person instances when this method belongs Command; if a given method, only queries Person information about instances when this method belongs to Query. When we would Command and Query separation of duties in accordance with, you just use the CQRS mode.

In fact, this is all the CQRS.

A friend may say, and if that's all CQRS also too simple, right? Yes, Road to Jane!

Separate read and write

When we were separated according to CQRS, you are not already seen this stuff too suitable for a separate read and write? When our database is master-slave mode, when the main library is responsible for writing, from the library is responsible for reading, exact match Command and Query, just perfect. So we are going to say about the separate read and write.

Mainstream database now supports master-slave mode, the main benefit from the convenient mode is I do failover, when the primary database goes down, they can quickly be enabled from the library, thereby reducing the system unavailable time.

When we use the database when the master-slave mode, if the application is not separate read and write, you will find basically useless from the library, main library busy dying every day, both responsible for writing, but also responsible for querying, accessing met a large amount of CPU time surge is common. However, from the library too busy, in addition to the main library to receive change records do data synchronization, and then nothing else to do, no matter how much pressure the main library, the library has been like with the CPU electrocardiogram 0-1-0-1. .. when we separate read and write, is responsible for writing the main library, from the library is responsible for reading the code to how to change it? We only need to define two Repository on it:

Copy
public interface IWritablePersonRepository {
    //写入数据的方法 } public interface IReadonlyPersonRepository { //读取数据的方法 } 

Connecting the main use of the library in IWritablePersonRepository, IReadonlyPersonRepository connection from the library used. Then, using the Command inside IWritablePersonRepository, used in the Query IReadonlyPersonRepository inside, so that in the application layer of the separate read and write.

CRUD and EventSourcing

Speaking CQRS, inevitably comes to the operation of these two data models. Why say data manipulation model it? Because data manipulation seriously affect the performance, and our separation is an important aim is to improve performance.

CRUD

CRUD (Create, Read, Update, Delete) is a data-oriented, it will be divided into operations on the data to create, update, delete, and read the four categories, which may correspond to our four operating SQL statement insert, select, update , delete, very intuitive, its existence is the operating data.

Because there is a reasonable, we can not say one-sided CRUD is good or bad, here only briefly about its problems:

  • Concurrency conflicts: This is a big problem, when A and B while updating a row, your transaction inevitable error.
  • Loss of context data manipulation: the problem is not small, for developers, we usually know when and by whom the data is what has been done to update, but CURD only stores the final state, the context of data manipulation nothing know.

Well, the more problems no longer listed, one is "concurrency conflicts" This is a problem, do not apply in a highly concurrent environments. Since CRUD NA, when we build high-performance applications, we can only hope the ES.

Event Souring

Event Souring, translated called event traceability. What does that mean? It objects to create, modify, delete and other operations as a series of events ( note: there is the difference between an event and command, will be mentioned later ), when only the persistent store events, media store event called EventStore, when to get the latest status of an object, the object retrieved by EventStore all Event and reload to get the latest state of the object. EventStore can be a database, disk files, MongoDB, etc., due to the Event of memory are added, concurrency issues so there is no conflict.

Command and Event

In CQRS + ES scheme, we have to face these two concepts, commands and events.

  • Command: describes the user's intent.
  • Event: describes the state of the object changes.

We give an example, say you want to update your profile, such as the Age of 35 revised to 18, then the corresponding command is:

Copy
public class PersonUpdateCommand {
    public string Id { get; set; } public int Age{ get; set; } public PersonUpdateCommand(string id, int age){ this.Id = id; this.Age = age; } }

PersonUpdateCommand is a command, which describes the intent of users to update personal information. When the program receives this command, it is necessary to change the data, causing the state change data, generating Event:

Copy
public class PersonAgeChangeEvent {
    public string Id { get; private set; } public int Age{ get; private set; } public PersonAgeChangeEvent(string id, int age){ this.Id = id; this.Age = age; } } public class PersonUpdateCommandHandler { private PersonUpdateCommand Command; public PersonUpdateCommandHandler(PersonUpdateCommand command) { this.Command = command; } public void Handle() { var person = GetPersonById(Command.Id); if(person.Age != Command.Age) { //生成并发送事件 var @event = new PersonAgeChangeEvent(Command.Id, Command.Age); EventBus.Send(@event); } } }

Data consistency

Common data consistency model in two ways: strong consistency and eventual consistency.

  • Strong Consistency: all users at any time or to query process is the most recent successful update data.
  • Eventual consistency: consistency and relatively strong, at some point the user to query or process data may be different, but the ultimate success of the updated data will be queried to all users or processes.

When it comes to the issue of consistency, we have to say about the CAP theorem.

CAP theorem

In 1998, a computer scientist at the University of California, Eric Brewer proposed a distributed system has three indicators.

  • Consistency: consistency
  • Availability: Availability
  • Partition tolerance: Fault-tolerant partition

They are the first letter C, A, P, these three indicators simultaneously impossible. This conclusion is called CAP theorem.

For distributed systems, constrained CAP theorem, eventual consistency became the only choice. To achieve eventual consistency, consider the following questions:

  • After the distributed system, we can not guarantee that every operation can be successfully implemented, such as network outages, downtime and other temporary server error, will lead the operation fails, then we will wait for Recovery: retry strategy retry. Retry operation for the system may cause some side effects, such as when the network you are paying interrupted, this time you do not know whether the payment is successful, retry again after the network, might result in a duplicate charge. If you want the system to avoid the harm caused by the retry, it is necessary to design a power operation and other operations.
    • Idempotency: simply put, it is a result of the execution time and perform multiple operations are created the same, does not produce side effects.
  • Withdrawal strategy: to retry strategy corresponding to determine if a final operation fails, then we need to undo this operation will restore the system to the state before the execution of the operation. Undo There are two, one is the direct object is modified to state before the execution, this situation will result in data auditing inconsistencies; the other is red-operate on similar financial, add a command to wash away on operation, to ensure data integrity and to meet the requirements of the audit data.

Messaging

Through the above description, we already know that in a system that all changes are based on operations and events generated by the operation triggered. The message may be a Command, it can also be a Event. When we realized based on message CQRS commands and event publishing, our system will be more flexible and scalable.

If your message based system, then I guess you can not do without the message bus, I was "purely a hand line and CQRS achieve" wrote a realization CommandBus memory-based, and interested friends can take a look in, CommandBus the codes are defined as follows:

Copy
public class CommandBus : ICommandBus
{
    private readonly ICommandHandlerFactory handlerFactory; public CommandBus(ICommandHandlerFactory handlerFactory) { this.handlerFactory = handlerFactory; } public void Send<T>(T command) where T : ICommand { var handler = handlerFactory.GetHandler<T>(); if (handler == null) { throw new Exception("未找到对应的处理程序"); } handler.Execute(command); } }

Memory-based message bus can only be used for the development environment, in a production environment can not meet the needs of our distributed deployment, this time on the need-based message queue ways to achieve. There are many message queue, such as Redis subscription publication, RabbitMQ, etc., realize the message bus, there are many excellent open source frameworks, such as Rebus, Masstransit, etc., you choose a familiar framework can be.

Data Auditing

Data auditing is CQRS brings us to another convenience. Since we store all the events, when we want to get the object change records, records only need to EventStore query out, you can see the whole life cycle. This operation is simply this clarity than even opened your adolescent diary.

Of course, if you want to know how the operation audit log objects do? By the same token, we record all of Command on it. All that query log it? Haha, not naughty. The more record something, the greater your store, if your storage space allows, of course, the more detailed the better, mainly to see the business needs.

If we recorded all Command, we can also carry out targeted analysis, which command a large amount, which commands execution time. . These data will provide data to support our expansion.

Packet deployment

In a distributed system, using a proportional Command and Query is not the same, between the Command and Command, right between the Query and Query heavy there are also differences, if simple average of the deployment of these services on each node, that purely messing around. A more reliable practice to different weights Command and Query group, and then targeted deployment.

to sum up

CQRS very simple, CQRS How good is the key. CQRS more like a thought that gives us a basic idea of ​​the separation system, combined with ES, Messaging and other models, provides a good theoretical basis for building distributed highly available and scalable system.

There are many garden delve CQRS + ES predecessors, this paper draws on their articles and ideas for their share!

Any inaccuracy in the article or the wrong place, please let us know! Welcome to the discussion!

Reference Documents

Guess you like

Origin www.cnblogs.com/IT-Evan/p/CQRS.html