是否有适用于前提条件的高度分布式OLTP情况的已知体系结构解决方案?例如,让我们使用银行示例。 A人想要将$ N转移给B人。成功的前提条件是A人的账户中必须有超过$ N.
从人员A的角度来看,他们登录到一些Web应用程序。他们以N美元创建从他们自己到B人的转移。请记住,在背景中,当正在应用此转移并且正在创建转移时,资金将被实时提取并存入人员A的账户。资金可能在创建之前存在,但是一旦应用了转移,它可能不会。换句话说,这不是客户端验证。 A人想知道这种转移同步成功或失败。人员A不希望异步提交传输,然后稍后返回队列或传输失败的通知。
是否有一个已知的架构可以大规模解决这个问题?如果所有帐户都在一个RDBMS中,那么您可以通过内置事务功能执行此类操作。但是,如果您使用的是最终一致的NoSQL样式数据存储区,或者像Kafka这样基于日志/消息的基础架构,那么这个问题的已知解决方案是什么?
基本上你需要的是一个分布式锁定机制。许多分布式服务器应用程序提供了这样的功能。
基本上,如果我们将您的问题转换为代码,它将看起来像这样
// 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(分布式缓存)。我相信你会在关键字“分布式锁定”下找到更多解决方案
你看过Splice Machine了吗?它是一个完全符合ACID标准的RDBMS,它运行在hadoop堆栈(hbase,spark,hdfs,zookeeper)之上。它们具有双体系结构,使用hbase进行快速OLTP查询,并为OLAP查询提供内容,并且内置了不需要任何锁定的事务功能。
ClustrixDB是另一种可能值得一试的解决方案。它使用Paxos进行分布式事务解析(内置于分布式,ACID,SQL兼容的RDBMS),并具有内置的容错功能。