gpt4 book ai didi

c# - 锁定每个用户的创建/更新/删除请求

转载 作者:行者123 更新时间:2023-11-30 15:13:48 25 4
gpt4 key购买 nike

我有一个用 Asp.Net Core & Entity Framework & SQL Server 编写的支付系统。我必须处理许多安全情况,在这些情况下,我需要防止用户同时执行 2 个或更多操作。例如:

每次发生支付交易

  1. 检查用户余额,如果信用不足则阻止。
  2. 执行付款并减少用户余额。

现在,如果用户发出 2 个或更多请求来创建付款,一些请求将通过可用的信用验证。由于我有很多与此类似的场景,所以我想到了一个可以解决所有这些问题的通用解决方案。我想过添加一个中间件来检查每个请求和以下内容:

  1. 如果请求是 GET 请求,它将通过 - 这将启用并发 GET 请求。
  2. 如果请求是 POST/PUT/DELETE 请求,它将检查是否已经存在针对该特定用户的现有 POST/PUT/DELETE(假设用户已登录)。如果有,错误请求的响应将返回给客户端。

为了以正确的方式执行此操作并支持超过 1 个服务器,我知道我需要在数据库级别执行此操作。我知道我可以锁定 Oracle 中的特定行并考虑在每个 UPDATE/CREAT/DELETE 的开头锁定用户行并在最后释放它。使用 EF 执行此操作的最佳方法是什么?有更好的解决方案吗?

我使用的是 UnitOfWork 模式,每个请求都有自己的范围。

最佳答案

我反对使用行锁作为请求同步机制:

  • 尽管 Oracle 以不升级行锁而著称,但事务级和其他优化可能会决定升级,这会导致可伸缩性和死锁降低。

  • 如果两个用户想互相转账,他们很可能会陷入僵局。 (如果您现在没有这样的功能,将来可能会有,所以最好创建一个不会那么容易失效的架构)。

现在,仅仅因为来自同一用户的另一个请求碰巧花费了更长的时间而返回“错误请求”的系统当然是一个故障安全系统,但它的可靠性(无故障运行的指标)受到影响。我希望世界上的任何支付系统都具有故障安全性和可靠性。

Is there a better solution?

基于 CQRS 的架构和 shared-nothing方法:

  • ASP.NET 服务器(“网络层”):
    • 像现在一样直接执行读取 (GET) 操作
    • 将写入(POST/PUT/DELETE)操作提交到队列中,并立即返回 HTTP 200。
  • 应用层:(微)服务集群,以无共享方式获取和执行写入请求:
    • 在任何时刻,来自任何特定用户的请求最多由整个系统中的一个线程处理(跨所有进程和机器)
    • 无共享方法可确保您永远不必同时处理来自同一用户的请求。

实现无共享

无共享架构可以通过分区(AKA 分片)来实现。例如:

  • 你有 N 个处理线程在 M 台机器上运行(在一些进程中)
  • 每台机器都被分配了一个独特的角色来运行这 N 个线程中特定范围的线程
  • 来自用户的每个请求总是通过计算分派(dispatch)到相同的特定线程:thread_index = HASH(User) % N,或者如果用户 ID 是整数:thread_index = USER_ID % N.
  • 如何将已分派(dispatch)的请求传递给处理线程取决于所选择的队列。例如,Web 层可以向 N 个不同的主题提交请求,或者直接将请求推送到分布式参与者(参见 Akka.Net),或者您可以只使用数据库表作为队列,并让每个线程获取请求属于它。

此外,您还需要一个编排器来确保每台 M 台机器都已启动并正在运行。如果一台机器出现故障,编排器会启动另一台具有相同角色的机器。例如,如果您对服务进行 docker 化,则可以使用 KubernetesStatefulSet .

关于c# - 锁定每个用户的创建/更新/删除请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57239189/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com