3

我有一个通过 http 提供文件的 java 文件服务器。每个文件都可以通过 ID 进行唯一寻址,如下所示:

http://fileserver/id/123455555

我希望为此添加一个缓存层,以便最常访问的文件保留在内存中。我还想控制缓存的总大小。我正在考虑为此使用 ehcache 或 oscache,但我之前只使用它们来缓存序列化对象。它们会是一个不错的选择吗?构建文件缓存是否还有其他注意事项?

编辑

感谢所有的答案。有关文件服务器的更多详细信息以简化(或复杂化)问题:

  1. 一旦文件被保存,它就永远不会被修改。
  2. MD5 哈希以避免在保存时重复文件。(我知道可能的碰撞和安全问题)
  3. 在 linux 机器上运行的文件服务器。

编辑 2 虽然服务器本身对其支持的文件类型没有任何限制,但文件大多是图像(jpg、gif、pgn)、Word、excel、不大于 10Mb 的 PDF。

4

4 回答 4

2

番石榴缓存?http://code.google.com/p/guava-libraries/wiki/CachesExplained

  • 不错的 API
  • 基于时间的驱逐
  • 基于大小的驱逐
于 2012-05-14T06:19:31.273 回答
1

Ehcache 也提供了进行网络缓存的能力。您可能想尝试http://www.ehcache.org/documentation/user-guide/web-caching

于 2012-05-14T06:34:56.290 回答
1

恕我直言,您最好使用 OS 磁盘缓存,因为这有几个优点。

  • 它更简单,因为操作系统完成了所有实际工作。
  • 操作系统可以使用所有可用的可用内存,这取决于系统的其他功能。
  • 您不会加倍使用磁盘缓存(因为它是磁盘缓存)。

无论如何,操作系统都会将所有最近最少使用的文件保存在内存中。

于 2012-05-14T07:15:31.507 回答
1

利用 HTTP 协议

到目前为止,您最有效的缓存机制是将缓存移出您自己的服务器并尽可能靠近客户端(数据局部性;))。有效地使用 HTTP 协议以允许客户端和缓存代理在适当的时候进行缓存:

  • 使用每个文件内容的某些功能(例如 MD5Sum)设置 ETag - 也缓存此信息,这样您就不会在每个服务上重新计算!
  • 根据需要设置 Expires / Last-Modified / Cache-Control 标头

编辑:您更新说文件永远不会被修改,所以我建议将 Expires 标头设置为遥远的未来日期。

...现在更直接地回答这个问题...

缓存

我对 EhCache 的体验是一个不错的选择,可以满足您提到的要求。

您提到“最常访问的文件保留在内存中”,因此似乎有必要提及,根据我(几年前)所做的一些性能测试,LFU(最不常用)驱逐策略LRU(最少最近使用)缓存写入 - 实际上慢了 30 倍。这是 LFU 与 LRU 的额外复杂性的产物。

检查您在生产中真正看到的数据使用模式以了解哪种驱逐策略最适合您,这将是一个好主意。在大多数情况下,我建议将 LRU 作为起点,因为它在缓存足够大并且没有大量异常数据访问的情况下接近 LFU。

操作系统缓存

我没有使用过 OSCache,所以不能在那里说什么。

其他注意事项

  1. 在他的回答中,Peter Lawrey 建议使用操作系统缓存。虽然这意味着你要为从 java 到 native 的读取付出代价,但我认为这个想法有很大的优点,因为它避免了在 Java 堆中缓存的一个重大问题:垃圾收集器有额外的工作来拖网大堆。(另一种解决方案是使用堆外缓存,例如通过BigMemory,但这有其自身的权衡)
  2. 如果内容是可压缩的,您可能需要考虑缓存文件的压缩(gzip'd)版本(否则您最终将在每次提供它时重新压缩它!)。这是反对使用 OS 磁盘缓存的一个论点。当然,还有其他一些与压缩相关的注意事项(例如,内容足够大,可以保证压缩并且压缩得相当好),因此它确实取决于这些文件中的内容。
于 2012-05-14T07:59:49.737 回答