akalend
@akalend
программирую

как лучше организовать контейнер для хранения IP адресов (1-3Mb)

для организации кеша IP адресов нужно готовое решение или эффективный алгоритм быстрого доступа к данным ( что-то типа хеш таблиц)
данные могут устаревать, необходимо хранить время последнего доступа.
должно быть предусмотрена чистка или вытеснение не актуальных данных
что в этом случае лучше?
частота обращения высокая (200-300 запросов в сек)!

решение должно быть похожим на мемкеш
быстрым и эффективным!

вход IP — 32-bit число
выход — не более 64 байт — данные фиксированного размера
доп параметр — время доступа

Цель — проверить время последнего доступа.

возможные варианты:
1)
не хотелось бы для вытягивания информации об IP, сканировать всю таблицу адресов.
в этом случае вставка нового IP — вставка в пустой слот данных, вместо первого просроченного слота.
2)
упорядочивание по IP из-за высокой частотностностью обращения не подходит (а может подходит???).
ищем IP методом половинных делений. Если не нашли — вставляем. Какую модель хранения слотов использовать в этом случае?
3)
организовавыть очередь по времени доступа — получается скан всей (части начинающейся с первого не просроченного IP — до него — метод половинных делений) таблицы адресов.
дописываем в конец.

какие есть еще варианты????
  • Вопрос задан
  • 2744 просмотра
Пригласить эксперта
Ответы на вопрос 8
@Dervish66
К одним и тем же данным Вам нужно обращаться двумя способами. Один способ — по IP, второй — по времени доступа. При этом необходимо чтобы поиск изменения в данных (смена IP в слоте данных и смена времени доступа) выполнялись быстро и эффективно.

Я бы решал эту задачу отделив сами данные (массив слотов) от индексов, через которые нужно обращаться. Если брать реализацию на С++ то примерно вот так:

// Описатель слота данных
struct CDataItem {
    __int64 accessTime; // Любое представление времени
    DWORD ip;
    BYTE  userData [64];
};

// Индекс по IP
std::map<DWORD, CDataItem *> ipIndex;

// Индекс по времени доступа
std::map<__int64, CDataItem *> accessIndex;

// Память для хранения массива слотов
CDataItem * dataArray = new CDataItem[32000];

При этом, конечно, после каждого изменения (обновления) слота придется обновлять индексы.
Ответ написан
amc
@amc
Не забывайте что IP адрес прекрасно представляется как 4-байтное число.
Ответ написан
outself
@outself
Для быстрого поиска, как индекс, можно использовать Фильтр Блума ( en.wikipedia.org/wiki/Bloom_filter )

И Chrome использует фильтры Блума для предварительной оценки того, является ли веб-сайт вредоносным. На практике, — Компактное хранение миллиона адресов в ~ 18-ти мегабайтах.
Ответ написан
@Dervish66
Вряд ли найдется контейнер, который обеспечивал бы эффективный доступ к данным сразу по двум индексам. Зато вместо std::map можно использовать что угодно, например, сбалансированные деревья, тем более что код будет писаться на С. Главная идея моего предложения — разнести индексы и сами данные. Тогда издержки на поиск слотов, вставки слотов и апдейтов индексов можно постараться свести к минимуму.

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

Обновление индекса можно сделать через удаление индексной записи и добавление новой.
Ответ написан
@shsmad
а чем собственно не подошел описаный вами же memcached?
Ответ написан
eternals
@eternals
Если типовые инструменты нельзя использовать, то постройте простейшее бинарное дерево. Лочить при перестроении отдельные ноды.
Ответ написан
catap
@catap
Смесь LRU кеша и какого-нибудь radix32 дерева
Ответ написан
akalend
@akalend Автор вопроса
программирую
заинтересованным, решил делать так:

поиск по IP структура в виде b-Tree
далее проверка на время
времена хранятся в ввиде обратного списка
вытесняется самый последний в очереди.

При обновлении IP — переносим значение эл-та в конец списка.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы