Нужно ли синхронизировать кеш? - PullRequest
3 голосов
/ 30 января 2009

Это кажется, пожалуй, наивным вопросом, но я вступил в дискуссию с коллегой, где я утверждал, что нет никакой необходимости в том, чтобы кэш был потокобезопасным / синхронизированным, поскольку я предположил бы, что это не имеет значения кто вводит значение, так как значение для данного ключа должно быть «постоянным» (в том смысле, что оно в конечном итоге исходит из того же источника). Если значения могут легко меняться, то сам кеш не кажется всем полезным (в том случае, если вам важно, чтобы значение было «текущим правильным», вам следует перейти к исходному источнику).

Основная причина, по которой я вижу, по крайней мере, синхронизацию GET, заключается в том, что если пропустить в кеше очень дорого, и вы не хотите, чтобы несколько потоков каждый выходили, чтобы получить значение для возврата в кеш. Даже тогда вам нужно что-то, что фактически блокирует всех потребителей во время цикла чтения-извлечения-вставки.

Во всяком случае, мое рабочее предположение состоит в том, что хеш по своей природе является поточно-ориентированным, потому что для любой комбинации {ключ, значение} значение является либо нулевым, либо чем-то, что не имеет значения, кто перейдет туда «первым» написать.

Вопрос: это разумное предположение?

Обновление: реальная область моего вопроса заключается в очень простых кэшах стилей id-> value (или {параметры} -> {вычисляемое значение}, где независимо от того, кто пишет в кеш, значение будет одинаковым, и мы просто пытаюсь спасти от «перерасчета» / возврата к базе данных. Фактический график объекта не имеет значения, а кэш, как правило, долговечен.

Ответы [ 5 ]

4 голосов
/ 30 января 2009

Для большинства реализаций хэша вам необходимо синхронизироваться. Что если хеш-таблицу нужно расширить / перефразировать? Что, если два потока пытаются добавить что-то в хеш-таблицу, где ключи разные, но хэши сталкиваются? Они оба могут одновременно модифицировать один и тот же слот в хеш-таблице. Предполагая, что вы используете хеш-таблицу для реализации своего кеша (что вы подразумеваете в своем вопросе), я предлагаю прочитать немного о том, как хеш-таблицы реализованы , если вы еще не знакомы с этим.

2 голосов
/ 30 января 2009

Пишет не всегда атомарно. Вы должны либо использовать атомарные типы данных, либо обеспечить некоторую синхронизацию (RCU, блокировки и т. Д.). Общие данные не являются поточно-ориентированными. Или избавьтесь от этого, придерживаясь алгоритмов без блокировок (то есть, где это возможно и возможно).

1 голос
/ 30 января 2009

Если вы хотите избежать повреждения данных, необходимо выполнить синхронизацию. Это особенно верно, когда кэш содержит несколько таблиц, которые должны обновляться атомарно. Представьте, что у вас есть база данных для DMV (отдел автомобилей). Вы добавляете в базу данных нового человека, у которого будут записи для автоматической регистрации плюс записи для билетов, полученных для записей для домашнего адреса, и, возможно, другая контактная информация. Если вы не обновите эти таблицы атомарно - в базе данных и в кэше - тогда любой клиент, извлекающий данные из кэша, может получить противоречивые данные.

Да, любой отдельный элемент данных может быть постоянным, но базы данных очень часто содержат данные, которые - если не обновляются вместе и атомарно - могут привести к тому, что клиенты базы данных получат неверные, неполные или противоречивые результаты.

1 голос
/ 30 января 2009

Пока стоимость приобретения и снятия блокировки меньше стоимости воссоздания объекта (из файла, базы данных или чего-либо еще), все обращения к кэшу действительно должны быть синхронизированы. Если это не так, вам вообще не нужен кеш. :)

0 голосов
/ 30 января 2009

Если вы используете Java 5 или выше, вы можете использовать ConcurrentHashMap. Это поддерживает несколько читателей и авторов в поточно-ориентированном виде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...