【发布时间】:2015-08-27 14:25:36
【问题描述】:
我想使用缓存来保存刚刚来自数据库读取的最近访问的对象。
在我的例子中,数据库主键是 Long。
在每种情况下,我都会有一个表示该数据的对象(案例类)。
Long 加上完整的类名的组合将成为查找任何特定对象的唯一标识符。 (命名空间不应该有冲突,因为类名不使用数字(通常?)。无论如何,对于这个用例,我控制整个命名空间,所以不是一个大问题)。
对象在缓存中的寿命相对较短——我只看到了一些情况,我可以通过多次保存相同的不可变对象来节省内存,而不是同一对象的不同实例,这将非常难以“到处传递一切”以避免。
这也有助于在不同眼球检查相同内容的情况下提高性能,但这不是这个特定用例的驱动因素(只是肉汁)。
我现在担心每 时间我需要一个给定的对象,我需要重新创建缓存键。这将涉及 Long.toString 和 String Concat。有问题的案例类在它们的伴生对象中有一个 val ,这样它们就知道它们的类名而不会发生任何进一步的反射。
我正在考虑将“缓存”放在主缓存键的伴随对象中,因为我希望避免(不必要的?)每次查找的重复操作以及由此产生的垃圾收集等。(最快的代码要运行的是永远不会被编写(或调用)的代码 - 对吧?)
有没有更优雅的方法来处理这个问题?其他人已经解决了这个特定问题吗?
我曾想过编写一个键类,但即使对 hash 和 toString 使用 val(惰性或其他方式),我仍然会为我要求的每个对象获得命中,因为现在我必须每次都创建键对象。 (这当然可以回到伴随对象的键缓存中,但如果我为键设置伴随对象缓存的麻烦,那么键对象方法是多余的。)
作为这个问题的第二个问题 - 假设我使用 Long 和完整的类名(作为字符串)最有可能获得最快的缓存拉取?
Long.toString + fullClassName
或
fullClassName + Long.toString
Long 是键中的字符串,所以假设它是缓存中的字符串“find”,这样更容易索引查找?首先是数字部分或字符串类名。
数字优先意味着您遍历所有具有匹配数字的对象以搜索匹配的类,而类优先意味着您首先找到特定类的块,但您必须走到字符串的最后才能找到完全匹配.
我怀疑前者可能更容易针对“快速查找”进行优化(我知道用 MySQL 术语来说是......)
那么,也许有人已经有了基于双键查找的缓存? :)
【问题讨论】:
-
将存在多少个应用程序实例?如果不止一个,你是假设一个分布式缓存还是每个应用实例都有自己的缓存?
-
好问题 - 没有试图假设任何东西,但我怀疑每个应用程序都有自己的缓存。处理深度嵌套的分层对象只是短暂的,这些对象往往会不时追逐自己的尾巴。