HighLoad.org – блог о высоких нагрузках
HighLoad.org > Серверы тикетов: дешевое распределение уникальных первичных ключей

Серверы тикетов: дешевое распределение уникальных первичных ключей
2010-02-19 19:21 my_fess 
Серверы тикетов не интересны сами по себе, но они являются важным блоком в построение Flickr. Главными темами о которых мы поговорим будет шардинг и мастер-мастер архитектуры. Серверы тикетов дают нам глобально (на Flickr) уникальные целые числа, которые являются первичными ключами в нашей распределенной системе.

Почему?

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

GUID?

Обычно когда нужно получить глобальные уникальные ID то возникает вопрос: почему не использовать GUID? В основном потому что GUID слишком большой, и в MySQL он индексируются плохо. Один из путей сохранения скорости в MySQL — индексация всего что хотим запрашивать, и мы делаем запросы только по индексам. Поэтому размер индекса является ключевым моментом. Если вы не можете хранить ваши индексы в памяти - вы не можете добиться чтобы база данных работала быстро. В дополнение к этому серверы тикетов предоставляют нам последовательность функций, которая обладает действительно классными свойствами включая создание отчетов и более прямолинейную отладку, и возможность включить некоторые трюки с кэшированием.

Согласованное хеширование?

Некоторые проекты, например такой как Amazon Dynamo предоставляют согласованное хеширующее кольцо поверх хранилища данных для обработки проблем с GUID/шардами. Это хорошо подходит для случая с дешевой записью, а MySQL оптимизирована для быстрого случайного чтения.

Централизация автоинкремента.

Если мы не можем сделать чтобы автоинкремент в MySQL работал сквозь несколько баз данных, почему бы нам не использовать одну базу данных? Когда кто-нибудь будет аплоадить новую фотографию - мы будем вставлять строку в эту одну базу данных и использовать это автоинкрементный ID из этой таблицы как первичный ключ для всех наших баз данных. Конечно с 60+ фотографиями в секунду эта таблица быстро станет большой. Мы можем избавиться от всех дополнительных данных о фотографии и хранить в центральной базе данных только ID. Даже в этом случае таблица станет неуправляемо большой очень быстро. И к тому же есть еще комментарии, отметки л понравившемся, посты в группах, теги и все это тоже требует ID .

REPLACE INTO

Немного более десяти лет назад MySQL поставлялась с нестандартным расширением REPLACE INTO к спецификации ANSI SQL. Позже появилось INSERT ON DUPLICATE KEY UPDATE и решило эту проблему намного лучше. Однако, REPLACE INTO все еще поддерживается.
REPLACE работает как INSERT, кроме того случая когда старая строка в таблице имеет такое же значение первичного ключа или уникального индекса как и новая строка, тогда старая строка удаляется прежде чем новая строка вставится.
Это позволяет нам автоматически обновлять единственную строку в базе данных, и получать новый увеличенный первичный ID.

Соберем все вместе.

Сервер тикетов на Flickr — это выделенный специально для базы данных сервер, с одной базой данных на нем, и в этой базе данных таблицы типа Tickets32 для 32-битных ID и Tickets64 для 64-битных ID. Схема Tickets64 выглядит примерно так:
CREATE TABLE `Tickets64`
(
`id` bigint(20) unsigned NOT NULL auto_increment,
`stub` char(1) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `stub` (`stub`)
)
ENGINE=MyISAM
Вызвав:
SELECT * FROM Tickets64
получим одну строку которая выглядит примерно так:
+-------------------+------+
| id | stub |
+-------------------+------+
| 72157623227190423 | a |
+-------------------+------+
Когда мне нужен новый глобальный уникальный 64-битный ID, я вызываю следующий SQL запрос:
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();

SPOF (Single point of failure)

Очень не желательно чтобы предоставляемые ID были бы единой точкой падения системы. Мы получаем высокую доступность запуском двух серверов тикетов. Репликация записи/обновления между серверами будет создавать проблемы, и блокировки убьют всю производительность сайта. Мы делим ответственность между двумя серверами разделением пространства ID поровну: в одном четные числа, а в другом нечетные:
TicketServer1:
auto-increment-increment = 2
auto-increment-offset = 1

TicketServer2:
auto-increment-increment = 2
auto-increment-offset = 2
Мы используем алгоритм Round-robin для распределения нагрузки между двумя серверами. Эти два сервера ведут себя не совсем синхронно, я думаю у нас на несколько сотен тысяч больше нечетных чисел чем четных в каждый момент времени, но это никому не мешает.

Больше счетчиков

На самом деле у нас больше таблиц чем Tickets32 и Tickets64 на сервере тикетов. У нас есть таблицы для фотографий, для аккаунтов, для оффлайновых заданий и для групп и тд. Оффлайновые задания имеют свою собственный счетчик, потому что мы уничтожаем многие из них и мы не хотим зазря увеличивать счетчики других вещей. Группы и аккаунты имеют их собственный счетчик, потому что у нас их относительно немного. Фотографии имеют их собственный счетчик, потому что нам надо было синхронизировать их с нашей старой таблицей с автоинкрементом и мы используем ID чтобы быстро узнавать сколько фотографий загружено.

Вот и все

Это не особо элегантный способ, но он работает потрясающе хорошо и мы выпустили его в продакшн в пятницу 13-того января 2006 года и это превосходный пример инженерного принципа разработки Flickr: можно использовать самую тупейшую вещь если она работает.

Автор статьи: Kellan Elliott-McCrea Дата: 8 февраля 2010 Оригинал статьи


комментарии [0]  | комментировать

  © 2010-2018 HIGHLOAD