如何在不影响响应时间的情况下跟踪数据库中的用户?

agyaoht7  于 2022-09-21  发布在  Redis
关注(0)|答案(1)|浏览(140)

我正在为用户设计一个大的(为我的)后端API,我想尝试一下用户最后一次出现的时间,以及他们与哪些IP一起出现(所有人)。

我通常的方法是使用一个简单的中间件--中间件检查它们是否经过身份验证。如果是,它只用当前时间更新数据库条目。然后,中间件继续执行所请求的功能。

然而,我正在处理更多的数据,我希望尽可能顺利地完成这项工作--我希望中间件在没有阻塞数据库操作的情况下尽快完成。我有一些想法:

1.我使用FastAPI的后台任务来完成。我不知道它们会带来多少开销,而且考虑到它们将在每条路线上运行,仅仅为了更新数据库中的时间戳而创建后台任务似乎效率很低。如果我想要扩展,我必须使用celery或其他东西,这可能会甚至更慢
1.瑞迪斯。这似乎是最有可能的;我可以简单地存储时间戳和以它们的地址为关键的IP。每隔一段时间(15-60秒),我可以让API查看所有条目并相应地更新数据库。这应该会使请求尽可能快,没有开销,非常可伸缩,真正的磁盘数据库将在大致“实时”的时间段内更新。我喜欢这个解决方案,但我担心它可能会被归类为过早优化。

需要说明的是,我正在寻找的需求是

  • 可扩展。当10,000个用户同时点击我的API时,这必须起作用,否则我必须放弃该功能。
  • 响应性-设计可能会使用某种中间件,这必须立即退出。我不能让一个正在工作的人等待数据库事务来完成。响应时间必须不受此功能的影响。
  • 相对实时-数据库必须在60秒内使这些IP和用户ID可用。我可以灵活地接受这个要求,但我不希望在查询之前等待太久。
ojsjcaue

ojsjcaue1#

我的答案可能不是最终答案,但以下是我的两点看法:

前提

  • 10K用户是相当多的,但这主要取决于您如何处理这10K请求。你的应用程序,无论有没有这个功能,都可能无法处理这样的流量。因此,它应该是水平可扩展的
  • 您需要接受功能和可伸缩性之间的某种权衡。水平可伸缩性的好处在于,如果您需要更多资源,只需水平添加一个服务器/服务即可。
  • 如果你正在做一些繁重的工作,这是很难做到接近实时的。我不确定这款应用能做什么,但有很多因素会导致等待时间,其中一些(如果不是大多数)是你无法控制的。

实际答案

话虽如此,我想中间件是最好的选择。您可以获取数据(IP、用户ID等)并执行对数据库的async调用以更新数据。在不等待数据库响应的情况下,让请求被处理,并且只有当请求完成时,您才能await进行响应。这将相对影响时间,但如上所述,必须进行一些权衡。即使使用外部系统,您也必须获取用户信息和IP(还有其他信息?)然后执行一个呼叫并等待它。

示例创意

你可以做一些类似的事情

from fastapi import FastAPI, Request, Depends

# other imports

app = FastAPI()

@app.middleware("http")
async def record_user_activity(request: Request, user = Depends(get_user), call_next):
    # get user IP and other data
    # do here the call for inserting the data into the db
    # DO NOT AWAIT IT
    response = await call_next(request)
    # NOW AWAIT THE CALL TO THE DB TO MAKE SURE IT HAS FINISHED CORRECTLY
    return response

相关问题