Замечательный сайт дающий ответ на вопрос “Should I be worried about scaling?” -
http://shouldibeworriedaboutscaling.info
Если кому было мало distributed cache-й, Microsoft строит свой - Velocity.
Релиза ещё нет, есть только несколько Community Technology Preview, но работы ведутся ударными темпами. У проекта есть
блог http://blogs.msdn.com/velocity и
форум http://social.msdn.microsoft.com/forums/en-US/velocity/threads
Трудно сказать зачем они это затеяли, может потому, что они всегда так делают, но вероятнее всего Microsoft продолжает строить свой software stack для Azure. Velocity = memcached, Dryad = Hadoop + Hive/Pig и т.д.
Но интересно не это, интересна архитектура проекта - наворотили знатно. Velocity умеет всё, умеет как memcached быть простым key-value со стандартным алгоритмом consistent caching и LRU вытеснением - так MS позиционирует Velocity для Web. А может быть сложным кешем с репликацией и гарантированной availability, со сложным routing, с transparent in-process cache с автоматическим обновлением локальных даных, умеет уведомления о изменеии состояния данных, умеет тэги и т.д. такое Velocity MS готовит для enterprise.
В общем, всё о чём можно только мечтать - Velocity умеет. На довесок - REST API, несколько видов упраления памятью, несколько видов блокировок (sic!), кворумы в репликации, failover, горячее добавлеие новых узлов.
Я просто терясь в догадках, зачем кешу всё это. Тут не хватает только disk persistence что бы построить non-sql DB который заткнёт за пояс всё что есть на сегодняшний день.
Замечательная PowerPoint презентация об архитектуре проекта - Project “Velocity”: Under the hood
И статья в MSDN http://msdn.microsoft.com/en-ca/library/cc645013.aspx
Правильный real-time мониторинг системы, дело не такое простое, как может показаться на первый взгляд.
Самый распространенный пример - измерение времени отклика сервера на запрос. Допустим у нас всё есть:
- сервер для каждого запроса вычисляет execution time, складывает в счётчик
- сервер умеет отдавать значение счётчика по внешнему запросу
- есть monitoring сервер который собирает значения каждый poll interval, хранит, агрегирует и рисует графики
Решение в лоб - измерять мгновенное значение счётчика - особого смысла не имеет, при poll interval в одну или пять минут, мы получим мгновенное значение производительности системы измеренное по последнему запросу. Если все 5 минут до этого исполнялись запросы по 2секунды или больше, а последний был легкий на 20ms мы увидим только 20ms. Или наоборот.
Стандартное решение - скользящее среднее по последним N запросам. Решение работает замечательно, пока N запросов выполняются за время меньшее poll interval. Если нагрузка падает, получается вот такое вот:

Между полночью и 4-мя часами утра либо не было запросов вовсе, либо было меньше N. Значение скользящего среднего не менялось и создаётся обманчивое впечатление, что сервер обрабатывал все запросы за 6ms.
Ниже, тот же счётчик, только с другого сервера где скользящее среднее было модифицировано.

Картина видна гораздо лучше. Видно где были запросы, а где не было.
Модификация довольно простая. Кроме параметра N - размера окна для скользящего среднего. Вводится ещё один параметр - T, время забывания (expiration time), все значения в окне, старше T не учитываются при подсчёте среднего.
Выбор T (ms) для данного значения poll interval (ms) - это другая интересная проблема.
Если T << poll interval, (много меньше) будут потерянные значения
Если T >> poll interval, (много больше) будет график #1
В первом приближении, можно принять T = 2 * poll interval
Это впечатляет - мост в Европу, дневной рост активности, и одинокие самолёты в южном полушарии…

Жили были item-ы и было у них sequential numeric id.
То, что оно sequential - это тяжелое наследие царского режима, потом пришли большевики, но ничего сделать было уже нельзя.
#0
И вот, при Николае-батюшке, было это autoincrement поле в MS SQL, item-ы получали id при вставке и никто горя не знал. Очевидно для того, что бы узнать это id на клиенте надо вставлять item-ы один за другим.
#1
Нагрузка возросла - власть поменялась, хостов баз данных стало больше одного, генерацию вынесли в отдельную таблицу. Простой инкремент. Продолжали вставлять один за другим.
#2
Нагрузка возросла - сделали вставку item-ов сразу пачками, а генерацию соответсвенно тоже поменяли, что бы генерировать сразу на всю пачку за один запрос. Стандартная hi-lo процедура (см ниже). Скажем, если вставляется 10 записей - один запрос на генерацию 10 ids.
#3
Нагрузка возросла - сделали пре-генерацию id наперёд блоками и кеширование этого блока на клиенте. Скажем, если вставляется 10 записей - один запрос на генерацию 1000 ids. 10 используются сразу, а 990 ждут следующего раза.
При порядка 700 витках (threads), которые всё время пишут в базу, эффект поразительный.

А вот если бы сесть и подумать, можно было бы сразу с последнего пункта начать…
hi-lo cхема выглядит так:
В догонку к CAP Theorem и availability
Обычные распределённые системы, RDBMS и J2EE контейнеры, целостность ставят во главу угла. Все эти фокусы с блокировками и распределенными транзакциями даются дорогой ценой. Эта цену большие распределенные системы платить не готовы, им нужно прежде всего availability. Поэтому Google, Amazon и некоторые другие крупные компании построили свои собственные инфраструктуры.
Werner Vogels, Amazon VP & CTO, популярно объясняет почему двух фазный коммит это плохой выбор если нужно строить scalable систему. Он ещё, ведет блог All things Distribtued для тех кому интересно.
Для того что бы система расширялась нужны асинхронные, stateless сервисы, а целостность приходится компенсировать сложными согласованиями-компенсациями в случае ошибок. Ну и конечно, модель данных оказывает существенное влияние на производительность. Чем проще - тем быстрее. Тут можно вспомнить про Dynamo от Amazon и MapReduce/BigTables от Google.
Полезная, для построителей распределенных систем CAP Theorem-а. Теорема о целостности, доступности и терпимости к разделению. Позволяет избежать изобретения велосипедов с квадратными колёсами.
CAP Theorem-а утверждает, что система может удовлетворять не более двум требованиям из трех: целостность (consistency), доступность (availability) и терпимость к разделению (partition tolerance).
Где:
целостность (consistency) - гарантирует, что все клиенты всегда прочтут одинаковые данные, в не зависимости к какому узлу в кластере они обратились. Операция записи атомарная для всех узлов.
доступность (availability) - гарантирует, что в в случае любого (разумного) отказа, клиенты все равно смогут получить доступ к копии их данных.
терпимость к разделению (partition tolerance) - гарантирует, что система остается работоспособной даже если авария сети приведет к образованию двух или более под-кластеров.
У этой теореме существует формальное доказательство. Работа 2002 года, ссылается на публикации конца 80-х начала 90-х.



