0

这是我正在考虑做的事情,我想知道你是否认为这是个好主意。

我从数据库中检索了一堆行,这在 groovy 中给了我一个列表列表,例如:

[
  [ 'Dog', 'M', 'Mutt', 'Sammy' ],
  [ 'Cat', 'F', 'Siamese', 'Pat' ],
  [ 'Dog', 'M', 'Husky', 'Taco' ],
  ...
]

不是我的真实数据集,但你明白了。

由于我将非常频繁地提取这些数据并在将其呈现在 UI 中之前对其进行一些分析,因此我想将其存储在由 groovy 映射(即 LinkedHashMaps)键入的MultiValueMap中,因此我可以检索其中的点点滴滴我需要,而不是每次都去数据库。它是来自多个表的数据子集的缓存(比上面的动物数据更复杂)。

我可以这样使用它:

animals.get([species:'Dog', gender:'M'])

返回:

[['Sammy', 'Mutt'], ['Taco', 'Husky'] ]

我想我知道如何实现它,所以我并不是真的在寻找它(尽管如果你有一个新颖的建议,请分享)。我主要是在找人告诉我,这要么由于某种原因不起作用,要么听起来不错,要么无法扩展,等等。或者也许有一些更简单的方法可以获得类似的功能。另一个考虑因素:整个数据集有时可能有点大,例如只有 10 万条记录。如果不是这样,除了每次都点击数据库之外,还有什么好方法来处理它?

我意识到周围有很多键/值缓存解决方案,但我认为我正在做的事情不需要如此繁重的任务。它只是一个使用率很低的小型 web 应用程序,主要是我正在为其构建的公司内部。

4

2 回答 2

2

如果您使用的值的子集是静态/确定性的,我只需将其转换为字符串并将其用作地图中的键。因此animals.get([species:'Dog', gender:'M']),我会使用animals.get('species:Dog:gender:M').

我知道您说您认为键值存储过于重量级,但这也是 Redis 的完美用例,它可以原生存储诸如哈希映射之类的东西。

您所说的存储类型正是我们在我工作的生产环境中使用它的方式,而且非常棒。它非常快,并且可以用于所有正在运行的进程,而无需拥有一个单例或多个非常大的地图副本。缓存失效也是你需要考虑的问题,redis 有助于解决。

您可以使用grails-redis 插件来记忆您的数据库调用,以便它首先自动检查 redis 以查看它是否在缓存中,如果不是,它会查询数据库并将其粘贴在缓存中,然后再返回。有关更多详细信息/示例,请参阅github 上的文档。

return redisService.memoizeHash('species:Dog:gender:M') {
    // database call that returns object, then you turn that into hash
    Dog d = Dog.findBy...
    [species: d.species, gender: d.gender, breed: d.breed, name: d.name, ...]
}

这样,只有当 Redis 还没有缓存时,它才会查询数据库。在缓存未命中时,它将返回值保存在 redis 中指定键的位置。

(免责声明,我是grails-redis 插件的作者,所以我有一些偏见)

于 2011-08-18T03:52:35.967 回答
0

使用可变 Map 作为键是一个非常糟糕的主意,因为如果键发生更改,则将找不到它。

于 2011-08-18T01:00:58.283 回答