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


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.