【问题标题】:Looking for Real Time Solution : Efficient DB interaction寻找实时解决方案:高效的数据库交互
【发布时间】:2011-09-24 07:24:01
【问题描述】:

在容器上部署了一个名为 sbs 的 java 应用程序。在它的顶部部署了 3 个其他 java 应用程序,比如说 A、B 和 C。

现在应用程序 A、B 和 C 命中一个方法名称为应用程序 sbs 的 Sing(id),用于播放消息。

应用sbs的sing(id)方法,每秒点击200次左右,为所有人播放一条消息。

我的问题:

数据库表:

播放 ID:播放 ID

Count : 请求此播放 id 的总数

Last Date Time : 上次播放的日期和时间

播放 ID:1

计数:总共 66 个

最后日期时间:10/8/2011 231145(某事)

现在更新表格

播放 ID:1

计数:总共 92 个

最后日期时间:10/8/2011 231344(某事)

我必须更新这个表,正如我之前提到的,这个字段每秒改变 200 次。目的是知道这个播放 id 已经播放了多少次。

我该怎么做?

每秒访问数据库 200 次是不可能的。所以我可以每 4-5 秒(定期)访问数据库并更新播放 ID 的计数状态。我如何明智地执行该应用程序。需要每秒将计数增加 200 次,并将值存储在某处并更新数据库......像这样......什么是最有效的方法......

如果您有任何困惑,请告诉我

寻找您的宝贵意见。提前致谢。

【问题讨论】:

  • 消息是否在两者之间更新 - 即所有请求都需要从数据库中获取它还是可以以某种方式缓存?
  • 即使我也不知道..因为这是媒体服务器的逻辑......场景是......我的应用程序......我的服务器......另一个是媒体服务器。 .我受限于我的服务器...
  • 我想你可以澄清一下。否则我会建议考虑安德烈的解决方案。

标签: java database


【解决方案1】:

正如你所说,这个问题有些可疑:

  • 如果可以接受每 4 或 5 秒只更新一次表,那么您将不可避免地“丢失”更新,如果您查询,countlast_date_time 的值将过期它。

  • 更糟糕的是(也许)如果您的系统在上次更新后 4.9 秒崩溃,那么您的系统将完全丢失几个计数滴答。

如果这些异常情况很重要,那么您别无选择,只能同步在每个 sing(...) 请求上保持 countlast_date_time 的值。

但如果它们无关紧要,为什么还要将这些信息保存在数据库中呢?为什么不把它全部保存在内存中并接受当服务器崩溃和重新启动时计数会重置?或者,如果您出于记账目的需要保留计数,为什么不将“play(id)”事件写入一个特殊的日志文件并通过离线扫描日志来生成帐户。


顺便说一句,每秒 200 次更新并不是不合理的,尤其是在表很小并且您进行一些调整的情况下。


我可以承受 4-5 秒的记录更新延迟。 .... 如果服务器崩溃,那么应用程序部署在哪里,我们可以放置一些逻辑......类似......如果特定播放 ID 的计数值为零......从数据库中获取最后一个计数,然后增加它到一个。

这种方法存在一个重大缺陷。在最后一次更新和应用程序崩溃之间的时间间隔内,对于任何给定的歌曲,可能有零个“播放”、一个“播放”或多个“播放”。当应用程序返回时,它根本不知道那些“播放”是什么......而且它无法知道它们,除非它们被记录在某个地方。

我们将这些信息保存在数据库中,因为通过这些记录,我们需要获取记录,例如为这个时间戳播放了多少播放 id(一些东西)。

大问题......你还没有回答......如果你偶尔不计算一些“游戏”是否重要

  • 如果没关系,那么缓存并每隔几秒进行一次更新就可以了。
  • 如果它真的很重要,那么该解决方案是不可接受的,因为它在某些情况下失去一些发挥。

另一种选择是(如我之前所说)是调整数据库;例如选择最合适的数据库引擎/表类型/索引,并调整用于进行更新的 SQL 或存储过程。如果您正确调整数据库,每秒 200 次更新不会过于昂贵。


如果我遇到的解决方案对我的性能影响不大,那么显然不会。

如果情况确实如此,那么只需采用“每 5 秒保存一次”的方法。或者,如果您想要更好的性能“5 分钟”或“5 小时”。

实际上,您并没有真正理解我在问什么......因为(对于不了解您业务的人)并不明显(对于不了解您的业务的人)这并不重要,并且性能确实不应该相关完全没有答案。要么重要,要么不重要。

让我换个方式问这个问题:

“如果计数不准确会损害您的业务

【讨论】:

  • 感谢您的意见。让我们讨论一下,记住每秒 200 次更新是昂贵的。第 1 点:性能是我唯一关心的问题。我可以承受 4-5 秒的记录更新延迟。第 2 点:我们将使用 RAC DB,我们不支持双重容错。如果服务器在部署应用程序的位置崩溃,那么我们可以放置一些逻辑......类似......如果特定播放 ID 的计数值为零......从数据库中获取最后一个计数,然后将其增加到一。
  • 我们将这些信息保存在数据库中,因为通过这些记录,我们需要获取记录,例如为这个时间戳播放了多少播放 id(一些东西)。每秒 200 次更新......你不认为它会押注我现有系统的性能......
  • The big question ... which you haven't answered ... is whether it matters if you fail to count some "plays" occasionally. 如果我遇到的解决方案对我的性能影响不大,那么显然不会。
  • The alternative is (as I said before) is to tune the database; e.g. choose the most appropriate database engine / table types / indexes, and tune the SQL or stored procedure used to do the update. 200 updates per second is not excessively expensive if you tune the database properly. 下面是我的数据库列。我正在使用 Oracle10g。请帮助我定义表类型/索引并调整 PLSQL 以进行更新和插入。(现在我真的很想看看性能在每秒连续 200 次更新后,我的系统会告诉你结果:))
  • - 播放 ID - ID 类型 - 歌曲或消息 计数 - 总和总播放次数 重试次数 - 总播放次数的总和,如果失败。 持续时间 - 总持续时间 上次更新 - 延迟更新日期时间
【解决方案2】:

好吧,您可以每秒访问您的数据库 200 次或更多,但在您的场景中,这不是必需的。而是在内存中创建一个同步计数器(就像一个带有原子整数的单例类),每次播放歌曲时都会递增,然后每隔 30 秒左右更新一次数据库中的计数值。我实际上做过类似的事情,效果很好。只需确保每个可数实体都有一个计数器类实例(我猜这里是歌曲),并且递增计数器值是线程安全的(原子整数应该解决这个问题)

【讨论】:

  • 是的,如果消息不会间歇性更新,我会推荐这种方法。他还可以放置一些缓存清除逻辑来补偿内存使用。
  • 做缓存是一个很好的建议,特别是如果在很多地方都需要这种行为并且手动编码会很耗时。 EhCache 有一个很好的简单 API 可以帮助您:ehcache.org/documentation/user-guide/getting-started
  • 嗯,谢谢,但我没有太多经验....我正处于学习阶段....请给我 4-5 行缓存概述...如何用简单的话解决我的问题......只是一个概述......所以一旦我阅读了文档......我就能得到它......这会很棒......
  • 唯一的问题是,如果您的系统在上次更新后 29 秒崩溃,您将丢失该数据。这可能是一个问题,也可能不是,取决于您的应用程序(请参阅@Stephen C 答案)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 2017-07-27
  • 2022-11-10
  • 2019-03-19
相关资源
最近更新 更多