【问题标题】:Best practice to save very busy counter in db在数据库中保存非常繁忙的计数器的最佳实践
【发布时间】:2019-05-02 06:35:03
【问题描述】:

我正在开发一个非常繁忙的 Web 服务,它应该每秒收到数千个请求。我希望每个请求都会更新一个计数器字段。我该怎么做?将计数器保存在 db 中非常重要,因此在服务器死机的情况下我不会丢失信息。我已经尝试过以下代码,但这对于每秒数千个请求来说将是一个巨大的瓶颈。 你会怎么做?

public void Upload(int organizationId)
{
  try
  {
    lock (UpadateLock)
    {
       using (var db = new DbContext())
       {
         Counter counter = db.Counters.Where(c => c.OrganizationId == organizationId).FirstOrDefault();
         counter.count++;
         db.SaveChanges();

       }
     }
   }
   catch (Exception ex)
   {

   }
}

【问题讨论】:

  • 如果您的服务实例很少,您的解决方案将不起作用:您将失去计数器。最直接的方法是在每个请求上调用UPDATE.. sql。但是对于thousands of requests per second,这不是一个好主意。为什么这个计数器如此重要?将其保存在内存中并在后台线程中每 5 秒将快照放入数据库会更容易。
  • @mtkachenko 我已经考虑过你的想法,但如果服务器死机,我可能会丢失一些信息。
  • @Dolev 您可以将请求排队还是需要实时?
  • @AmanB 我可以创建一个单独的线程,在队列中等待更新数据库,以及缓存中的一个单独的计数器,该计数器也将被更新。你是故意的吗?

标签: c# sql-server performance entity-framework web-services


【解决方案1】:

如果您在服务器死机时绝对不会丢失数据,那么您必须为每个增量写入持久存储。

问题只是使用什么商店。

您当然可以使用 SQL 来完成。像这样的简单查询并不太昂贵。您可以对此进行基准测试以查看开销是否可以接受。测量 Web 服务器和 SQL 服务器上的 CPU 使用率。还可以测量磁盘使用情况和事务日志大小。

Redis 可能会成为一个非常好的数据库。众所周知,它速度很快,并且支持服务器端增量。

您还可以通过将增量写入多个服务器(随机选择一个)来扩展此工作负载。

您也可以使用任何其他数据存储。如果它本身不支持递增,您可以改为插入新行。然后,有一个后台进程定期聚合这些行,这样它们就不会继续累积。

【讨论】:

    猜你喜欢
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 2017-01-26
    • 2011-11-23
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    相关资源
    最近更新 更多