SW-Architecture - 服务层和持久层之间的缓存

时间:2016-04-10 12:36:34

标签: caching architecture filesystems

我正在开发一个文件系统,它使用融合库和jnr-fuse(https://github.com/SerCeMan/jnr-fuse)封装对Amazon S3存储桶的访问作为java绑定。

我的第一个版本正在运行,目前正在进行一些代码清理和重构工作,试图将所有内容都放到一个合适的多层架构中。

到目前为止,我大致有以下几点:

  • 前端:这是来自jnr-fuse的FuseFileSystem接口的实际实现。它对jnr(native)类型有一些依赖,而且这些方法是fuse的c函数的java等价物。
  • 服务层:一个接口,它具有来自前端层的所有文件系统方法的“非本机相关”版本,但不依赖于jnr或融合。这个想法也可以在其他环境中使用(例如,作为S3的java.nio.FileSystem-API实现的核心组件,或任何其他需要在“文件系统”中访问S3的API的场景-ish“时尚但不想通过保险丝这样做,因此不想要所有jnr依赖项”

我目前正在努力的是持久层:由于与S3的所有通信实际上是通过http完成的,我正在进行一些相当数量的缓存以减少流量并提高性能。 问题是缓存最适合的地方..

显然,实际的DAO不应该被任何类型的缓存/锁定逻辑污染 - 它们应该只处理对数据的实际访问(即对S3进行http调用)。 另一方面,服务层也不应该真正关注缓存(如果持久层和缓存需求发生变化),所以我想要做以下其中一种:

  1. 使用“doubled”持久层:每个DAO实现两次:一个版本保存缓存并从其缓存中提供数据。如果一个对象不在缓存中,我们委托第二个DAO实际获取该对象(然后将其添加到缓存中)
  2. 引入一个单独的“缓存”层,其界面与处理所有缓存需求的实际持久层略有不同,并根据需要委托给持久层。
  3. 从服务层的角度来看,版本1将是更清晰的 - 使用缓存和不使用缓存之间没有任何区别,因为对持久层的所有调用都将针对相同的接口。另一方面,它还将关于文件的状态或“生命周期”的所有逻辑(打开 - >读/写 - >关闭)转移到持久层。 版本2将管理“缓存”层内文件的生命周期,我认为这将使任何刚接触代码的人更容易理解。另一方面,它还假设总是是一个缓存层(可能是真的)。​​

    从设计的角度来看,上述方法是否有任何其他利弊,或者是否存在解决此类问题的模式?

    现在我宁愿选择选项2,但听到一些意见真的很有意思。

1 个答案:

答案 0 :(得分:4)

你为什么反对在DAO中缓存?这一直是我缓存的理想场所。它是一个数据访问问题,因此进入数据访问层。有几次我为方便起见使用了各种AOP实现,但有90%的时间,我在DAO中实现了缓存逻辑。

缓存本身并不存在于DAO中,它通常是它自己的接口,所以我可以在实现之间交换(内存中,磁盘上等)。

使用Apache HTTP客户端自带的内置缓存时,我也有一些运气。它允许您尊重HTTP缓存语义,或使用自定义逻辑覆盖它。