Який алгоритм закінчення терміну дії елементів у сховищі ключових значень?


10

Я думав над тим, як поточні сховища ключових значень реалізують "термін дії" для предметів. На даний момент у мене на увазі два варіанти:

  1. вони нічого не роблять (зберігають дані про термін дії) та перевіряють лише тоді, коли ви робите, наприклад, GET за допомогою якогось ключа. Проблема тут полягає в тому, що якщо ви обмежуєте пам’ять, елементи з простроченим терміном не буде видалено.
  2. вони зберігають додаткові структури даних, щоб мати можливість "скоріше закінчитися". Я бачу, що це можна зробити так:

    storage_data = dict(key -> [value, expire_timestamp])
    expire_tree = SomeBinaryLikeTree(expire_timestamp -> [keys])
    

Відповіді:


6

Проблема видалення прострочених записів у кеш-пам'яті - це майже еквівалент збирання сміття , мінус ціла складність підрахунку посилань.

Люди в Nasza-Klasa запропонували алгоритм O (1) для Memcache наступним чином:

Схоже, багато людей чомусь вважали, що звільнення записів з минулим терміном не можна виконувати в O (1), або навіть, що для цього потрібні операції Omega (N). Використання купи даних чи інших структур пріоритетних черг очевидно може дати вам O (log N), але виправлення нижче спрямоване на O (1). Це досягається, маючи одне відро на кожну секунду, і додаючи кожен запис у відповідне відро, переглядаючи час закінчення терміну придатності. Потім на кожну секунду ми просто звільняємо елементи з наступного відра. Це, очевидно, O (1) амортизований час, але може статися, що у вас є багато елементів, які закінчуються в той самий момент, тому патч пропонує фіксовану межу для кількості операцій, які ви готові виконати за один запит, щоб сміття протікало більш гладко.

Переглянути всю пропозицію з доданим кодом .


Дякую. Я також розглядав "відро" рішення як один із способів. Крім того, немає жодної проблеми з "занадто великою кількістю предметів у відрі", оскільки ви можете піти з алгоритмом "візьміть відра, які ви не брали останній раз, і поверніться, коли закінчите".
Костянтин Рибников

@k_bx: тому вони пропонують подвійний список, щоб ви могли повернутися до попередніх версій.
vartec

Якщо відра - це щось на зразок секунд, то вам взагалі не потрібні пов'язані списки. Щоб перейти попередньо, ви просто зменшите клавішу :)
Костянтин Рибников

@k_bx: зменшити на скільки? одна секунда? що робити, якщо попереднє не повністю випорожнене відро було 5 хвилин тому? зменшення на крок 1s в 300 разів?
vartec

Під час першого запуску сервера ви ініціюєте змінну під назвою current_expire_bucket до деякого значення. Потім ви запускаєте очищення, починаючи з current_expire_bucket, закінчуючи поточну секунду. Після закінчення очищення ви спите якийсь невеликий період. Якщо сервер зупиняється, ви знову пройдете те саме "відмінне відро", але так це має відбуватися лише на зупинках сервера.
Костянтин Рибников

7

Я припускаю, що сховище ключа-значення є занадто великим, щоб просто перебирати всі kv-пари, щоб дізнатися, який термін дії може закінчитися. Я також припускаю, що кожен доступ для читання оновлює часову позначку терміну придатності, тому втрачають чинність лише ті елементи, до яких не було доступно протягом певного часу.

Завдання полягає в тому, щоб ефективно знайти всі записи, термін дії яких може закінчитися (щоразу, коли відбудеться очищення), а також ефективно оновити часову позначку терміну дії для кожного доступу для читання (тому ми повинні знайти ключ у структурі, що використовується для закінчення терміну дії).

Моя пропозиція: груповий термін дії відміток у відра; Наприклад, якщо предмети живуть 8 годин, робіть одне відро на годину. Ці відра зберігаються у пов'язаному списку; коли термін придатності відбувається, перше відро спорожняється, а список зменшується. Кількість відра - інтервал життя / очищення. Кожне відро містить хеш-набір усіх ключів, термін дії яких закінчився. Ітерація над усіма ключами хештету досить ефективна.

Під час доступу для читання програма перевіряє, в якому відрі знаходиться ключ, і до якого відра тепер належить. У більшості випадків це одне відро, тому подальших дій не потрібно. В іншому випадку вийміть ключ зі старого відра (вилучення з набору хешів є ефективним) та вставте його у нове відро.

   +--------------+   +--------------+   +--------------+
-->+ Expiry 08:00 +-->+ Expiry 09:00 +-->+ Expiry 10:00 +
   | KeySet       |   | KeySet       |   | KeySet       |
   +--------------+   +--------------+   +--------------+
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.