9

本学期我已经学习了一个数据库类,并且正在研究如何维护RDBMS和缓存服务器(如memcached)之间的缓存一致性。存在竞争条件时会出现一致性问题。例如:使用memcached和像MySQL这样的rdbms时的缓存一致性

  1. 假设我从缓存中做一个get(key),并有高速缓存未命中。因为我得到一个缓存未命中,我从数据库中获取数据,然后在缓存中执行一个put(key,value)
  2. 但是,竞争条件可能会发生,其中一些其他用户可能会删除从数据库中提取的数据。在我将put放入缓存之前,可能会发生此删除操作。

因此,理想情况下put进入缓存不应该发生,因为数据在数据库中较长。

如果高速缓存条目具有TTL,则高速缓存中的条目可能会过期。但仍有一个窗口,其中缓存中的数据与数据库不一致。

我一直在寻找关于这类问题的文章/研究论文。但是,我找不到任何有用的资源。

回答

0

如何使用memcache中保存的变量作为锁定信号?

每一个内存缓存的命令是原子

您从数据库中检索数据后,拨动锁

你把数据到内存缓存后,拨动锁断

之前从数据库中删除,请检查锁定状态

-1

当你读,会发生以下情况:

if(Key is not in cache){ 
    fetch data from db 
    put(key,value); 
}else{ 
    return get(key) 
} 

当你写,会发生以下情况:

1 delete/update data from db 
2 clear cache 
+0

请解释如何解决问题中提到的竞争条件。你的回答显然不能解决问题。 – Alexey

0

本文为您提供在Facebook上如何(试图)维持缓存的一致性一个有趣注:http://www.25hoursaday.com/weblog/2008/08/21/HowFacebookKeepsMemcachedConsistentAcrossGeoDistributedDataCenters.aspx

下面是文章梗概。

  1. 我从“杰森”到“西游记”更新我的名字
  2. 我们在加利福尼亚的主数据库写“西游记”,并在加利福尼亚州从memcache中删除我的名字,但不是弗吉尼亚
  3. 有人去我在弗吉尼亚
  4. 轮廓我们在memcache中找到我的名字,并返回“杰森”
  5. 复制赶上,我们用我的名字为“猴子更新从数据库。“我们也从弗吉尼亚的memcache中删除我的名字,因为缓存对象的复制流中出现了
  6. 别人进入我的个人资料在弗吉尼亚
  7. 我们没有在memcache中找到我的名字,所以我们阅读从从,并得到“西游记”
0

下面的代码给出了如何使用Memcached的运营addgetscas实现乐观锁定,以确保与数据库缓存的一致性一些想法。
免责声明:我不保证它是完全正确的,并处理所有竞赛条件。另外,一致性要求可能因应用程序而异

def read(k): 
    loop: 
    get(k) 
    if cache_value == 'updating': 
     handle_too_many_retries() 
     sleep() 
     continue 
    if cache_value == None: 
     add(k, 'updating') 
     gets(k) 
     get_from_db(k) 
     if cache_value == 'updating': 
     cas(k, 'value:' + version_index(db_value) + ':' + extract_value(db_value)) 
     return db_value 
    return extract_value(cache_value) 

def write(k, v): 
    set_to_db(k, v) 
    loop: 
    gets(k) 
    if cache_value != 'updated' and cache_value != None and version_index(cache_value) >= version_index(db_value): 
     break 
    if cas(k, v): 
     break 
    handle_too_many_retries() 

# for deleting we can use some 'tumbstone' as a cache value