0

我希望我的问题适合这个网站并且不是太宽泛,但是我在设计以下架构时遇到了麻烦:

我有两个网站。站点 1 负责在用户之间转移信用。站点 2 负责为这些用户提供服务/产品,这些服务/产品可以使用他们在站点 1 中拥有的积分来支付。

假设我在站点 1 上有 1000 个积分。我有一个在站点 2 上花费 50 个积分的服务/产品,并且用户想用他在站点 1 中拥有的积分购买它。

两个站点都与 REST 通信。因此,例如,当用户想要购买服务/产品时,站点 2 准备其请求并将其发送到站点 1,站点 1 进行交易并向站点 2 确认交易成功(例如,用户对服务/产品有足够的积分并且这些学分已成功转移到目的地)

现在这是棘手的部分。在站点 1 中,我有以下逻辑:

Begin transaction
update user set credits -= 50 where id = 1
update user set credits += 50 where id = 2
REST CALL (Site 2) Success
Site 2 response - OK, commit transaction
Commit

由于 REST 是对不同站点的调用,因此事务可能需要一些时间才能完成。同时,是否为任何事务锁定了整个表,或者用户 1 和用户 2 的行是否被锁定?这是实现我的逻辑的正确方法吗?我错过了什么吗?

先感谢您。

4

2 回答 2

1

由于您使用的是主键而不是范围,因此它应该是行级锁定。还有共享锁与排他锁的概念。共享锁允许其他进程在更新/删除场景中使用独占锁时仍然读取数据,并阻止所有其他进程读取它。

一般的逻辑..如果真的只有一个地方存储学分和一个读取它们的地方,那么实时同步有多重要?3、5 或 10 秒后是否足够?如果站点 1 完全关闭,您是否要让站点 2 仍然工作?

就个人而言,我会稍微重组一下:

  • 用户在站点 1 上创建一个帐户。
  • 第一次在站点 2 上完成交易时,它会验证帐户是否存在于 S1 上并获取信用数量......并保留它。
  • 每当在站点 2 上完成交易时,您首先检查本地信用计数(缓存),如果有足够的信用,您将返回202 Accepted响应代码。它基本上意味着“嘿,我们接受了这个,但还没有完成。”
  • 您可以立即允许用户在此时继续。
  • 在您进行本地信用检查的同时,您向 S1 发出了另一个实际交易请求。
  • 希望该服务可以为您提供成功/失败消息以及更新的最终/官方信用计数。
  • 使用它,您将本地事务状态更新为 204 NO Content (success) 并为下一次更新缓存。

由于 S1 始终返回确定的当前信用计数,因此您不必担心以 100% 准确的方式维护 S2 上的信用计数。您可以从 S1 等待它。

如果你真的很紧张,你可以有一个工作每 N 小时运行一次,轮询 S1 请求在这 N 小时内更新的每个帐户的更新。

于 2013-01-19T23:21:02.587 回答
1

这是对您对凯西回答的问题的回应:

是的,只要你这样做:

  • 站点 2:

    1. 客户登录。
    2. 向站点 1 询问此用户(用户 1)的信用总额和交易历史记录(GET 请求)。
    3. (任何收到“交易成功”响应的等待交易都可以下载/发送)
    4. 使用信用总额为可以负担的东西启用“购买”按钮。
    5. 客户点击购买按钮
    6. 生成站点 2 唯一的事务 ID,将其与谁购买了什么、何时购买的详细信息一起存储在数据库中,状态 = 未决。告诉用户交易已经收到,他们应该尽快通知它是否成功(HTTP 202 响应)
    7. 将购买请求发布到站点 1,包括身份验证(不希望伪造请求导致人们花费他们不想花费的钱)和交易 ID。
  • 站点 1

    1. 验证身份验证
    2. 验证站点 2 之前没有使用过站点 2 的 transactionID。如果有,则返回错误,如果没有:
    3. 开始交易
    4. 更新用户设置积分 -= 50 其中 id = 1
    5. 更新用户设置积分 += 50 其中 id = 2
    6. 插入事务 remoteSiteID = 'Site2', remoteTransactionID = tID, user = 1
      如果 site2 是唯一使用来自 site1 的积分的站点,则不需要 remoteSiteID 字段
    7. 犯罪
    8. REST CALL(站点 2)成功
  • 站点 2:

任一:
1. 接收 REST 成功调用,使购买可用于下载/发送,向用户显示一些消息说购买处理完成。更新本地交易记录,state=succeeded。


2. 站点 2 已关闭。下次后台轮询过程运行(检查等待响应的购买请求的状态)或下次客户登录时(在这种情况下也启动轮询——第一个列表中的步骤 3),将记录交易成功

如果您没有收到对事务的响应,请使用事务 ID 执行 GET。如果响应是错误的,Site 1 没有收到原始请求,Site 2 可以自由地重复事务(POST)请求。如果响应是“交易失败”,那么用户没有足够的积分,相应地更新站点 2 上的交易记录。如果结果是“交易成功”,也要记录。

如果交易失败 N 次,或者自用户单击按钮后经过了一段时间(例如 5 分钟),则站点 2 将停止重试购买。

于 2013-01-22T09:02:05.823 回答