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