Кэширование данных из базы данных MySQL - техника и соответствующий контейнер STL?

Я разрабатываю систему кэширования данных, в которой одновременно может храниться очень большое количество записей, и мне нужно знать, какой stl-контейнер использовать и как его использовать. Приложение заключается в том, что у меня есть чрезвычайно большая база данных записей для пользователей - когда они входят в мою систему, я хочу извлечь их запись и кэшировать некоторые данные, такие как имя пользователя и несколько важных свойств. Когда они взаимодействуют с системой, я обновляю и получаю доступ к их свойствам. Некоторые свойства очень изменчивы, и я делаю это, чтобы избежать «ударов» по ​​БД со многими транзакциями. Кроме того, мне редко нужно использовать базу данных для сортировки или чего-то еще - я использую это так же, как прославленный двоичный файл сохранения (поэтому я счастлив кэшировать записи в памяти ..); более важной целью для меня является возможность масштабирования для огромного количества пользователей.

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

Сервер хранит свои:

vector <UserData *> loggedInUsers;

С UserData сохраняются такие вещи, как имя пользователя (строка) и другие свойства из БД, а также другие временные данные, такие как сетевые дескрипторы.

Мой первый вопрос: если мне нужно найти конкретного пользователя в этом векторе, какой самый быстрый способ сделать это и есть ли другой контейнер stl, который я могу использовать, чтобы сделать это быстрее? Что я делаю сейчас, так это создаю итератор, запускаю его в loggedInUsers.begin() и итерирую до .end(), проверяя *iter->username == "foo" и возвращаясь, когда он найден. Если имя пользователя находится в конце вектора или если в векторе 5000 пользователей, это значительная задержка.

Мой второй вопрос: как я могу циклически планировать запись этих данных обратно в БД? Я могу вызывать функцию каждый раз, когда я готов записать несколько записей в БД. Но я не могу удерживать итератор в векторе, потому что он станет недействительным. Что я хотел бы сделать, так это иметь вращающуюся очередь, где я могу получить доступ к голове очереди, сохранить ее в БД, а затем повернуть ее, чтобы она стала концом очереди. Это похоже на много накладных расходов... какой тип я мог бы использовать, чтобы сделать это лучше?

Мой третий вопрос заключается в том, что я использую сервер MySQL и коннектор libmysqlclient / C. Есть ли какое-либо встроенное кэширование, которое могло бы решить эту проблему «бесплатно», или есть вообще другой метод? я открыт для предложений


person Nektarios    schedule 04.02.2011    source источник


Ответы (2)


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

А2. Список, вероятно, был бы для вас лучше — сдвиньте вперед, оторвите конец. (также можно использовать дек, но вы не можете сохранить итератор, если вы удалите из него, вы можете со списком). push_back и pop_front (или наоборот) позволят вам постоянно очередь кэшированных данных.

А3. Вы можете попробовать SQLite, мини-базу данных, предназначенную для простых потребностей в хранении баз данных на уровне приложений. Он также может работать полностью в памяти.

person gbjbaanb    schedule 04.02.2011
comment
А1: Спасибо. A2: Как насчет производительности pull/push, каждая операция будет предполагать, что я отбрасываю/добавляю совершенно новый элемент, верно? Есть ли какая-либо структура данных, которая просто «вращается»? A3: Несколько приложений могут попасть в БД. Более крупный дополнительный вопрос: A1 и A2 Я хочу объединить в одну вещь, чтобы я мог хранить все эти данные на карте и вращать их, чтобы сохранять обновления обратно в БД ... как я могу это сделать? - person Nektarios; 04.02.2011
comment
Извините, на A3 я понимаю, что вы предлагаете мне использовать SQLite в памяти в качестве структуры данных. Это было бы здорово на самом деле - person Nektarios; 04.02.2011

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

Тем не менее ... вам может быть лучше использовать карту (http://www.cplusplus.com/reference/stl/map/) с именем пользователя в качестве ключа.

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

person SteveMc    schedule 04.02.2011
comment
Спасибо, хороший совет, и вы правы, я мог бы лучше определить свое приложение. Мои данные малы, скажем, 64 байта, абсолютный максимум. Это означает, что в 1 ГБ ОЗУ у меня будет около 16 миллионов пользователей в памяти, так что это не проблема (сначала у меня закончатся дескрипторы сетевых сокетов). Мне нравится ваша идея просто держать указатели и смотреть, что вы имеете в виду с помощью shared_ptr - person Nektarios; 04.02.2011