利用 HTTP 协议
到目前为止,您最有效的缓存机制是将缓存移出您自己的服务器并尽可能靠近客户端(数据局部性;))。有效地使用 HTTP 协议以允许客户端和缓存代理在适当的时候进行缓存:
- 使用每个文件内容的某些功能(例如 MD5Sum)设置 ETag - 也缓存此信息,这样您就不会在每个服务上重新计算!
- 根据需要设置 Expires / Last-Modified / Cache-Control 标头
编辑:您更新说文件永远不会被修改,所以我建议将 Expires 标头设置为遥远的未来日期。
...现在更直接地回答这个问题...
缓存
我对 EhCache 的体验是一个不错的选择,可以满足您提到的要求。
您提到“最常访问的文件保留在内存中”,因此似乎有必要提及,根据我(几年前)所做的一些性能测试,LFU(最不常用)驱逐策略比LRU(最少最近使用)缓存写入 - 实际上慢了 30 倍。这是 LFU 与 LRU 的额外复杂性的产物。
检查您在生产中真正看到的数据使用模式以了解哪种驱逐策略最适合您,这将是一个好主意。在大多数情况下,我建议将 LRU 作为起点,因为它在缓存足够大并且没有大量异常数据访问的情况下接近 LFU。
操作系统缓存
我没有使用过 OSCache,所以不能在那里说什么。
其他注意事项
- 在他的回答中,Peter Lawrey 建议使用操作系统缓存。虽然这意味着你要为从 java 到 native 的读取付出代价,但我认为这个想法有很大的优点,因为它避免了在 Java 堆中缓存的一个重大问题:垃圾收集器有额外的工作来拖网大堆。(另一种解决方案是使用堆外缓存,例如通过BigMemory,但这有其自身的权衡)
- 如果内容是可压缩的,您可能需要考虑缓存文件的压缩(gzip'd)版本(否则您最终将在每次提供它时重新压缩它!)。这是反对使用 OS 磁盘缓存的一个论点。当然,还有其他一些与压缩相关的注意事项(例如,内容足够大,可以保证压缩并且压缩得相当好),因此它确实取决于这些文件中的内容。