如何更新片段缓存,同时允许在更新期间从缓存中读取?

时间:2010-01-26 22:01:12

标签: ruby-on-rails memcached

有没有办法以允许在更新发生时从缓存中读取的方式刷新片段缓存?

我正在使用erb中的cache do .. end块缓存Rails中html.erb视图的一部分。

我通过调用expire_fragment(:controller => 'controllername')

使控制器中的缓存过期

我正在使用memcached作为片段缓存存储。

我可能是错的,但看起来默认行为是你调用expire_fragment片段从缓存中删除的那一刻,所以另一个请求在此之后的一瞬间对同一个片段将丢失缓存

我真正想要的是从缓存中读取内容,直到新片段被计算并保存在缓存中,此时所有后续请求都会获得新的缓存版本。

这个特定的片段计算起来很昂贵。大约需要7秒钟。

2 个答案:

答案 0 :(得分:0)

我认为memcached有一些处理读写冲突的机制。

此问题仅适用于流量非常高的网站。

编辑: 发现了一个问题“Is_memcached_atomic?”在memcached FAQ

  

发送到的所有单个命令   memcached绝对是原子的。如果   你发送一套和一个并行,   针对同一个对象,他们不会   互相遮挡。他们会   序列化,一个将被执行   在另一个之前。甚至在线程中   模式,所有命令都是原子的。如果他们   不是,这是一个错误:)

我不认为你描述的问题会成为一个问题。在没有进入Rails内部的情况下,仍然可能在多vm Rails环境中可能存在高速缓存未命中,但最坏的情况仅仅是片段是由恰好具有正确时序的请求生成的。除非你的碎片非常昂贵(秒而不是毫秒)并且你的流量和基础设施很庞大(多个轨道实例,每秒数百个请求),我怀疑这将是一个问题。

答案 1 :(得分:0)

您还可以在后台计算缓存值的新值,然后以原子方式切换读取器以使用新值。对于某些应用程序,这可以提供帮助。例如,写一个缓存的大文件可能需要一段时间。使用此技术可以写入新版本的文件,同时仍然可以从缓存中提供旧版本。这是技术:

使用版本号作为缓存键的一部分。这可以使用片段缓存或内存缓存来完成。

步骤:

  1. 将“cache_ver”添加到相应的模型
  2. 计算缓存密钥时包含cache_ver。请记住,片段“缓存”方法可以使用任何字符串。
  3. 更新缓存:
    1. 计算cache_ver的下一个值
    2. 计算缓存的新值,并使用新的cache_ver作为密钥的一部分将其存储在缓存中
    3. 更新模型的cache_ver。 - 下次请求进入时,控制器将查找cache_ver并使用新值,并返回新结果
    4. 不要忘记在某些时候刷新旧的缓存值。也许每晚......
  4. 如果需要,cache_ver可以存储在mem_cache中,而不是db。