#caching #memcached #distributed-computing #race-condition #consistency
#кэширование #memcached #распределенные вычисления #состояние гонки #согласованность
Вопрос:
В этом семестре я изучал класс базы данных, и мы изучаем поддержание согласованности кэша между RDBMS и сервером кэша, таким как memcached. Проблемы с согласованностью возникают при наличии условий гонки. Например:
- Предположим, я выполняю a
get(key)
из кэша, и есть ошибка в кэше. Поскольку я получаю ошибку в кэше, я извлекаю данные из базы данных, а затем выполняю aput(key,value)
в кеш. - Но может возникнуть условие гонки, когда какой-либо другой пользователь может удалить данные, которые я извлек из базы данных. Это удаление может произойти до того, как я внесу a
put
в кеш.
Таким образом, в идеале put
в кэш не должно происходить, поскольку данные больше не присутствуют в базе данных.
Если запись в кэше имеет TTL, срок действия записи в кэше может истечь. Но все же есть окно, в котором данные в кэше несовместимы с базой данных.
Я искал статьи / исследовательские работы, в которых говорится о такого рода проблемах. Но я не смог найти никаких полезных ресурсов.
Ответ №1:
В этой статье приводится интересная заметка о том, как Facebook (пытается) поддерживать согласованность кэша: http://www.25hoursaday.com/weblog/2008/08/21/HowFacebookKeepsMemcachedConsistentAcrossGeoDistributedDataCenters.aspx
Вот суть статьи.
- Я обновляю свое имя с «Джейсон» на «Обезьяна»
- Мы записываем «Monkey» в главную базу данных в Калифорнии и удаляем мое имя из memcache в Калифорнии, но не в Вирджинии
- Кто-то заходит в мой профиль в Вирджинии
- Мы находим мое имя в memcache и возвращаем «Jason»
- Репликация догоняет, и мы обновляем подчиненную базу данных моим именем как «Обезьяна». Мы также удаляем мое имя из Virginia memcache, потому что этот объект кэша появился в потоке репликации
- Кто-то еще заходит в мой профиль в Вирджинии
- Мы не находим мое имя в memcache, поэтому мы считываем с ведомого устройства и получаем «Monkey»
Ответ №2:
Как насчет использования переменной save в memcache в качестве сигнала блокировки?
каждая отдельная команда memcache является атомарной
после извлечения данных из БД включите блокировку
после того, как вы поместите данные в memcache, отключите блокировку
перед удалением из БД проверьте состояние блокировки
Ответ №3:
Приведенный ниже код дает некоторое представление о том, как использовать операции Memcached add
gets
и cas
реализовать оптимистичную блокировку для обеспечения согласованности кэша с базой данных.
Отказ от ответственности: я не гарантирую, что он абсолютно корректен и обрабатывает все условия гонки. Также требования к согласованности могут различаться в разных приложениях.
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
Ответ №4:
При чтении происходит следующее:
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
Комментарии:
1. пожалуйста, объясните, как исправлены условия гонки, упомянутые в вопросе. ваш ответ, по-видимому, не решает проблему.