Actor based distributed transactions


One question that often shows up when talking about the Actor Model, is how to deal with distributed transactions.

In .NET there is the concept of MSDTC, Microsoft Distributed Transaction Coordinator, that can be used to solve this problem when working with things like SQL Server etc.

The MS Research project Orleans (MS Azure Actor framework) also supports distributed transactions.
See 3.8 http://research.microsoft.com/pubs/153347/socc125-print.pdf on this.
[Edit] The transactions described in that paper was revoked, the Orleans team are currently working on a new implementation.

The problem with distributed transactions is that they are expensive, very expensive, they do not scale very well.

We as programmers are also trained to think of transactions as some sort of binary instant event that occurs, it either succeeds or it fails, and the time span is very short, but during this timespan, you freeze and lock everything that is involved with it.

In the real world however, transactions are more fuzzy, they don’t necessarily succeed or fail in a binary fashion, and they are far from instant.

And just to avoid confusion here, lets think of this as technical transactions vs. business transactions. In the end, they both ensures a degree of consistency, even though the concepts are different.

In the actor world, we can approach this the same way that the Saga pattern works.
See @Kellabytes excellent post on this topic: http://kellabyte.com/2012/05/30/clarifying-the-saga-pattern/

In Kellys post, she talks about failures in a technical context, but the failure could very well be a failure to comply to an agreement also. there would be no distinction between technical and business failures.

Let’s say that you purchase something on credit in a store, you make up a payment plan that stretches over X months.
During this time, you agree to pay Y amount of money at the end of each month for example.
If you do so, everything is fine, if you don’t, the store will send you a reminder, and if you still don’t pay, you will get fined.
This is a transaction that stretches over a very long time, and it can partially succeed.

Happy path:

happypath

Partial failure with compensating action:

overdue
Complete failure with compensating action:

failure

This is how you could model business transactions in a distributed system, it is asynchronous and it scales extremely well.

When two or more parties begin a transaction, all parties have to agree to some sort of contract before the transaction starts, this is your message flow, much like a protocol, that defines what happens if you violate the contract.A scheme of messages and actions that describe exactly how your (business) transaction is supposed to be resolved, and which of the involved parties that needs to ensure that a specific part of this agreement is handled.

This will make your transactional flow very business oriented, it goes very well with the concept of domain driven design. The transactional flow is actually just a process of domain events.

Akka.NET – Concurrency control


Time to break the silence!

A lot of things have happened since I last wrote.
I’ve got a new job at nethouse.se as developer and mentor.

Akka.NET have been doing some crazy progress the last few months.
When I last wrote, we were only two developers, now, we are about 10 core developers.
The project also have a new fresh site here: akkadotnet.github.com.
We are at version 0.7 right now, but pushing hard for a 1.0 release as soon as possible.

But not, let’s get back on topic.

In this mini tutorial, I will show how to deal with concurrency using Akka.NET.

Let’s say we need to model a bank account.
That is a classic concurrency problem.
If we would use OOP, we might start with something like this:

public class BankAccount
{
    private decimal _balance;
    public void Withdraw(decimal amount)
    {
        if (_balance < amount)
            throw new ArgumentException(
              "amount may not be larger than account balance");

        _balance -= amount;

        //... more code
    }
    //... more code
}

That seems fair, right?
This will work fine in a single threaded environment where only one thread is accessing the above code.
But what happens when two or more competing threads are calling the same code?

    public void Withdraw(decimal amount)
    {
        if (_balance < amount) //<-

That if-statement might be running in parallel on two or more theads, and at that very point in time, the balance is still unchanged. so all threads gets past the guard that is supposed to prevent a negative balance.

So in order to deal with this we need to introduce locks.
Maybe something like this:

    private readonly object _lock = new object();
    private decimal _balance;
    public void Withdraw(decimal amount)
    {
        lock(_lock) //<-
        {
           if (_balance < amount)
              throw new ArgumentException(
               "amount may not be larger than account balance");

           _balance -= amount;

        }
    }

This prevents multiple threads from accessing and modifying the state inside the Withdraw method at the same time.
So all is fine and dandy, right?

Not so much.. locks are bad for scaling, threads will end up waiting for resources to be freed up.
And in bad cases, your software might spend more time waiting for resources than it does actually running business code.
It will also make your code harder to read and reason about, do you really want threading primitives in your business code?

Here is where the Actor Model and Akka.NET comes into the picture.
The Actor Model makes actors behave “as if” they are single threaded.
Actors have a concurrency constraint that prevents it from processing more than one message at any given time.
This still applies if there are multiple producers passing messages to the actor.

So let’s model the same problem using an Akka.NET actor:


//immutable message for withdraw:
public class Withdraw
{
     public readonly decimal Amount;
     public Withdraw(decimal amount)
     {
         Amount = amount;
     }
}

//the account actor
public class BankAccount : TypedActor, IHandle<Withdraw>
{
     private decimal _balance;

     public void Handle(Withdraw withdraw)
     {
         if (_balance < amount)
         {
              Sender.Tell("fail"));
              //you should use real message types here
              return;
         }

          _balance -= withdraw.Amount;
          Sender.Tell("success);
          //and here too
     }
}

So what do we have here?
We have a message class that represents the Withdraw message, the actor model relies on async message passing.
The BankAccount actor, is then told to handle any message of the type Withdraw by subtracting the amount from the balance.

If the amount is too large, the actor will reply to it’s sender telling it that the operation failed due to a too large amount trying to be withdrawn.

In the example code, I use strings as the response on the status of the operation, you probably want to use some real message types for this purpose. but to keep the example small, strings will do fine.

How do we use this code then?


ActorSystem system = ActorSystem.Create("mysystem");
...
var account = system.ActorOf<BankAccount>();

var result = await account.Ask(new Withdraw(100));
//result is now "success" or "fail"

Thats about it, we now have a completely lock free implementation of an bank account.

Feel free to ask any question :-)

Introducing Akka.NET


akkanet

There are a lot of things going on right now.
First, Pigeon Framework now has a new name; Akka.NET.
We got OK from Typesafe to use the name since we are a pure port of real Akka.

We are also doing a lot of work on the core and remote libs.
We now have a real EndpointManager actor managing transports.
And we have and Endpoint actor for each active endpoint.
Thus, we now support multiple transports, even if only Tcp is provided out of the box right now.

There have been some progress on Routers too.
We now support “Group” routers, e.g. RoundRobinGroup and ConsistentHashingGroup.
“Pool” router support is currently being developed.

Another nice feature we have ported is remote deployment.
This is IMO maybe the coolest feature we have ported so far, this means that we can now via configuration decide if an actor should be deployed locally or remote.
If remote deployment is used, the local actor system will send a message to the remote system, telling it to create the given actor with all of its configuration on the remote node.

For more info see: https://github.com/rogeralsing/Pigeon