Высокораспределенная архитектура OLTP

Существует ли известное архитектурное решение для ситуаций с высокой степенью распределенности OLTP, где применяются предварительные условия? Например, давайте использовать банковский пример. Лицо A хочет перевести N долларов лицу B. Предварительным условием для успеха этого является то, что лицо A должно иметь на своем счету более N долларов.

С точки зрения лица А, они входят в какое-то веб-приложение. Они создают перевод от себя лицу B на сумму N долларов. Имейте в виду, что в фоновом режиме деньги снимаются и вносятся со счета лица А в режиме реального времени по мере применения и создания перевода. Деньги могут существовать до создания, но после применения перевода их может и не быть. Другими словами, это не может быть проверка на стороне клиента. Человек А хотел бы знать, что эта передача прошла успешно или не удалось синхронно. Человек А не хотел бы отправлять перевод асинхронно, а затем возвращаться позже в очередь или к какому-либо уведомлению о том, что перевод не удался.

Существует ли известная архитектура, решающая эту проблему в больших масштабах? Если все учетные записи находятся в одной СУБД, вы можете сделать что-то подобное с помощью встроенных транзакционных возможностей. Но если вы используете в конечном счете согласованное хранилище данных в стиле NoSQL или инфраструктуру на основе журналов/сообщений, такую ​​​​как Kafka, есть ли известное решение подобных проблем?


person Logicalmind    schedule 05.06.2016    source источник
comment
Я не уверен, нужен ли вам подход или инструмент, но вы можете взглянуть на это: blog.cask.co/2014/11/   -  person guillaume31    schedule 07.06.2016


Ответы (3)


В основном вам нужен механизм распределенной блокировки. Многие распределенные серверные приложения предоставляют такую ​​возможность.

В основном, если мы преобразуем ваш вопрос в код, он будет выглядеть так

// BANK WITHDRAWAL APPLICATION

// Fetch BankAccount object from NCache
BankAccount account = cache.Get("Key") as BankAccount; // balance = 30,000
Money withdrawAmount = 15000;

if (account != null && account.IsActive)
{
    // Withdraw money and reduce the balance
    account.Balance -= withdrawAmount;

    // Update cache with new balance = 15,000
    cache.Insert("Key", account);
}

=========================

// BANK DEPOSIT APPLICATION

// Fetch BankAccount object from NCache
BankAccount account = cache.Get("Key") as BankAccount; // balance = 30,000
Money depositAmount = 5000;

if (account != null && account.IsActive)
{
    // Deposit money and increment the balance
    account.Balance += depositAmount;

    // Update cache with new balance = 35,000
    cache.Insert("Key", account); 
}

Это в основном пример состояния гонки

Состояние гонки — это когда два или более пользователей пытаются одновременно получить доступ к одним и тем же общим данным и изменить их, но в конечном итоге делают это в неправильном порядке.

Ответом на приведенный выше код в распределенной блокировке будет

LockHandle lockHandle = new LockHandle();

// Specify time span of 10 sec for which the item remains locked
// NCache will auto release the lock after 10 seconds.
TimeSpan lockSpan = new TimeSpan(0, 0, 10); 

try
{
    // If item fetch is successful, lockHandle object will be populated
    // The lockHandle object will be used to unlock the cache item
    // acquireLock should be true if you want to acquire to the lock.
    // If item does not exists, account will be null
    BankAccount account = cache.Get(key, lockSpan, 
    ref lockHandle, acquireLock) as BankAccount;
    // Lock acquired otherwise it will throw LockingException exception

    if(account != null && account.IsActive)
    {
        // Withdraw money or Deposit
        account.Balance += withdrawAmount;
        // account.Balance -= depositAmount;

        // Insert the data in the cache and release the lock simultaneously 
        // LockHandle initially used to lock the item must be provided
        // releaseLock should be true to release the lock, otherwise false
        cache.Insert("Key", account, lockHandle, releaseLock); 
    }
    else
    {
        // Either does not exist or unable to cast
        // Explicitly release the lock in case of errors
        cache.Unlock("Key", lockHandle);
    } 
}
catch(LockingException lockException)
{
    // Lock couldn't be acquired
    // Wait and try again
}

Этот ответ очень специфичен для NCache (распределенный кэш). Я уверен, что вы найдете больше решений по ключевому слову «Распределенная блокировка».

Источник

person Basit Anwer    schedule 08.06.2016
comment
Я думаю, что вопрос, который он задал, заключался в том, чтобы узнать, что требуется с точки зрения архитектуры и инфраструктуры. - person I.Tyger; 13.09.2018

Вы смотрели на Splice Machine? Это СУБД, полностью совместимая с ACID, работающая поверх стека хаупов (hbase, spark, hdfs, zookeeper). У них двойная архитектура, которая использует hbase для быстрых запросов OLTP и spark для запросов OLAP, а также встроенные возможности транзакций, не требующие блокировки.

person tdong    schedule 20.12.2016

ClustrixDB — еще одно решение, которое, возможно, стоит проверить. Он использует Paxos для разрешения распределенных транзакций (встроен в распределенную СУБД, совместимую с ACID, SQL), а также имеет встроенную отказоустойчивость.

person lucygucy    schedule 19.03.2019