1

是否有适用于先决条件的高度分布式 OLTP 情况的已知架构解决方案?例如,让我们以银行为例。A 想将 $N 转给 B。此操作成功的先决条件是 A 的账户中必须有超过 $N。

从人 A 的角度来看,他们登录到某个 Web 应用程序。他们以 $N 的价格创建了从自己到个人 B 的转账。请记住,在应用此转账和创建转账时,资金会在后台实时从个人 A 的账户中提取和存入。这笔钱可能在创建之前就存在,但一旦应用转移,它可能就不存在了。换句话说,这不可能是客户端验证。A 想知道这个传输是同步成功还是同步失败。A 不希望异步提交传输,然后稍后返回到队列或传输失败的某些通知。

是否有一种已知的架构可以大规模解决这个问题?如果所有帐户都在一个 RDBMS 中,那么您可以通过内置的事务功能执行类似的操作。但是,如果您使用的是最终一致的 NoSQL 风格的数据存储,或者像 Kafka 这样的基于日志/消息的基础架构,那么是否有解决此类问题的已知解决方案?

4

3 回答 3

0

你看过拼接机吗?它是一个完全符合 ACID 的 RDBMS,运行在 hadoop 堆栈(hbase、spark、hdfs、zookeeper)之上。他们有一个双架构,使用 hbase 进行快速 OLTP 查询,使用 spark 进行 OLAP 查询,并且它内置了不需要任何锁定的事务功能。

于 2016-12-20T18:52:24.440 回答
0

ClustrixDB 是另一个值得一试的解决方案。它使用 Paxos 进行分布式事务解析(内置到分布式、ACID、SQL 兼容的 RDBMS 中),并且还具有内置的容错能力。

于 2019-03-19T22:26:06.650 回答
0

基本上你需要的是一个分布式锁定机制。许多分布式服务器应用程序都提供了这样的功能。

基本上,如果我们将您的问题转换为代码,它将如下所示

// 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(分布式缓存)。我相信您会在关键字“分布式锁定”下找到更多解决方案

资源

于 2016-06-08T07:47:52.383 回答