代码之家  ›  专栏  ›  技术社区  ›  Aidos

在爪哇中构建“隔离”和“自动更新”高速缓存(java. U.L.List)

  •  1
  • Aidos  · 技术社区  · 14 年前

    对于任何感兴趣的人: 我已经实现了我正在寻找的行为的代码,并在google代码上开源。把它拿过来! pojo-mvcc

    ——

    嗨,伙计们,

    我试图编写一个框架,其中包含许多从长寿命缓存创建的短期缓存。这些短期缓存需要能够返回其实体内容,实体内容是从原始长期缓存的克隆。

    实际上,我试图构建的是短时间缓存的事务隔离级别。用户应该能够修改短期缓存的内容,但对长期缓存的更改不应该通过(也有一种情况,根据缓存类型,更改应该通过推送)。

    我会尽力解释:

    主缓存包含:[a,b,c,d,e,f] 使用状态[a、b、c、d、e、f]创建的临时缓存

    1)临时缓存添加项g:[a、b、c、d、e、f] 2)临时缓存删除项B:[A、C、D、E、F]

    主缓存包含:[a,b,c,d,e,f]

    3)主缓存添加项[x,y,z]:[a,b,c,d,e,f,x,y,z]

    临时缓存包含:[a,c,d,e,f]

    当项中的值可以更改且不应总是更新时,事情变得更加困难(因此我甚至不能共享底层对象实例,我需要使用克隆)。

    我已经实现了一个简单的方法,就是在arraylist上使用标准的collection构造函数创建一个列表的新实例,但是当您得到大约200000个项时,系统就耗尽了内存。我知道200000的值对于迭代来说太多了,但是我试图稍微强调一下我的代码。

    我原以为它可以以某种方式“代理”列表,所以临时缓存使用主缓存,并存储它的所有更改(实际上是更改的纪念品),但是当您想要迭代临时缓存或检索特定的项时,这很快就会成为一个噩梦。FIC指数另外,考虑到我希望对列表的内容进行一些修改(取决于临时缓存的类型,不管它是不是“自动更新”),我完全无法理解。

    任何指向技术、数据结构或只是一般概念的尝试和研究都将受到极大的赞赏。

    干杯,

    AIDOS

    1 回复  |  直到 14 年前
        1
  •  2
  •   Will Hartung    14 年前

    这是你想做的。类似于mvcc,多版本货币控制。

    简单地说,您需要将事务id与缓存元素相关联。

    所以缓存条目看起来像这样:

    public class CacheEntry {
        long transactionId;
        boolean deleted;
        Object value;
    }
    

    缓存条目以相反的transactionid顺序存储在列表中。

    当你去获取一个缓存元素时,你会查找列表(在你的散列映射中)。然后搜索具有最高事务ID的值,该值小于或等于事务的事务ID。

    所以,让我们考虑一下删除问题。

    你有第10笔交易,寻找“ABC”。我们假设ABC已经在缓存中了,它是由事务5放入的。

    因此,t10获取abc的条目列表,向下搜索列表,发现在t5处有值“123”。t5是小于或等于t10的最高交易。t10将abc的值从123更改为456。

    现在t12出现了,它寻找abc。它将从t10中找到456的值。t12决定删除abc,因此t12的一个“deleted”缓存条目被放置在缓存条目列表中。如果t10再次尝试查找abc,它将找到456,因为12>10,并且最高事务<=10是t10,因此它看不到删除。

    t14出现,搜索abc,找不到它(因为它被“删除”),并插入一个新值789。如果t12看起来仍然会被删除,如果t10是,它仍然是456。

    最后,缓存列表如下所示:

    {tid: 14 deleted: false value: 789}
    {tid: 12 deleted: true  value: nul}
    {tid: 10 deleted: false value: 456}
    {tid:  5 deleted: false value: 123}
    

    下一个问题是处理开放事务的可见性。也就是说,另一个事务是否可以看到另一个未提交的未完成事务的数据。但这并不太难,因为它只是在扫描合适候选人的版本列表时调整标准。您还可以保留一个事务id列表,其中包含它们的状态(open、committed、rolledback)。

    最后,你必须想出一个机制来清理松散的末端。提交两个事务后,如果没有其他打开的事务,则可以删除较旧的记录。

    例如,如果您有来自t5和t10的数据,如果这两个数据都已提交,那么将无法再次“看到”t5的数据,因为t10现在是“当前”状态。因此,可以删除t5行。

    这可能最好通过简单地遍历缓存并删除过时的事务条目来完成。

    这就是它的要点,显然魔鬼在细节。