简体   繁体   中英

Orleans. Akka.net. Problem with understanding the actor model

If you don't know C# but you are familiar with the actor model please read my problem below as it is more about architecture and data management.

I'm a very junior C# developer and trying to understand what the actor model is. I'm kind of done with it but it's left one point that I cannot get.

Before I tell you a problem let me describe the context in order to provide you with better undersrtanding.

As a test example I want to build an app for an imaginary bank. I'm going to implement this application by using both akka.net and Orleans on learning purpose and to be able to compare them.

Use cases:

  • As a user I want to be able to create a new account;
  • As a user I want to be able to login to the app using my account unique number;
  • As a user I want to be able to deposit money to my account;
  • As a user I want to be able to select another user and transfer a specified sum of money to their account;
  • As a user I want to be able to withdraw a sum of money from my account.

So, there are the following entities:

  • User;
  • Account.

Identifying one to one relationship between the user and their account. I'm going to use ORM to store this data in my Database. Obviously the models look something like this:

public class User
{
    public Guid Id { get; set; }
    public string FullName { get; set; }
    ....
}

public class Account
{
    public Guid Id { get; set; }
    public string UniqueNumber { get; set; }
    public string Balance { get; set; }
    ...
}

And I also want to have two actors/grains:

  1. AccountActor;
  2. TransactionService;

Their interfaces:

//Or IAccountGrain
public interface IAccountActor
{
    void Deposit(Money amount);
    void Withdraw(Money amount);
}

//Or ITransactionGrain
public interface ITransactionActor
{
    void Transfer(IAccountActor from, IAccountActor to, Money amount);
}

The thing that I don't understand is how to treat the data in the relation database. Let's imagine the following scenario:

50 users are online and vigorously making request via the client app to the REST API of the app. They are withdrawing, depositing and transferring money almost without any pauses.

The question is:

  1. Should I create one actor per user account? I'm pretty sure that I need because how then I can implement thousands of transactions between different accounts.
  2. How can I associate the user account with the AccountActor? Is it correct If I load the data from database using repository before actor's activation/start and set up the state?

And the main problem: How to save state back to the database?

Let's image an account A that has 1000$. And It occurs about 100 transactions initiated by the users where this account is involved. Account A changes its state from message to message.

What is the best approach to save these changes to database? I read that If I use calls to the database directly from the actor, I will lose all the benefits because of blocked operations.

Should I create one more actor to process messages from other actors and writes changes to database using repositories?

I mean I can send from AccountActor messages about the account changes to the new actor where I will call the appropriate repository. But, Isn't it a bottleneck? Let's imagine 1000 users online and about 100 000 transactions between accounts. Then the actor that is responsible for saving accounts changes to the database can have too many messages to process.

Sorry for the long text. I tried to find examples of applications that use Orleans or Akka.net but I haven't found anything what utilizes a database.

Thank you for you attention.

There are a couple ideas you're missing here, but let's take the questions in order.

Should I create one actor per user account? I'm pretty sure that I need because how then I can implement thousands of transactions between different accounts.

I assume the alternative you're considering is multiple actors per user account, and this would be wrong. There can be only one actor per user account or else you will run into the problem you describe that simultaneous requests can withdraw the same money twice.

How can I associate the user account with the AccountActor?

You are missing a UserActor which owns the AccountActors. An account cannot exist without an owner, otherwise we don't know who owns the money in an account. In the real world, one typically does not send money to a random account. They want to send it to a person, and uses the senders User persona account to do so.

Is it correct If I load the data from database using repository before actor's activation/start and set up the state?

Yes, in fact that is mandatory. Without the state in the actor, the actor is not good for much.

What is the best approach to save these changes to database? I read that If I use calls to the database directly from the actor, I will lose all the benefits because of blocked operations. Should I create one more actor to process messages from other actors and writes changes to database using repositories?

You're on the right track but not quite there yet. Saves of actor state are done with asynchronous methods to write to the DB. With an async method, the main thread does not block waiting for the DB write to happen, thus the processing thread can continue with its business.

When only one actor is involved in an action, it can save its own state via the async method. In banking registers there are always 2 accounts involved and writes to both must succeed or fail, never one succeed and one fail. Therefore, the TransactionActor will open a DB transaction and tell each AccountActor to save its state using that DB transaction. If either fails, it aborts the transaction and both fail. Note that this method is a private async method on the TransactionActor so you get the benefits of parallel processing.

BTW, you can't find any examples of writing to the DB in Orleans because that is all handled for you by the framework. The save methods are automatically async and they interact with the DB. All you do in Orleans is reference the Actor and the state is automatically pulled from the DB for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM