在 RavenDB 4.0 中(是的,这还差得远),我们正在研究其他数据类型和存储引擎。例如,我们要添加的内容之一是八卦分布式计数器的概念。然而,对于我们这里的目的而言,这实际上并不重要。
我今天想谈的是通过网络进行小更新的问题。考虑计数器示例。到目前为止,最常见的操作是以下的一些变体:
counters.Increment(name, 1);
由于数据库是远程的,我们需要通过网络发送。但这是一个 非常 小的操作。为此一路走到远程数据库是浪费时间。考虑到在大多数系统中,我们不只有一个执行线程,我们有很多。他们每个人都在执行自己的操作。允许每个操作自行进行是一种很大的浪费,但我们还能提供哪些其他选择?
还有其他考虑因素。虽然大多数时候我们会进行小操作,但也经常需要进行批量操作。也许您是第一次设置系统,或者从文件中导入数据等。发出大量的单独请求会扼杀任何快速执行此操作的希望。显而易见的答案是使用批处理。一次向服务器发送大量值。这显着降低了网络开销。
该 API 类似于:
counters.Increment(name, 1);
所以这对大事情来说很好,但对个人操作不是很有帮助。我们仍然必须为每一个去服务器。
当然,我们也可以使用批处理 API,但是将其用于单个操作是……很大的浪费。
该怎么办?
我们得出的最终结果是我们拥有三个级别的 API:
- 计数器.增量(名称,1); – 单一操作,立即通过网络执行。保证成功或失败并给你结果。
- counters.Advanced.NewBatch() – 批处理操作,对批处理中的所有项目执行(但不是作为单个事务),会让您知道 整个 操作是否成功,或者是否存在问题。
- counters.Batch.Increment() – 默认批处理,线程安全,可由单个请求使用。这是一次即发即弃的操作。我们递增,在幕后我们将合并来自所有线程的所有增量,并将它们分批发送到服务器。
请注意,最后一个选项意味着我们将只进行批处理,因此只有当足够的时间过去或我们有足够的项目要发送时,我们才会将数据发送到服务器。这个想法是你可以根据你正在做的事情的重要性来选择。
如果您需要确认某事是否成功,请使用单独的操作。如果您只是希望我们尽最大努力,并且如果真的发生了一些不好的事情您不关心它,请使用批处理选项。
请注意,我在这里使用计数器示例是因为它很简单,但同样适用于时间序列和我们当前正在构建的其他内容。