使用 memcached 和 MySQL 等 RDBMS 时的缓存一致性

发布于 2024-12-10 08:44:42 字数 423 浏览 8 评论 0原文

这学期我选修了数据库课程,我们正在学习如何维护 RDBMS 和缓存服务器(例如 memcached)之间的缓存一致性。当存在竞争条件时,就会出现一致性问题。例如:

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

因此,理想情况下不应将数据放入缓存,因为数据在数据库中存在的时间较长。

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

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

I have taken a database class this semester and we are studying about maintaining cache consistency between the RDBMS and a cache server such as memcached. The consistency issues arise when there are race conditions. For example:

  1. Suppose I do a get(key) from the cache and there is a cache miss. Because I get a cache miss, I fetch the data from the database, and then do a put(key,value) into the cache.
  2. But, a race condition might happen, where some other user might delete the data I fetched from the database. This delete might happen before I do a put into the cache.

Thus, ideally the put into the cache should not happen, since the data is longer present in the database.

If the cache entry has a TTL, the entry in the cache might expire. But still, there is a window where the data in the cache is inconsistent with the database.

I have been searching for articles/research papers which speak about this kind of issues. But, I could not find any useful resources.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你另情深 2024-12-17 08:44:42

本文为您提供了有关 Facebook 如何(尝试)维护缓存一致性的有趣说明:http://www.25hoursaday.com/weblog/2008/08/21/HowFacebookKeepsMemcachedConsistentAcrossGeoDistributedDataCenters.aspx

以下是本文的要点。

  1. 我将我的名字从“Jason”更新为“Monkey”
  2. 我们将“Monkey”写入加利福尼亚州的主数据库,并从加利福尼亚州的内存缓存中删除我的名字,但不是弗吉尼亚州
  3. 有人访问我在弗吉尼亚州的个人资料
  4. 我们找到了我的 名字内存缓存中的名字并返回“Jason”
  5. 复制赶上,我们用我的名字“Monkey”更新从属数据库。 我们还从弗吉尼亚内存缓存中删除了我的名字,因为该缓存对象出现在复制流中
  6. 其他人访问了我在弗吉尼亚的个人资料
  7. 我们在内存缓存中找不到我的名字,因此我们读取从奴隶那里得到“猴子”

This article gives you an interesting note on how Facebook (tries to) maintain cache consistency : http://www.25hoursaday.com/weblog/2008/08/21/HowFacebookKeepsMemcachedConsistentAcrossGeoDistributedDataCenters.aspx

Here's a gist from the article.

  1. I update my first name from "Jason" to "Monkey"
  2. We write "Monkey" in to the master database in California and delete my first name from memcache in California but not Virginia
  3. Someone goes to my profile in Virginia
  4. We find my first name in memcache and return "Jason"
  5. Replication catches up and we update the slave database with my first name as "Monkey." We also delete my first name from Virginia memcache because that cache object showed up in the replication stream
  6. Someone else goes to my profile in Virginia
  7. We don't find my first name in memcache so we read from the slave and get "Monkey"
夏见 2024-12-17 08:44:42

使用内存缓存中保存的变量作为锁定信号怎么样?

从数据库检索数据后,每个内存缓存命令都是原子的

,将数据放入内存缓存后打开锁定

关闭锁定,检查锁定状态

,从数据库删除之前

How about using a variable save in memcache as a lock signal?

every single memcache command is atomic

after you retrieved data from db, toggle lock on

after you put data to memcache, toggle lock off

before delete from db, check lock state

殤城〤 2024-12-17 08:44:42

下面的代码展示了如何使用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

The code below gives some idea of how to use Memcached's operations add, gets and cas to implement optimistic locking to ensure consistency of cache with the database.
Disclaimer: i do not guarantee that it's perfectly correct and handles all race conditions. Also consistency requirements may vary between applications.

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
掌心的温暖 2024-12-17 08:44:42

当您阅读时,会发生以下情况:

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

When you read, the following happens:

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

When you write, the following happens:

1 delete/update data from db
2 clear cache
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文