[erlang-questions] Modelling question - concurrency and scalability
Rudolph van Graan
rvg@REDACTED
Fri Aug 10 11:31:29 CEST 2007
Hi Guys,
Suppose you write an accounting system (like in an ordinary set of T
accounts). Now you have a lot of transactions running concurrently,
each one debiting one account and crediting another.
An account may look like this: {account, ID, Debits, Credits}
When we start the set of accounts look like this: (The debits and
credits add up to 0)
{account, 1, 0, 0}
{account, 2, 0, 0}
{account, 3, 0, 0}
We define a transaction so: {transaction, ID, Amount, DebitAccount,
CreditAccount}
So we run these transactions against the accounts:
{transaction, 1, 10 , 1, 2}
{transaction, 2, 20 , 2, 3}
{transaction, 3, 40 , 3, 1}
{transaction, 4, 20 , 2, 1}
The accounts should look like this at the end:
{account, 1, 10, 60} (Balance = Credit 50)
{account, 2, 40, 10} (Balance = Debit 30)
{account, 3, 40, 20} (Balance = Debit 20)
The Debits == Credits == 90 --> This means the system is in balance
as it should be.
Each transaction does the following:
1. Check if an account has sufficient credits to continue
2. Credit this account, Debit the other
The problem here is that you need to modify two accounts for each
transaction, but before you do that you need to know atomically what
it's current balance is. In essence, if you have a small number of
accounts and a large number of transactions you will have a large
contention ratio on a single account. If you use mnesia (or any
database for that matter), your system will only scale to the maximum
rate at which the DBMS process transactions atomically. And then it
seems as though you cannot scale anymore. Concurrency will not solve
this problem. If you use SQL you have exactly the same problem:
- start transaction
- select the current balance of the account
- if sufficient
-- debit account 1
-- credit account 2
- commit transaction
The key property here seems to be the fact that you always ADD to the
values, never SUBTRACT. If you never had to know in a transaction
what the "current" balance is, you can fix the problem. But IMO not
when you need to check values atomically.
Does anyone have suggestions on how one can solve the scalability
problem here taking into account that you must know the current
balance of the account before modifying it? A scheme where you split
each account into smaller ones won't work, as you will have to sum
all the smaller accounts to get the balance of the larger one. The
more accounts you have and the more even the transactions are spread
over the different accounts the easier it is to scale. But what do
you do if this is not true?
Rudolph
More information about the erlang-questions
mailing list