使用分布式 JVM 缓存同步计算和结果

Posted

技术标签:

【中文标题】使用分布式 JVM 缓存同步计算和结果【英文标题】:synchronizing computation and result using a distributed JVM cache 【发布时间】:2015-06-28 06:53:24 【问题描述】:

我想缓存一个昂贵的操作,并且不希望其他线程在给定时间在不同的 JVM 中执行相同的操作。我们保证在同一时间为同一计算获得至少 5 个近乎实时的请求,并且对简化这些请求没有任何控制权。

我能想到的解决方案:

    这些其他线程可能会等待获取锁 (Hazelcast),但如果有更多线程,最后一个获取锁的线程可能会花费很多 等待获取锁的时间。

有没有办法让这些其他线程简单地“等待锁定” 被释放”而不是获取锁,因为他们只是在阅读 来自缓存?

    使用轮询。首先,阻塞 threadId=cache.putIfAbsent(key) 返回哪个线程将处理,其他线​​程将继续轮询另一个 通过 threadId 缓存条目以获取结果。这是浪费投票, 有没有办法“等待从缓存中读取”?

    一个实际的分布式“Shared Reentrant Read Write Lock”似乎是解决方案,但 Apache Curator 库似乎并不轻 重量。我正在寻找一个简单的异步 P2P 分布式缓存 接近。

或者我如何使用 HazelCast 达到同样的效果? 总的来说,首先阻塞和避免计算(在我们的例子中是 CPU 和 IO 限制)不是比让所有线程计算并说使用数据库/缓存失败额外写入并返回第一个计算结果更好的方法吗?

【问题讨论】:

很好的面试问题;)。 【参考方案1】:

前段时间做了以下事情,首先发布了一个已经使用 Hazelcast 的解决方案:https://github.com/ThoughtWire/hazelcast-locks。

这个库代替了一个分布式的“共享可重入读写锁”,允许在写入时锁定,但在读取时不允许锁定,因此我们保证这只发生一次。我们面临的唯一问题是锁定释放通知的等待时间比我们预期的要长。除此之外,您必须在特定时间后以某种方式显式清理昂贵的锁,因为它们与特定的键相关联。

我们最终在请求到达 tomcat 容器之前在转发代理中实现了一个自定义逻辑,该容器基本上根据密钥将请求路由到特定服务器,并且我们在基于相同的共享并发映射条目上有一个本地 JVM 锁定完成这项工作的关键。此外,清理逻辑要简单得多。

【讨论】:

您能否扩展您的答案以显示它如何回答您的问题?

以上是关于使用分布式 JVM 缓存同步计算和结果的主要内容,如果未能解决你的问题,请参考以下文章

分布式本地缓存(JVM缓存)

浅谈分布式缓存解决方案

缓存异步集群和分布式等架构模式的实践

一种基于“哨兵”的分布式缓存设计

Redis进阶学习06--分布式缓存--上

史上最强大型分布式架构详解:高并发+数据库+缓存+分布式+微服务+秒杀