1

问题:
我需要实现多个共享序列生成器,它们将被 50-100 个 Tomcat 服务器使用。每个序列生成器应从 1 开始,并在每次请求后递增 1。序列生成器实现应该有原子增量命令。Java 客户端应该可用。

规模:
多达 50000 个积极使用的序列生成器,对于每个生成器,我们预计在 5-10 秒内有一个增量请求。每秒最多 20000 个请求
50-100 个 Java 客户端(Tomcat 服务器)。对序列生成器的访问在这些服务器之间共享。重要提示:只有 2 个客户端使用相同的序列生成器。
50-100 次 - 每个序列生成器的平均使用次数。
24 h TTL - 一个生成器最多应在创建后 24 小时后被清理 - 因此实际上可能有超过 50000 个序列生成器,但预计最多只有 50000 个会同时主动接收请求。

性能:
<1ms 优选平均响应时间。平均超过 2ms 绝对不够好。

我们排除了 Oracle 的 Sequence 对象。
我们目前正在考虑 Redis 和 Memcached。
两者都很快。

推荐/足够好的实现是什么?
为此目的还有其他更好的技术吗?

另一个重要的问题:
incr、Redis 或 Memcached 哪个性能更好?

谢谢

4

2 回答 2

6

Redis 应该让你轻松做到这一点。

  1. 为每个序列生成器创建一个键
  2. 使用INCR命令获取下一个序列号
  3. 如果返回的数字为 1,则表示该键以前不存在。在这种情况下,您还应该发出PEXPIRE命令以在 24 小时后使密钥过期

为了进一步减少延迟,您可以做几件事 -

  1. 仅为序列生成器维护 Redis 服务器。换句话说,不要在此服务器上存储任何其他数据。
  2. 不要使用 AOF;而是使用 RDB 持久性。AOF 将在日志文件中附加每个 INCR 命令,另一方面,RDB 将简单地存储每个序列的当前值。

您应该通读诊断延迟问题以及有关redis 持久性的页面。

此外,expire 命令必须在 24 小时内最多发出一次,这将需要两次往返 redis。如果你想避免这种情况,你可以创建一个 lua 脚本。速率限制 lua 脚本是一个很好的起点。

于 2012-08-20T11:42:43.247 回答
3

我有以下建议:

天真的方法是有问题的,因为它涉及对保存当前序列值的记录进行非常细粒度的锁定。有这么多客户 - 它会产生难以忍受的争执。

我的建议是允许客户对一系列序列进行预订。因此,客户第一次订购了一个范围,例如从 1 到 1000。此订单的处理是同步的。因此,如果另一个人同时要求一个范围 - 它应该阻止并稍后接收范围 1001 到 2000。

每个客户端都会获得一个不相交的序列池并从中提取值。一旦池耗尽,它就会向数据库询问另一个范围。如前所述,这涉及锁定。

问题是您可以微调范围的大小以权衡锁争用和资源利用率(不能保证完全使用保留的范围 - 客户端可能会决定它不再需要任何序列,或者它可能会完全崩溃)。

于 2012-08-19T18:10:45.240 回答