问题:
我需要实现多个共享序列生成器,将由50-100个Tomcat服务器使用。每个序列生成器应从1开始,并在每个请求后递增1。
序列生成器实现应具有原子增量命令。
Java客户端应该可用。
规模:
主动使用多达50000个序列生成器,对于每个序列生成器,我们期望在5-10秒内有一个增量请求。
每秒最多20000个请求
50-100个Java客户端(Tomcat服务器)。在这些服务器之间共享对序列生成器的访问。重要提示:只有2个客户端使用相同的序列生成器
50-100次 - 每个序列发生器的平均使用次数
24小时TTL - 发电机在创建后24小时内最多应该清洁 - 因此实际上可以有超过50000个序列发生器,但预计最多只能有50000个同时主动接收请求。
性能:
< 1ms优选的平均响应时间。平均超过2毫秒绝对不够好。
我们排除了Oracle的Sequence对象 我们目前正在考虑Redis和Memcached 两者都很快。
建议采用什么/足够好?
还有其他更好的技术用于此目的吗?
另一个重要问题:
哪个有更好的性能,用于incr,Redis或Memcached?
由于
答案 0 :(得分:4)
Redis应该让你轻松做到这一点。
为了进一步减少延迟,您可以做几件事 -
您应该阅读diagnose latency problems以及redis persistence上的页面。
此外,expire命令必须在24小时内最多发出一次,这需要两次往返redis。如果要避免这种情况,可以创建lua脚本。 rate limit lua script是一个很好的起点。
答案 1 :(得分:2)
我有以下建议:
天真的方法是有问题的,因为它涉及保持当前序列值的记录上非常细粒度的锁定。有这么多客户 - 它会造成无法忍受的争用。
我的建议是允许客户端对序列的范围进行预留。 因此,客户第一次订购范围,例如从1到1000。 该订单的处理是同步的。因此,如果另一个同时要求范围 - 它应该阻止并稍后接收范围1001到2000.
每个客户端获取一个不相交的序列池并从中提取值。一旦池耗尽,它就会向db询问另一个范围。如上所述,这涉及锁定。
问题是你可以微调范围的大小来权衡锁争用和资源利用(保证范围不能保证完全使用 - 客户可能会认为它不再需要任何序列或者它可能会崩溃共)。