2013-09-13 2 views
3

мне нужен простая структура кэша (в питоне, но это на самом деле не имеет значения), с некоторыми специфическими требованиями:Оптимальный алгоритм кэша с истекает

  1. до нескольких миллионов мелких объектов (100 байт в среднем)
  2. Скорость является ключевым (как ставить и получить), я бы ожидать, время срабатывания при температуре около нескольких микросекунд
  3. только один поток доступа к этому - так это может быть всего лишь в памяти (не требуется настойчивость)
  4. Ключами являются хеширование MD5 (если это имеет значение)
  5. Там в момент истечения срока действия, глобальный для кэша - каждый ключ должен быть удален из кэша после истечения времени, считая с момента первым положить

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

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

Большинство ответов на эту проблему предлагают использовать memcached, но я думаю, что это будет пустой тратой процессора, тем более, что я сохраняю объекты, которые могут быть помещены в словарь по ссылке, но с использованием memcached они должны быть (de) сериализованная.

У меня есть идея, как реализовать это: разделите данные на временные фрагменты, имея на самом деле несколько словарей - например, если время истечения составляет 60 секунд, то у нас есть (самое большее) 4-е изд. И каждые 20 секунд мы добавляем новые один - где кладут новые ключи и удаляют четвертый - где у нас будут ключи, добавленные более 60 секунд назад. Это делает очистку очень быстро за счет времени восстановления, когда вам нужно искать в 4 словарях вместо одного (а использование ОЗУ - на 33%).

Итак, наконец-то вопрос - что есть: есть ли лучшее решение? Или, может быть, я ошибаюсь, и некоторые из упомянутых решений (удаление ключей один за другим) будут лучше и быстрее? Я не хочу изобретать велосипед, но не нашел хорошего решения в сети.

ответ

-1

Используйте службу таймера (расписание на Python?), Которая запускает событие через N секунд. Для каждого ключевого графика событие таймера (они довольно легкие) и удалите ключ.

Java-аналог является: http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html

+0

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

+0

в общем опросе гораздо менее эффективен, чем уведомление. в этом случае вы не только опросите один объект за его истечение, но и будете опросить все население. удачи! – necromancer

+0

, и вы можете использовать уведомление таймера без синхронизации в самом кэше. просто вставьте в него уведомления, а один поток один раз в то же время сбрасывает очередь и удаляет из очереди уведомленные объекты. я не вижу, как периодически проверять 1000 000 объектов, чтобы найти, что 1000 истекших объектов могут быть более эффективными, чем обработка 1000 удалений из очереди. вздох ... – necromancer

1

только эксперименты покажут вам, какой лучше.

Вот еще одна простая идея: соединить все ключи в связанном списке в порядке поступления. Каждый раз, когда вы извлекаете ключ, итерации с начала списка и удаления всех истекших элементов, как из списка, так и из словаря.

+0

Вы правы, я должен просто поэкспериментировать. Уже проверено, что извлечение из 4 словарей в порядке по-прежнему подходит ниже 1us, так что, вероятно, это путь. Но все еще интересно, кто-то уже создал подобную вещь. – kompas

0

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

Да, он может оставить элементы с истекшим сроком действия в хеш-таблице произвольно долго, но только O (N) элементов в среднем, где N - размер вашей хеш-таблицы.

Хорошие свойства этого подхода состоят в том, что одновременная очистка не происходит, а накладные расходы более или менее постоянны.

Вам нужно закодировать это на C, а не на Python, если вам нужна скорость.

Смежные вопросы