API 设计:网络上的小修改

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

在 RavenDB 4.0 中(是的,这还差得远),我们正在研究其他数据类型和存储引擎。例如,我们要添加的内容之一是八卦分布式计数器的概念。然而,对于我们这里的目的而言,这实际上并不重要。

我今天想谈的是通过网络进行小更新的问题。考虑计数器示例。到目前为止,最常见的操作是以下的一些变体:


 counters.Increment(name, 1);

由于数据库是远程的,我们需要通过网络发送。但这是一个 非常 小的操作。为此一路走到远程数据库是浪费时间。考虑到在大多数系统中,我们不只有一个执行线程,我们有很多。他们每个人都在执行自己的操作。允许每个操作自行进行是一种很大的浪费,但我们还能提供哪些其他选择?

还有其他考虑因素。虽然大多数时候我们会进行小操作,但也经常需要进行批量操作。也许您是第一次设置系统,或者从文件中导入数据等。发出大量的单独请求会扼杀任何快速执行此操作的希望。显而易见的答案是使用批处理。一次向服务器发送大量值。这显着降低了网络开销。

该 API 类似于:


 counters.Increment(name, 1);

所以这对大事情来说很好,但对个人操作不是很有帮助。我们仍然必须为每一个去服务器。

当然,我们也可以使用批处理 API,但是将其用于单个操作是……很大的浪费。

该怎么办?

我们得出的最终结果是我们拥有三个级别的 API:

  • 计数器.增量(名称,1); – 单一操作,立即通过网络执行。保证成功或失败并给你结果。
  • counters.Advanced.NewBatch() – 批处理操作,对批处理中的所有项目执行(但不是作为单个事务),会让您知道 整个 操作是否成功,或者是否存在问题。
  • counters.Batch.Increment() – 默认批处理,线程安全,可由单个请求使用。这是一次即发即弃的操作。我们递增,在幕后我们将合并来自所有线程的所有增量,并将它们分批发送到服务器。

请注意,最后一个选项意味着我们将只进行批处理,因此只有当足够的时间过去或我们有足够的项目要发送时,我们才会将数据发送到服务器。这个想法是你可以根据你正在做的事情的重要性来选择。

如果您需要确认某事是否成功,请使用单独的操作。如果您只是希望我们尽最大努力,并且如果真的发生了一些不好的事情您不关心它,请使用批处理选项。

请注意,我在这里使用计数器示例是因为它很简单,但同样适用于时间序列和我们当前正在构建的其他内容。