OrmHate
Бля, три раза повторить, что есть очень реальная проблема, и ни разу не объяснить, что же эта за проблема. Почему в памяти нельзя effectively работать с реляционными структурами?Потому что если Фаулер будет писать об удобстве РСУБД, его не позовут выступать на конференции - у хипстеров NoSQL в моде.
и еще причем тут "in-memory/relational mapping problem"? Если я размещу базу на RAM диске, проблема исчезнет?
Если такая прослойка есть, то появляется проблема mapping-а, а если нет, то тогда не будет реляционности.
не будет реляционности.во всех языках есть простые незамороченные структуры для набора кортежей. Откуда проблема?
и еще причем тут "in-memory/relational mapping problem"? Если я размещу базу на RAM диске, проблема исчезнет?Достаточно создать все таблицы с опцией NOLOGGING - и сразу все станет in memory, и все проблемы исчезнут, Фаулер одобряет!
во всех языках есть простые незамороченные структуры для набора кортежей. Откуда проблема?это не будет реляционкой.
это не будет реляционкой.Это будет
http://martinfowler.com/articles/lmax.html
В этой статье он описывает разработку какой-то велосипедной СУБД на джаве (СУБД однопользовательская, как sqlite, и без транзакций - sqlite с транзакциями). В процессе описания устройства этой велосипедной СУБД он упоминает реализованный в ней redo log и чекпоинты, которые есть в любой СУБД, включая sqlite, но подносит это своим читателям как какую-то совершеннейшую новинку. Возникает мысль, что Фаулер не в курсе устройства типовой СУБД.
Это будет in-memory структурами языка, которые не вызывают проблем мепинга на реляционную модель. Все счастливы?
С маппингом у тебя проблем не будет, а вот с производительностью — та да. И ты будешь несчастлив, и все люди использующие твою шнягу будут несчастливы, и, как указал классик, каждый по-своему.
Надо ли рассказать про разницу между Relational Algebra and Relational Calculus, или ты, как видный специалист в нафигачивании обёрток над скул, может быть знаешь?
есть простые незамороченные структуры для набора кортежейА почему все считают, что РСУБД могут возвращать только тупой набор кортежей? Вообще говоря, sql запрос может возвращать произвольное дерево:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/expres...
Ну это очень нечестивое извращение над SQL которое никакого отношения не имеет к математической основе.
С маппингом у тебя проблем не будет, а вот с производительностью — та да. И ты будешь несчастлив, и все люди использующие твою шнягу будут несчастливы, и, как указал классик, каждый по-своему.Алё, ты о чём? Я говорю про вот это:
while (dataReader.Read {
IMyTupe myTupe = dataReader.Materialize<IMyTupe>
}
Тут потерь производительности просто НЕТ, т.е. производительность максимальная. При этом данные уже в in-memory структуре языка.
видный специалист в нафигачивании обёрток над скул
Опять алё, ты на своей волне? Я тут всё время проповедую работу с чистым SQL, а ты мне приписал какие-то обертки.
Возникает мысль что ты просто не сталкивался с задачами (и требованиями к производительности и особенно времени отклика где могут потребоваться такие "велосипеды", вот и не оценил. У нас подобный "велосипед" сделали в двух ипостасях за последние лет 5, активно используем во всех новых проектах:Ты прав, я не сталкивался с такими задачами. Вполне допускаю, что в вашем случае это было абсолютно оправданным решением. Но Фаулер явно пишет, что мотивацией создания своей СУБД было не беспокойство о производительности, а нелюбовь к традиционным СУБД:
The second advantage is that it simplifies programming - there's no object/relational mapping to do. All the code can be written using Java's object model without having to make any compromises for the mapping to a database.
...
There's usually a non-trivial effort that goes into the relationship with the database. Object/relational mapping tools can help much of the pain of dealing with a database, but it doesn't deal with it all. Most performance tuning of enterprise applications involves futzing around with SQL.
Рассуждения о перформанс характеристиках полученной системы вызывают недоумение:
Firstly it's fast - there's no database to provide slow IO to access, nor is there any transactional behavior to execute since all the processing is done sequentially.
Признание того, что полученная система нетранзакционна, не мешает Фаулеру в дальнейшем измерять ее производительность в транзакциях в секунду:
6 million TPS
Возникает мысль что ты просто не сталкивался с задачами (и требованиями к производительности и особенно времени отклика где могут потребоваться такие "велосипеды", вот и не оценил.что за требования?
В процессе описания устройства этой велосипедной СУБД он упоминает реализованный в ней redo log и чекпоинты, которые есть в любой СУБД, включая sqlite, но подносит это своим читателям как какую-то совершеннейшую новинку.
Прочитал статью, познавательно. Тебя не затруднит процитировать место, где автор "подносит это своим читателям как какую-то совершеннейшую новинку"?
Прочитал статью, познавательно. Тебя не затруднит процитировать место, где автор "подносит это своим читателям как какую-то совершеннейшую новинку"?Фаулер не указывает, что такой подход применяется во всех имеющихся СУБД, и одновременно противопоставляет описываемую систему этим самым СУБД. У несведущего читателя должно сложиться впечатление, что это новинка.
только тупой набор кортежей?в этом и есть сила реляционки
The 6 million TPS benchmark was measured on a 3Ghz dual-socket quad-core Nehalem based Dell server with 32GB RAM.Для понимания на сколько это круто.
Текущий рекорд для РСУБД : ~500,000 TPS
Получен на
CPU Type: Oracle SPARC T3 - 1.65 GHz
Total # of Processors: 108
Total # of Cores: 1728
Total # of Threads: 13824
Для понимания на сколько это круто.К сожалению, это разные TPS.
Почему-то топикстартеру не поставили 100500 плюсов. Минусуют, конечно же, профнепригодные.
Например:эта статья вообще не о СУБД
http://martinfowler.com/articles/lmax.html
В этой статье он описывает разработку какой-то велосипедной СУБД
ваш КО
Да-да. Это как один мой знакомый, узнав, как в общих чертах устроен поиск Яндекса сказал: "ну и велосипедисты, купили бы просто кластер Oracle побольше, деньги ведь есть".
эта статья вообще не о СУБДОднако слово database в ней упомянуто 15 раз.
Однако слово database в ней упомянуто 15 раз.зато слово Disruptor там упомянуто 32 раза (в любом случае, странный у тебя алгоритм чтения статьи). в нем как раз вся соль
эта статья об устройстве торговой платформы и ее архитектуре, а мимо database автор не мог пройти, т.к. это довольно важная составляющая любой сложной системы, в частности, торговой. умолчать о ней - значит, проявить свою некомпетентность
К созданию LMAX'а Фаулер отношения не имеет. К базам данных LMAX имеет весьма посредственное отношение. Единственное сходство - и там и там используется термин транзакции.
Транзакции в LMAX соответствуют определению. Поясню процитированный кусок про transactional behaviour. Если ты вдруг не уловил, то вся бизнес логика со всем стейтом у них крутится в одном треде. За счет этого они избавились от всех синхронизаций в своем бизнес коде, и неожиданно получили столько попугаев, сколько получили. Именно поэтому же для обеспечения транзакционности им не надо париться об изоляции, резолюции дедлоков и пр.
Сам проект, вообще, считается самой быстрой трейдинговой платформой в мире.
А тем не менее, материал годный. ORM — самое большое зло.ORM, я смотрю, стало модно ругать. Так же, как, примерно, майкрософт с виндовсом. Выругался, и всем сразу вокруг понятно стало, какие они неудачники, сидящие на виндовс/орм.
То, что у виндовса/орм есть своя область, в которой оно отлично справляется, это товарищи эксперты неJava-архитекторы, конечно, не учитывают.
То, что само использование термина ORM некорректно, так как каждый программист на объектном языке, обращающйся к RDBMS, вынужден так или иначе решать проблему ORM, судя по всему таким кричащим уже невдомек...
так как каждый программист на объектном языке, обращающйся к RDBMS, вынужден так или иначе решать проблему ORM,Часто эта проблема никак не решается, и ОО-код работает с базой в недореляционной парадигме, оперируя коллекциями структур. Маппинг множества кортежей на коллекцию структур никакой объектности еще не добавляет.
ОО-шность появляется когда на ОО-код приходится мапить связи между таблицами, чем обычно занимаются уже тяжелые ORM-framework-и: Hibernate, EF и т.д.
myObj.setName(resultSet.getString("name";
входит в ORM. Да, пускай это самая примитивная часть, но энивей.
А так я с тобой согласен. Но вот пианист напианистил не уточнив, что именно ему не нравится в ОРМах, поэтому его точку зрения я, скажем так, не разделяю.
К базам данных LMAX имеет весьма посредственное отношение.Однако, Фаулер сравнивает этот LMAX с СУБД:
Most business systems these days have a core architecture that relies on multiple active sessions coordinated through a transactional database. The LMAX team were familiar with this approach, and confident that it wouldn't work for LMAX.
Транзакции в LMAX соответствуют определению.
Нет, для транзакций нужен ACID, а в рассматриваемой системе отсутствует A, а наличие D вообще не рассматривается в статье. Так ты можешь про любую программу без concurrency сказать, что в ней есть транзакции.
Сравнивает. И говорит, что это разные вещи.
> Нет, для транзакций нужен ACID, а в рассматриваемой системе отсутствует A, а наличие D вообще не
> рассматривается в статье. Так ты можешь про любую программу без concurrency сказать, что в ней есть
> транзакции.
Вообще, понятие транзакций немного более старое, чем ACID.
Тем не менее, к D как раз относится redo log, там про это все чуть ли не в самом начале статьи написано.
Atomicy в статье не обсуждается, но никто не говорит, что его там нет.
Concurrency в LMAX, если ты не заметил, тоже есть. Просто она не там, где ее ожидают увидеть твои заточенные на RDBMS мозги.
Собственно, весь смысл статьи в том, чтобы показать, как клево они этот конкарренси устроили. То, что они сделали, действительно не имело аналогов.
Вообще, у меня впечатление, что статью ты прочитал по диагонали, но "авторитетное мнение" сформировал. А жаль, остальные твои посты мне нравились...
Вообще, у меня впечатление, что статью ты прочитал по диагонали, но "авторитетное мнение" сформировал. А жаль, остальные твои посты мне нравились...+1
Atomicy в статье не обсуждается, но никто не говорит, что его там нет.
Именно что обсуждается, и Фаулер явно говорит, что ее там нет.
Тем не менее, к D как раз относится redo log, там про это все чуть ли не в самом начале статьи написано.Redo log не гарантирует durability. В тех же самых РСУБД ты можешь указывать, чтобы запись в redo log шла асинхронно, при этом транзакция теряет свойство durability.
Более того, легко сделать вывод, что durability там нет. Как пишет Фаулер, система обрабатывает 6 млн запросов в секунду. Тебе известны жесткие диски, которые могут записывать 6 млн. раз в секунду? Тем более, как пишет Фаулер, система работает на commodity hardware. Можно конечно писать на диск большими группами, но тогда можно забыть про якобы имеющуюся super low latency.
Цитату, пожалуйста.
> Redo log не гарантирует durability. В тех же самых РСУБД ты можешь указывать, чтобы запись в redo
> log шла асинхронно, при этом транзакция теряет свойство durability.
И какой там пефоманс в полностью синхронном режиме?
> Тебе известны жесткие диски, которые могут записывать 6 млн. раз в секунду?
SSD.
> Более того, легко сделать вывод, что durability там нет.
: sigh :
В инпутном дизраптере заводим читателя, который читает все подряд, и пишет это на винт. Запись последовательная, в один поток. При 6m tps мы таким образом на современных commodity ssd имеем возможность писать порядка 100 байт на одну транзакцию. Cхема легко параллелится на большее кол-во винтов.
В аутпутном дизраптере таким же макаром, если очень нужно, можно логать, что ушло.
Если клиентам нужен acknowledge на их "коммиты" в LMAX, то и это можно устроить, добавив новый поток в инпутный дизраптер, который будет бежать за писателями в журнал и слать acknowledge'и
Все, на что мы ответили acknowledge'м, будет гарантированно в журнале, и "durability" таким образом гарантировано.
Род проблем, который остается - это что если сообщение из аутпутного дизраптера ушло, в лог попасть не успело, и тут нас выключили. Или в журнал мы евент записали, акноледж послать не успели, и тут нас выключили. Но такого рода проблемы никаким суперсинхронным io ни в каких супер rdbms не решаются.
Самое плохое, что может при этом случиться - какие-то сообщения уйдут больше одного раза.
Вообще, предлагаю тебе писать сразу Фаулеру. Ну или в LMAX. Будешь им рассказывать, как у них на самом деле ничего не работает.
Тут разница в понимании области проблемы. Мне вот кажется, что та часть, которая избавляет от проблемы написания кучи строчек типаЗачем писать эти строчки? В динамических языках, в том числе на C# 4.0, можно писать так:
myObj.setName(resultSet.getString("name";
входит в ORM. Да, пускай это самая примитивная часть, но энивей.
resultSet.name
Проблема остается? Какая? ORM нужен?
И какой там пефоманс в полностью синхронном режиме?Ты сначала намекаешь, что синхронный коммит тормозит, а потом доказываешь, что в LMAX синхронный коммит для 6000000 транзакций в секунду, и все работает зашибись. Ты сначала определись со своей точкой зрения, чтобы я смог ответить на твой вопрос.
Проблема остается? Какая? ORM нужен?То есть ты, который стремится все свои проблемы решить через строгую типизацию, предлагаешь для всех модельных объектов юзать класс ResultSet?
Мне действительно начинать перечислять минусы такого подхода, или ты пошутил?
> Именно что обсуждается, и Фаулер явно говорит, что ее там нет.
Цитату, пожалуйста.
A second feature of the programming model lies in error handling. The traditional model of sessions and database transactions provides a helpful error handling capability. Should anything go wrong, it's easy to throw away everything that happened so far in the interaction. Session data is transient, and can be discarded, at the cost of some irritation to the user if in the middle of something complicated. If an error occurs on the database side you can rollback the transaction.
LMAX's in-memory structures are persistent across input events, so if there is an error it's important to not leave that memory in an inconsistent state. However there's no automated rollback facility. As a consequence the LMAX team puts a lot of attention into ensuring the input events are fully valid before doing any mutation of the in-memory persistent state. They have found that testing is a key tool in flushing out these kinds of problems before going into production.
в цитате про rollback, а не про ACID
Утверждение "для durability необходима синхронность и/о", к твоему сожалению, справедливо только в твоем мире.
Слушай, серьезно, мне не хочется ругаться и что-то доказывать человеку, который просто не потрудился прочитать/осмыслить прочитанное.
Ну правда. Пожалуйста, если ты хочешь продолжать дискуссию, у нас получится лучше, если ты будешь уверен, что ты из своей ссылки до конца переварил и понял раздел "Input and Output Disruptors". В качестве бонуса можно дотошно прочитать и попробовать осмыслить "Queues and their lack of mechanical sympathy" - сразу скорей всего не получится, но оно того стоит.
"However there's no automated rollback facility." != no atomicy
Утверждение "для durability необходима синхронность и/о", к твоему сожалению, справедливо только в твоем мире.То есть, по твоему, можно отправить диску асинхронный запрос на запись, не дожидаясь ответа сообщить клиенту, что транзакция прошла, и это будет называться durability?
"However there's no automated rollback facility." != no atomicy
Что тогда, по твоему, atomicity?
То есть, по твоему, можно отправить диску асинхронный запрос на запись, не дожидаясь ответа сообщить клиенту, что транзакция прошла, и это будет называться durability?как вариант, можно транзакции кидать на диск пачками и так же пачками слать сообщения, что транзакция прошла.
> Что тогда, по твоему, atomicity?
что есть только два состояния: либо транзакция применилась, либо не применилась. И что отсутствует вариант частичного применения транзакции.
При фиксации изменений в самом конце - atomicity достигается без необходимости реализовывать rollback
При фиксации изменений в самом конце - atomicity достигается без необходимости реализовывать rollbackНапример, ты вычислил, что по результатам запроса надо обновить переменную foo, и заменить в массиве bar элемент по индексу 20.
foo = 100;
bar[20] = 200;
Внезапно оказывается, что мы где-то налажали, и в массиве bar всего 10 элементов. В результате foo обновлено, а bar нет, потому что вылетел эксепшен.
как вариант, можно транзакции кидать на диск пачками и так же пачками слать сообщения, что транзакция прошла.Я про это и писал, но при этом страдает latency. Записать 6 000 000 раз в секунду не может даже SSD диск ( ошибается на 3 порядка).
ORM — самое большое зло.По традиции, надо начинать с "ООП - зло", потом переходить к ORM.
Я про это и писал, но при этом страдает latency. Записать 6 000 000 раз в секунду не может даже SSD диск ( ошибается на 3 порядка).если на диск писать пачками по 50тыс. записей, то в latency - 1мс оно как раз вполне уложится
при этом это будет всего 120 операций/сек ввода/вывода на диск
> сообщить клиенту, что транзакция прошла, и это будет называться durability?
Почему бы и нет?
Учитывая, что у них там еще и горизонтальная избыточность железа, то можно даже и на это забить, а в случае сбоя в асинхронной записи просто переключаться на реплику.
For our performance critical journal based storage we use 15k SAS raid with battery backed write cache.
> Записать 6 000 000 раз в секунду не может даже SSD диск ( ошибается на 3 порядка).
Даже десктопные ssd сейчас обладают iops'ом в ~100k при нагрузке последовательной записью 4к блоков.
Всякие pcie решения - уже около 250к. Есть и дедикейтед штуки под 1m-6m.
Но, в целом, делать 6 млн отдельных операций на запись совсем не требуется. Давай прикинем на салфетке.
Берем десктопный ssd с 100k iops на sequential write. Блоки по 4к.
Нужно прикинуть, сколько места надо на журналирование одного элемента. К сожалению, тут будем тыкать пальцем в небо, но, думаю, 400 байт неплохая прикидка - туда и строковые идентификаторы приличной длины поместятся, и таймстемпы, и uuid'ы, и много еще чего.
Итого, на одном диске мы имеем 1m элементов в секунду. Ставим 6 ssd. Параллелится это элементарно - disruptor может держать читателя, который будет читать только каждую 6-ую запись в инпуте. Батчинг тоже там есть.
Прикидываем latency. С 100k iops, одна запись занимает 10 микросов. Вот тебе и все "latency" на журналирование.
Возникает нетривиальный вопрос. А что же у rdbms? Почему они тогда так не могут? В общем-то, я не ради подколки про пефоманс рдбмс спросил, а в надежде услышать какие-то цифры.
Но я, действительно, могу предположить, почему rdbms так не могут. Потому что у них вся транзакция от начала до конца обрабатывается в одном треде, и работа с журналом в нем же. Соответственно, если у нас синхронная буферизованная запись, то есть всем тредам приходится как минимум синхронизироваться для записи в буфер, что уже есть нехилый contention, потом ждать пока буфер набьется, етц...
Именно эту часть и решает дизраптор. Буфер набивается параллельно, без contention'a и ожидания.
Проблема остается? Какая? ORM нужен?Этими вопросами я хотел выяснить, если на минуту забыть о проблемах отсутствия статической типизации, какие-нибудь еще проблемы остаются?
То есть ты, который стремится все свои проблемы решить через строгую типизацию, предлагаешь для всех модельных объектов юзать класс ResultSet?
Мне действительно начинать перечислять минусы такого подхода, или ты пошутил?
Для статической типизации решением является вот такой extension метод к resultSet-у:
IX x = resultSet.Materialize<IX>
interface IX
{
string name { get; }
}
Алгоритм метода Materialize крайне прост:
public static T Materialize<T>(this ResultSet resultSet)
{
создаем объект obj типа T
для каждого проперти p из набора пропертей данного типа T
obj.p =
если проперти p типа String, то resultSet.getString(PropertyName)
если проперти p типа int, то resultSet.getInt(PropertyName)
и т.д.
return obj;
}
Ок. Поздравляю, вы только что написали yet-another ORM...
Ок. Поздравляю, вы только что написали yet-another ORM...У меня это несколько десятков строк кода. Где "the , the "?
but you don't have to deal with the full experience of writing that stuff (the , the ).
http://martinfowler.com/bliki/OrmHate.html
С какой корыстной целью ты хочешь, чтобы кто-то дал тебе очевидный ответ? Мы это даже лично с тобой уже обсуждали...
The object/relational mapping problem is hard. Essentially what you are doing is synchronizing between two quite different representations of data, one in the relational database, and the other in-memory. Although this is usually referred to as object-relational mapping, there is really nothing to do with objects here. By rights it should be referred to as in-memory/relational mapping problem, because it's true of mapping RDBMSs to any in-memory data structure. In-memory data structures offer much more flexibility than relational models, so to program effectively most people want to use the more varied in-memory structures and thus are faced with mapping that back to relations for the database.
The mapping is further complicated because you can make changes on either side that have to be mapped to the other. More complication arrives since you can have multiple people accessing and modifying the database simultaneously. The ORM has to handle this concurrency because you can't just rely on transactions- in most cases, you can't hold transactions open while you fiddle with the data in-memory.
so to program effectively most people want to use the more varied in-memory structuresчестно не понимаю что он подразумевает под "to program effectively"? Покажите мне это ЭФФЕКТИВНОЕ ПРОГРАММИРОВАНИЕ с использование varied in-memory structure. Такое что, если мы убираем varied in-memory structure, то получаем НЕЭФФЕКТИВНОЕ ПРОГРАММИРОВАНИЕ.
можно вспомнить банальный массив, к которому доступ по ключу занимает O(1 а для реляционных данных доступ по ключу O(log n)
можно вспомнить банальный массив, к которому доступ по ключу занимает O(1 а для реляционных данных доступ по ключу O(log n)Кто мешает из пришедшего из базы IEnumerable делать ToDictionary/ToLookup/ToArray/ToList? Судя по примерам, Фаулер под термином "varied in-memory structure" понимает разветвленный граф объектов с применением кучи видов разнообразных структур, см. документацию по Hibernate. Например, зачем класс Customer должен иметь филд orders, см. тут?
Я это к тому, что проблема не на границе [реляционная база]<->[объекты в памяти], а чисто в памяти [объекты в памяти]<->[объекты в памяти]. Причем "объекты в памяти" это не какие-то Доменные Объекты, это объекты языка C#/Java/Ruby, и живут они по законам C#/Java/Ruby, а не по Доменным Законам. Нет никакого Домена, это всё выдумки, которые усложняют программирование. Проблема же [объекты в памяти]<->[объекты в памяти] сугубо проблема выразительности языка. После выхода 3-ей версии языка C# это проблема стала мало заметна.
Кто мешает из пришедшего из базы IEnumerable делать ToDictionary/ToLookup/ToArray/ToList?Тут еще вот что важно. Как правило, получаемые Dictionary/Lookup/Array/List это read only коллекции. Когда требуется реализовать какой-нибудь итерирующий алгоритм, вначале делаешь Dictionary, и используешь его, а когда алгоритм отработал просто оставляешь Dictionary сборщику мусора. Потом при необходимости создаешь новый Dictionary.
Получается реляционная модель в памяти (с некоторыми отличиями от реляционной базы). Получаем простоту модели — набор отношений. А вспомогательные структуры для производительности идут отдельно, также как в базе индексы идут отдельно от отношений. Отличие в том, что индексы обновляются сами автоматически незаметно для пользователя. А в памяти мы создаем "индексы" по требованию каждый раз (или почти каждый). Время затрачиваемое на пересоздание "индексов" не существенно, поскольку в память выгружаются из базы небольшие коллекции.
The mapping is further complicated because you can make changes on either side that have to be mapped to the other. More complication arrives since you can have multiple people accessing and modifying the database simultaneously. The ORM has to handle this concurrency because you can't just rely on transactions- in most cases, you can't hold transactions open while you fiddle with the data in-memory.Понимание и реализация нормального coarse-grained lock проще на обычных объектах без ORM. Управление параллельным доступом это отдельно стоящая задача, зачем тут ORM? Управление параллелизмом от ORM это просто слезы.
Ты столько всего написал, что нужно сделать, чтобы не было "the , the ", что мне уже самому страшно...
Ты столько всего написал, что нужно сделать, чтобы не было "the , the ", что мне уже самому страшно...ну до фаулеровского словоблудия мне еще далеко
Прикидываем latency. С 100k iops, одна запись занимает 10 микросов. Вот тебе и все "latency" на журналирование.Это неверное рассуждение. IOPS и latency это отдельные характеристики. Вообще, 10 мкс - это время, которое требуется чтобы сделать один контекст свитч.
Возникает нетривиальный вопрос. А что же у rdbms? Почему они тогда так не могут?
Погугливая инфу по Разрушителю, я наткнулся на такую статью:
http://habrahabr.ru/post/130113/
На прошлой неделе компания LMAX, где я работаю, получила приз Java Duke's Choice Award 2011 за фреймворк Disruptor.
...
Чтобы добиться скорости исполнения более 10 тысяч операций в секунду, LMAX разработали паттерн Disruptor.
Оказывается, 6 миллионов транзакций в секунду существовали только в мокрых мечтах джава-архитекторов. На деле, полученного перформанса можно было достичь на open source СУБД, с нормальными транзакциями, бэкапом, recovery и миграцией данных.
На самом деле, существуют и полноценные однотредные in-memory БД, например http://en.wikipedia.org/wiki/VoltDB.
Производительность - 50000 TPS на одной ноде, при этом используется специально адаптированный под особенности данной СУБД бенчмарк TPCC:
http://blog.voltdb.com/695k-tps-nodejs-and-voltdb/
Обращаю внимание, что доступен код бенчмарка, который действительно можно запустить и посмотреть, а не заверения типа "мы тут такой паттерн зафигачили, ну в общем оракл соснул, там спинлоки и из-за них все тормозит, инфа 100%, и сиквель изучать надо".
Сравнивая, например, с
http://rhaas.blogspot.ru/2012/04/did-i-say-32-cores-how-abou...
и принимая во внимание некоторые особенности voltdb (доступ только через хранимые процедуры, невозможность огранизовать длинную транзакцию, необходимость иметь разные СУБД решения для OLTP и BI видим, что революции не произошло, все могут быть спокойны.
> которое требуется чтобы сделать один контекст свитч.
Это не неверное рассуждение, а, возможно, неточное. Причем, оно станет неточным, когда ты приведешь более точную корректную прикидку.
Вообще, напомню, началось с того, что ты смело заявил, что "буферизация" журналирования обязательно приводит к возрастанию latency. Я тебе показал, что при некоторых условиях это необязательно / несущественно.
Сравнение с временем context switch'а как-то не очень понятно. В нормальном воркфлоу LMAX их происходит оч мало.
> Обращаю внимание, что доступен код бенчмарка
Код + замеры
Вообще, вместо того, чтобы читать вторичный источник типа Фаулера или вотевер - посмотри лучше это. Там гораздо больше интересных мыслей, хотя и видео занимает целый час - имхо оно того стоит. Много мыслей известны и понятны, но тут все собрано в одном месте.
> На самом деле, существуют и полноценные однотредные in-memory БД, например
> http://en.wikipedia.org/wiki/VoltDB.
Отлично! Это хорошо, что кто-то додумался это сделать. Я вот тоже все хотел погуглить.
А теперь смотри. Допустим, мы хотим написать на этом VoltDB быструю биржу и повторить успех LMAX.
У нас должен быть кто-то, кто будет слушать сокет, куда будут коннектиться клиенты.
* Напрямую из VoltDB мы вряд ли сможем это сделать. Даже если они когда-нибудь научатся это делать, это будет значить, что вся логика должна будет быть полностью написана на предоставляемом ими языке. В принципе, может быть не так уж и плохо, но пока этого нет.
* Стандартная архитектура - есть application layer на чем-нибудь general-purpose, есть database layer из VoltDB, и они общаются. Тут, очевидно, присутствует оверхед на общение. Даже если эти слои живут в одном jvm, все равно надо из представления VoltDB создавать представление для app layer - а это cpu bound + потом нагрузка на gc. И это принципиальная проблема, от которой не уйти.
Поэтому LMAX это все же немножко больше, чем просто VoltDB. 6 миллионов, в которые ты так не веришь, были как раз замеряны на том одном потоке (на видео выше время 26:23). Понятно, что там ничего нету - ни синхронизации, ни журналирования (оно снаружи ни автоматических транзакций, ни gc, только сама логика. Поэтому эта цифра не кажется мне сумасшедшей. В VoltDB ты, вероятно, получишь похожую цифру, если померяешь производительность того одного потока, который собсно лопатит данные.
Проблема с VoltDB vs LMAX в том, что уровни, где ты меряешь - разные. И в случае с VoltDB это уровень глубже на один слой...
К сожалению, у всего этого действительно есть большой недостаток - они пока, собственно, не заопенсорсили часть, которая за дизраптором - журналирование + снапшоты. На снапшоты в общем-то насрать, как сериализовать некий граф объектов в памяти все и так хорошо знают. А вот с журналированием, подозреваю, опенсорса мы никогда и не увидим, потому что, подозреваю, данные, хранящиеся в журнале, жестко прибиты к их бизнес-логике.
Но ты, к сожалению, споришь с чем-то другим. То с тем, что преимуществ у такого подхода нет. То, что это все баян. То, что оно не выдает пефоманс, о котором они хвастаются...
А вообще, да, все идеи по отдельности не есть что-то новое:
* ring buffer
* lock-free spin locks
* выкидывание лишних слоев
Но все в куче сделало интересную вещь.
Оставить комментарий
6yrop
8 May 2012 http://martinfowler.com/bliki/OrmHate.htmlБля, три раза повторить, что есть очень реальная проблема, и ни разу не объяснить, что же эта за проблема. Почему в памяти нельзя effectively работать с реляционными структурами?