LINUX.ORG.RU

Микросервисы и точки отказа.

 , ,


4

2

Сейчас такая мода на микросервисы... Но смищно когда все микросервисы разворачивают на одном сервере, но это ССЗБ. А еще, когда я рос в ИТ, я помню постулат «Всегда снижай точки отказа», а с развитием микросервисов мне кажется что точек отказа просто писец как больше становиться. Притом админ при каждом обновлении фронта и бэка ставиться бешенной собакой. Обновления «экосистемы» становяться каким-то нетривиальным делом. Еще и микрофронтэнд тут сбоку подползает.


Перемещено maxcom из talks

★★★★★

Последнее исправление: splinter (всего исправлений: 2)

Ответ на: комментарий от byko3y

Зачем? Зачем кому-то вычислять сиракузскую последовательность? Это не задача, это «решение», а я просил задачу.

Математику. Хотя согласен, математику надо много последовательностей и можно каждую в отдельный поток.

А именно задачу… парсер XML в просмотрщике/редакторе подойдёт?

monk ★★★★★
()
Ответ на: комментарий от monk

И к моменту начала транзакции какая-то проверка стала ложна из-за другого пользователя.

Ага.

Но ты об этом уже не узнаешь и спишешь в минус деньги со счёта, остатки со склада и т.д.

Узнаю, потому что updated_at поменялся этим другим пользователем и affected rows при моём апдейте будет 0. Конечно, это нужно проверять внутри транзакции и отменять её.

Или ты про то, что updated_at должно работать как виртуальная транзакция и обновляться при каждой операции?

Да, этакий optimistic lock.

Соответственно, получая ошибку, пробуем повторить весь flow, начиная с селектов. С каким-то лимитом повторов. Звучит как будто оверхед, но это может помочь сократить время и область транзакций и/или блокировок в БД, а приложение отмасштабировать проще. Да и случаев, когда миллионы пользователей пытаются во так конкурентно, одновременно изменить общий ресурс, не так много.

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

korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 2)
Ответ на: комментарий от monk

Например, в CouchDB, ЕМНИП, подобное версионирование существует из коробки и включено по-умолчанию. Типа вычитываешь какую-нибудь сущность, что-то делаешь, пробуешь записать изменения, если версия внутри БД поменялась кем-то другим, она тебе выдаст ошибку.

korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 1)
Ответ на: комментарий от aist1

«Микросервисы», как таковые, делают только большие overstuffed компании
Микросервис только тогда микросервис, когда команда делает только его

Кстати, да, точно подмечено: микросервисами очень часто называют не микросервисы. Настоящие же микросервисы, независимые маленькие службы без необходимости сохранения данных, могут существовать только в таких больших компаниях. Потому что при меньшем числе разработчиков необходимости в таких службах просто нет, кто-то что-то неизбежно должен запоминать, отсюда проблемы миграции и согласованности, которые намного сложнее решать в распределенной системе.

Все остальные делают т.н. fine-grained сервисы (или вариации на тему SOA), где критерий нарезки будет уже именно техническим. Например, нарезка делается по границам масштабирования. Или — отказоустойчивости

Ну ты насмешил, конечно, масштабирование и отказоустойчивость в коммерческом программировании — кто ж их видел живьем-то? Они же как Йети — басни ходят, что где-то там высоко в горах кто-то когда-то увидел... А по итогу сумели «смасштабировать» на сотню серверов систему, которая могла бы обрабатывать ту же нагрузку на одном сервере. А «отказоусточивость» заключается в том, что опять что-то отвалилось, но на «всю систему» отвал не влияет, что бы это не значило, вплоть до отвала ключевой функции, но «большая часть» системы работает.

Поэтому «микросервисная архитектура» всегда будет неполной — в ней будет вонючая монолитная СУБД, просто воплощение мерзости и регресса (в кавычки не беру, эти люди реально так думают). Успокаивает лишь то, что БД дается облаком в виде сервиса, т.е. проходит «обряд очищения»

Да, это что-то вроде пары вонючих кодеров, которые на митингах редко появляются, тимбилдингом не занимаются (зачем они вообще нужны?), только делают сомнительную половину проекта, которая вообще-то не нужна, она ведь просто занимается хранением данных для всего проекта, но это же прошлый век, а век нынешний — это микросервисы без хранения данных. И по итогу реализацию 10% функциональности делают 90% штата.

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

Что «эти люди» реально так думают я увидел в треде с альфой и ко, где ребята всерьез удивлялись «состояние? зачем нам эта гадость?». Это bikeshedding в промышленных масштабах, целая идеология проектирования, реализации, и поддержки навесов для великов, а производство... извините, мы до такого не опускаемся, вот там сидят пять задротов, они занимаются производством, а мы заняты более важными делами.

А сказать слово против этого — это примерно как сказать «лезбухой и гомиком быть постыдно». Да, ты будешь прав, твоей храбрости будут завидовать многие, но тебя выгонят с работы, сытой, ненапряжной работы в мейнстримовой нише.

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

Oh rly? С Кассандры на MS SQL ты собрался легко мигрировать? Даже если ты применяешь хранимые процедуры, то твой выбор целевых СУБД сразу же резко сокращается. Заменить одну СУБД на другую ты можешь только если они и так почти одинаковые. Многоуровневая архитектура была популяризована именно ораклом, который продвигал модель «бизнес-логика, гвоздями приколоченная к БД на оракле» — это классика, это знать надо.

критерием наличия сервера приложений было использование ORM и кэширования на сервере приложений. Сервер с кэшированием — это уже сервер с состоянием, но это один из немногих паттернов работы с состоянием, который «условно нормально» вписывается в сервисную парадигму

Это неизбежное следствие применения многоуровневой архитектуры ПО МЕРЕ РОСТА нагрузки, но никак не обязательно условие. Или ты хочешь сказать, что вот у нас была изолированая бизнес-логика и отдельная БД, это был не сервер приложений, но вот сегодня мы на какую-то табличку поставили кэширование на стороне логики — и это немедленно превратило его в «сервер приложений»? Нет, сервером приложений его делала обособленность от БД — дальше не важно, какой степени.

В этом случает на помощь могут прийти sql-федераторы, такие, как https://trino.io/ и PrestoDB. Они заточены на аналитику, но так же могут относительно шустро работать и в режиме выполнения точечных запросов (OLTP)

В жизни не поверю, что эти костыли сумеют выдать хотя бы 100 тыс транзакций в секунду. А ведь это даже не высоконагруженная БД, если чо. Я бы в жизни не догадался, что инерция индустрии способна выдать таких уродцев, как Trino. SQL — это полнейший антипод распределенности и масштабируемости, ты либо с SQL и без масштабируемости, либо у тебя SQL и ты сидишь на одном сервере. И в первую очередь из-за join-ов — это краеугольный камень вообще всей реляционной модели, который зародился еще до появления самого термина «SQL». То, на какие системы ориентировался тот же Oracle, как бы говорит само за себя.

ORM поверх такого sql-федератора даст уже нормальный такой экспириенс работы со сложно-структурированным распределенным состоятнием, как с локальным

Во сколько обойдется такой «нормальный экспириенс»?

(2) требует уже SSI, поэтому для чего-то серьезного я выберу Postgres, а не MySQL

Сериализуемые снимки равноценны снимкам с блокировками по изменяемым записям.

Ни RR, ни (S)SI уже не масштабируемы

Во-первых, оба этих режима подразумевают мелкогранулярные блокировки, масштабируемость которых определяется мелкостью этих самых блокировок. Если они всегда будут попадать на один сервер, желательно на локальный, то масштабируемости эт о не помешает. Если блокироваться будут какие-то случайные записи, раскиданные по всей системе, то здесь начинается «во-вторых» — весь SQL не проектировался из расчета на масштабируемость, потому модели мира SQL непроизвольно погружают тебя в мир немасштабируемости. Священный грааль SQL, на котором выстроены все эти понятия — это сериализуемость, которая одновременно является кладбищем для любой масштабируемости.

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

То, что на самом деле подкупило потребителя — это универсальный язык, который позволяет работать с данными, не задумываясь про устройство хранилища. Однако же, наспех слепленная модель данных (реляционные таблички) этого языка надежно остановила развитие индустрии на многие десятилетия, приковав разрабов к крайне сложным реализациям исполнителей SQL, которые «легко и непринужденно» сглаживают всю кривизну реляционной модели.

Причем, парадокс здесь в том, что на самом деле на реляционную модель почти никакие данные из реального мира не налазят, отсюда возникла целая теория нормализации. То есть, разработчик берет простую логичную прикладную модель, с трудом натягивает ее на реляционную модель, чтобы в результате получить гарантированно немасштабируемую модель, которую может эффективно обрабатывать только очень сложный сервер.

Люди, которые втирают нам про scale-out, в следующем предложении будут говорить, что «джоины — не нужны, как и транзакции»

Да, не нужны. Вам масштабируемость или джоины?

byko3y ★★★★
()
Ответ на: комментарий от aist1

SAT-солверы на GPGPU сливают своим аналогам на CPU

Ну типа решение проблемы топографии в микросхемах — это вроде как SAT, да? Тем не менее, эффективно решают ее именно при помощи ИИ, работающего на матрицах. SAT — это по прежнему еще не задача, а способ решения.

Из этой оперы мне приводили пример конечного автомата — мол, конечный автомат нельзя эффективно реализовать на GPGPU. Да, только конечный автомат является решением, а не задачей.

Я согласен с тем, что есть задачи, которые плохо решаются GPGPU, но эти же задачи прекрасно параллелизуются FPGA. Мне на ум сейчас не приходит что-то конкретное, но, грубо говоря, это большое число параллельных условных обработок, где каждый шаг одного потока отличается от параллельного потока, потому не может быть выполнен на GPGPU, но по этой же причине он прекрасно параллелизуется.

В общем случае стоит смотреть не на то, что это (CPU, GPU или FPGA), а какая у железки архитектура памяти. Тупо передать слово из RAM в CPU требует в 600 раз больше энергии, чем перемножить два слова. Поэтому, скоро будет рулить in-memory computing

Внезапно, сам CPU занимается in-memory computing, но почему-то до сих пор играется в прозрачный доступ к RAM, что само по себе создает огромный слой неэффективности.

CPU — это машина состояний над вполне определенной архитектурой памяти: 3 уровня кэшей, сложный prefetching, скрывающий задержки. Всё ориентировано на ускорение произвольного доступа

??? Всё ориентировано на ускорение последовательного доступа — чтение данных доступом к случайным четырем байтам по уникальному адресу будет еле ползать на любом современном процессоре.

На самом деле оптимизирует он пошаговое выполнение, сглаживая его в доступ к последовательным блокам, поскольку пошаговое выполнение редко само по себе последовательно читает байты. GPGPu точно так же ориентирован на пошаговость, только последовательные блоки данных там реализованы явно в самом фундаменте, «сглаживать» ничего не нужно.

byko3y ★★★★
()
Ответ на: комментарий от vbr

Суть в том, что они могут быть на разных технологиях. Один блок на typescript + react. Второй на vue, третий на angular. Каждый блок разрабатывается отдельной командой, никак не зависящей от других

Ага, так вот кто пишет сайты, которые у меня не работают. Вот где-где, а во фронте такой подход 100% не работает, никогда, ни в каком проекте и ни в какой команде. То, что называется «привет фейсбуку», хотя даже у фейсбука тотальная диктатура реакта.

Да, могут быть подключаемые модули, модули могут разрабатываться относительно независимо, под капотом может дергаться что-то стороннее, но фронт перестает работать в тот момент, когда разработчики конечного интерфейса (именно того самого, который на vue, react, angular) окукливаются и начинают независимо писать разные блоки одной и той же страницы. Потому что пользователю забывают сообщить о том, что разные блоки писали разные команды, и он, дурак, ожидает от интерфейса единого поведения, и не понимает, почему страница вроде одна, но блоки на ней он должен ублажать по отдельности, особенно когда один блок мешает другому — потому желательно не пытаться одновременно вводить данные в оба этих блока, и уж тем более не ожидать, что блоки будут знать про данные из соседнего блока.

byko3y ★★★★
()
Ответ на: комментарий от tz4678_2

<div id=«vue-govno»></div>
<div id=«react-govno»></div>

app.mount('#vue-govno')

ReactDOM.render(<App />, document.getElementById('react-govno'))

Это рецепт для катастрофы. Два цикла обновления интерфейса, и как они будут взаимодействовать между собой — ума не приложу. Причем, именно Angular и Vue отличаются сложностью взаимодействия в любую сторону, то есть, сторонний JS тяжело встроить во Vue и Vue тяжело встроить в сторонний JS. С реактом все-таки чутка попроще, потому что он сам по себе примитивнее.

Правда, всех переплюнет jQuery, который начнет по месту менять DOM — свой, родительский, дочерний, нарушая работу случайных компонентов.

byko3y ★★★★
()
Ответ на: комментарий от vbr

Где, если ты хочешь, чтобы соседняя команда что-то сделала, тебе надо подождать несколько месяцев и то если повезёт. Для них всё, что позволяет увеличить независимость команды - благо

Выгонять бездельников и налаживать процессы разработки не нужно — давайте окуклимся и будем дальше сидеть на окладе. Ох и богатая же компания у вас, я прям завидую.

byko3y ★★★★
()
Ответ на: комментарий от monk

А именно задачу… парсер XML в просмотрщике/редакторе подойдёт?

Хороший пример, принимается. Хороший пример чудовищно плохого формата сериализации. Я не понимаю людей, которые рассуждают, что лучче «самотык, пика, или ножка от стула» — так и хочется сказать «а вы на обычной седушке прямостоящего стула сидеть не пробовали?». Я мечтаю когда-нибудь достать мемуары какого-нибудь менеджера-комитетчика, чтобы узнать, какую дозировку кокаина он применял, когда принимал решение, что «это» — хороший, годный формат для хранения данных. Буквально каждый аспект XML отвратителен, начиная от выбора способа разметки и кончая вообще идеей использовать язык разметки для форматирования данных. Наверняка там было что-то вроде «ну у нас же есть готовый парсер» — но это слишком простое оправдание, ведь в XML есть куча фич, которых не было в HTML, и потому никаким готовым парсером это не объясняется.

Так вот, XML НЕВОЗМОЖНО парсить быстро из-за глубоких взаимосвязей элементов разметки 95% фич, которые задействованы в 5% программ, но парсер обязан поддерживать 100% этих фич. Даже на CPU выходит что-то порядка нескольких десятков МБ/с. Можно парсить гигабайт в секунду небольшое подмножество XML, но тот трэшак, который зовется стандартным XML, неподъемен для любого вычислителя. Если у тебя сервисы общаются друг с другом по XML, то парсинг XML почти всегда будет узким местом — потому была тенденция укрупнять сервисы и минимизировать передачу XML, пока XML наконец не закопали.

byko3y ★★★★
()
Ответ на: комментарий от tz4678_2

там нету двух циклов. он один:
whilte (true)
{
executeJs();
renderHtml();
}

То, что в JS сделали единственный механизм главного цикла, не отменяет возможности в этом главном цикле крутится нескольким не знающим друг про друга циклам со своими независимыми асинхронными операциями. Ты не можешь влезть в цикл Vue и повлиять на поведение (всякие там $nextTick и хуки времени жизни) — нужны какие-то функции-интерфейсы. которые сделаны со стороны Vue и которые сделают всё за тебя. Да, ты можешь возражать в духе «ну я же могу взять реактивный объект и поменять в нем значение простым JS, и Vue подхватит изменение». Действительно, подхватит, но только пока это изменение примитивного значения. Со сложными объектами всё выходит из-под контроля очень быстро, потому только функции-интерфейсы. Но даже они не позволяет влиять на поведение, на саму реакцию на изменение состояния, которая растянута во времени — приходится расширять и утяжелять интерфейсную часть, чтобы конвеер Vue становится интерфейсом.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

там нет циклов внутри. у тебя надуманные проблемы. интерфейсы не нужны. вот есть русский язык, есть английский, ты пытаешься на английском говорить по правилам русского… с языками программирования то же самое. они просто другие. пусть и очень похоже на джавы, c++ и тп

tz4678_2
()
Ответ на: комментарий от byko3y

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

Вот, кстати, да. Недавно промелькнула мысль у меня, что СУБД, в том числе и реляционные, используются как storage. И что большинству приложений нужны не СУБД, а гибриды БД и ФС. Но, таких нет. Поэтому едим, что есть.

Oh rly? С Кассандры на MS SQL ты собрался легко мигрировать?

Я помню, еще начинал с EJB 2.0, и там делалась доменная модель с кэшированием состояния в памяти сервера приложений, что позволяло не только изолировать логику от БД, но и разгрузить саму БД. Доступ в БД был по большей части точечный, т.е. переехать с C* на MSSQL можно было, с поправкой на EC в C* и невозможность делать длинный скроллинг.

Тут дело принципа: среднее звено должно выполнять какие-то нетривиальные функции. Иначе, это не трехзвенка, а её косплей. Таковой функцией является доменная модель. Которая тоже должна быть нетривиальной. Например, можно сменить storage минимальными усилиями.

С появлением кэширующих ORM трехзвенка, как таковая, выродилась. В смысле, стала декларативной частью фреймворка и про нее «забыли».

В жизни не поверю, что эти костыли сумеют выдать хотя бы 100 тыс транзакций в секунду.

Это не костыли, а инструменты для аналитики с возможностью работы так же и в OLTP режиме. Да, они (а) дают некоторый overhead и (б) не оптимизируются специально для OLTP. Но они умеют в predicate pushdown, т.е., например, точечные запросы (которые СУБД делают по «100 тыс в секунду») по первичному ключу пойдут прямиком в datasource.

Я там выше обозначил, когда этот паттерн стоит применять: когда приходится делать джоины в памяти сервера приложений. Делать джоины «руками» — оно, конечно, несопоставимо быстрее будет работать, и в разработке на много удобнее, чем применить SQL-федератор, непосредственно на это заточенный (нет).

Если же у нас в архитектуре одна «нагруженная СУБД», то федератор нам просто не нужен. А вот если монга, мускуль, и эластик — вот тут уже вопрос...

Но, если подумать, кому действительно нужна сериализуемость?

С сериаизуемостью всё становится сильно проще. С неё надо начинать и идти в более слабые модели только когда это (а) необходимо и (б) возможно. Разработка тоже стоит (больших) денег, не только железо.

Вот пример. LMDB, сделанная из говна и палок и дающая линеаризованные транзакции с неблокирующимися читателями, способна давать TPS на уровне IOPS-ов диска (реально — нет, из-за mmap, но схема всё равно рабочая). Что сейчас нам даст миллионы точечных транзакций на один сервер средней руки. Этого хватит, чтобы зарулить «пол-уолл-стрита» разом. Нет, конечно же, но идея такая, что точечные сериализуемые транзакции можно иметь в большом количестве на дешевом железе. И вот только когда упираемся в предел железа, то начинаем ослаблять модель и идти вширь, в том числе в...

Для всех остальных данных достаточно выполнения причинно-следственных связей.

Causal Consistency (СС) очень сложна в разработке. Её в общем виде никто толком не делает. MAANG в расчет не берем, это параллельная Вселенная со своими законами физики. У нас же тут чудес не бывает))

Вам масштабируемость или джоины?

Джоины, конечно же. Мне именно БД нужна, а не просто storage. Гибридная БД с достаточно быстрым OLTP для real-time аналитики. Причем, аналитика хочет видеть консистентные мгновенные снимки данных. Еще хочу RETE и forward chaining для Complex Event Processing, прямо в БД. Не отходя, так сказать, от кассы. Да, я много чего хочу, яж в инжиниринге данных работаю.

Но я тебя понимаю, что ты за СС топишь и я с тобой согласен, как с теоретической, так и с практической стороны. Несмотря ни на что, будущее всё же за CC.

aist1 ★★★
()
Ответ на: комментарий от byko3y

Я согласен с тем, что есть задачи, которые плохо решаются GPGPU

Я просто хотел сказать, что «ужасно неэффективны» сейчас не CPU вообще, а CPU с OoOE. Производительность от поколения к поколению хоть и растет сейчас экспоненциально (10-15% каждый раз — это, всё же, экспонента), но растет она куда медленее, чем могла бы (и скоро всё же упрется в стену). OoOE-ядра большие, горячие и плохо масштабируются, и проблема в том, что ну не нужны их «десятки» в оконечных устройствах с таким потреблением. Тогда как на 1 см^2 площади кристалла можно разместить тысячу легких RV64 ядер с акселераторами, и решать точный SAT (а не приближенный, как в случае «ИИ на матрицах»), а так же Tableau и прочий вывод на деревьях в единицах ватт. GPGPU тут будут где-то далеко-далеко в плане энергоэффективности.

aist1 ★★★
()
Ответ на: комментарий от korvin_

Да, этакий optimistic lock.

Даже в примитивном описанном случае может поломаться, если будет завершение работы после транзакции, но до перевода на счёт получателя.

В более сложных придётся через этот updated_at какие-то суррогатные сущности помечать. Например, списание со склада: будешь помечать номенклатуру? И списание с одного склада блокирует все склады?

И чем велосипедная блокировка на дополнительной колонке будет быстрее стандартной?

Да и случаев, когда миллионы пользователей пытаются во так конкурентно, одновременно изменить общий ресурс, не так много.

Тогда и стандартной хватит. Но вот для случая продажи со склада и не очень большом ассортименте, блокировки будут почти постоянно (хлеб на 3 кассе и на 15 кассе …, пакет на 4 кассе и на 5 кассе …).

monk ★★★★★
()
Ответ на: комментарий от aist1

Тут дело принципа: среднее звено должно выполнять какие-то нетривиальные функции. Иначе, это не трехзвенка, а её косплей. Таковой функцией является доменная модель. Которая тоже должна быть нетривиальной. Например, можно сменить storage минимальными усилиями

Кто и по какой линейке будет мерять тривиальность-нетривиальность функций? На самом деле люди с радостью бы выполняли код прямо в БД, но один хочется на таком языке, другой хочет на эдаком, при этом оба языка реализованы на си и непонятно, какие имеют уязвимости и насколько надежны — а это дело должно торчать в веб или хотя бы в интранет. Потом выносят логику в отдельный процесс. Дальше уже прикручивание нетривиальности и кэшей — чистые формальности.

Это не костыли, а инструменты для аналитики с возможностью работы так же и в OLTP режиме. Да, они (а) дают некоторый overhead и (б) не оптимизируются специально для OLTP. Но они умеют в predicate pushdown, т.е., например, точечные запросы (которые СУБД делают по «100 тыс в секунду») по первичному ключу пойдут прямиком в datasource

Модель «здесь я работаю так, а здесь я работаю совершенно иначено только в очень специфически случаях» очень даже тянет на «груда костылей». CPython так сделан, например, он может «быстро» вычислять сумму по целым числам — всё остальное еле ползает. Это как бы ad-hoc оптимизация заведомо провальной модели.

Если же у нас в архитектуре одна «нагруженная СУБД», то федератор нам просто не нужен. А вот если монга, мускуль, и эластик — вот тут уже вопрос

Да, у меня тоже вопрос: кто это всё налепил и зачем?

С сериаизуемостью всё становится сильно проще. С неё надо начинать и идти в более слабые модели только когда это (а) необходимо и (б) возможно. Разработка тоже стоит (больших) денег, не только железо

Мы уже обсуждали этот вопрос где-то год назад, с тех пор я уже работаю за деньгу над проектом, который ориентирован на масштабирование по дереву индексов и там в принципе нет сериализуемости, а мои теоретические изыскания ушли уже намного дальше, я больше не ограничиваюсь случаями шардирования дерева по индексу, а увидел, что колоть можно и нужно намного больше данных, и что на самом деле причина всех проблем одна и сводится к реляционной модели.

Причем, если поднять сообщения двухлетней давности, то можно увидеть, что я топил за реляционную модель, как за решение всех проблем, общий знаменатель, который может быть не самым оптимальным, но самым универсальным решением всех проблем. Теперь я переобулся и считаю его универсальной проблемой для всех решений. Если ограничиться реляционной моделью, то, действительно, решением может быть только сериализуемость, а причинно-следственные связи очень тяжело описывать.

Вот пример. LMDB, сделанная из говна и палок и дающая линеаризованные транзакции с неблокирующимися читателями, способна давать TPS на уровне IOPS-ов диска (реально — нет, из-за mmap, но схема всё равно рабочая)

Это плюшевые TPS-ы, а не настоящие транзакций, никаких сложных транзакций записи при параллельных читателях ты сделать не сможешь даже чтобы дотянуть до уровня repeatable reads/serializable snapshot.

Causal Consistency (СС) очень сложна в разработке. Её в общем виде никто толком не делает

Нужно не так формулировать: разработку БД на причинной согласованности никто даже не начинал делать. Все надеятся, что внешних индексов в РСУБД фатит, хотя они прежде всего опираются на сериализуемость, и потому принципиально немасштабируемы, как и прочие join-ы. При этом на самом деле на причинной согласованности невольно строится любая проектируемая с нуля система, то есть, та, которая не строится на готовой СУБД со своими гарантиями. Но чтобы начать действительно эффективно разрабатывать такие решения, а не каждый раз будто в первый раз, нужно начать строить операции работы с несогласованностью данных, а не с изначально согласованными данными, как это делается обычно. Один из первых шагов в это направлении — CRDT, но обычно «всё это ваше CRDT» упирается в тупое «last writer wins» — так сделал амазон, так было на моем первом крупном проекте, а с этой точки до причинной согласованности еще как до киева раком.

Гибридная БД с достаточно быстрым OLTP для real-time аналитики. Причем, аналитика хочет видеть консистентные мгновенные снимки данных

Нет, тебе не нужны мгновенные снимки. Какая тебе разница, придет ли согласованный кусок секундой раньше или позже? Тебе нужна именно согласованность между данными, а не мгновенность во времени. Даже Google Spanner такой мгновенности не обеспечивает, у него есть некоторое окно расхождения в несколько миллисекунд. Есть ровно один способ сделать мгновенный снимок — иметь единственную ячейку в памяти одного компьютера, которая будет решать, какой индекс снимка у нас сейчас самый актуальный. Соответственно, это не масштабируемо и не отказоустойчиво. Есть либо вариант синхронной репликации, которые просто растягивают все твои транзакции на время одного двух RTT и сотни RTT при отказе, либо масштабируемо, но не отказоустойчиво и твоя система оказывается в непонятном состоянии после выхода из строя той одной ячейки памяти.

RETE и forward chaining для Complex Event Processing, прямо в БД

Не знаю такого.

byko3y ★★★★
()
Ответ на: комментарий от aist1

«ужасно неэффективны» сейчас не CPU вообще, а CPU с OoOE

Внеочередное и спекулятивное выполнение создает неэффективность в несколько раз, но это все равно далеко не единственный источник. Например, теперь мы знаем, что строгая упорядоченность операций над кэшем плюс переусложненность набора инструкций стоит двухкратной неэффективности (ARM vs x86). Тем не менее, у ARM есть поочередное выполнение, которое возможно именно благодаря свободной модели кэша, но какого-то космического прироста производительности оно не дает — просто потому, что размер кэша затмевает размер вычислительной части ядра, и потому дополнительный АЛУ не отсвечивает на общем фоне.

То есть, если бороться с неэффективностью, то начинать надо не со внеочередного выполнения, а с кэша, который сейчас занимает примерно половину площади ядра.

Тогда как на 1 см^2 площади кристалла можно разместить тысячу легких RV64 ядер с акселераторами, и решать точный SAT (а не приближенный, как в случае «ИИ на матрицах»), а так же Tableau и прочий вывод на деревьях в единицах ватт

Мне показалось, или ты предлагаешь разбивать решение SAT на много-много мелких потоков?

byko3y ★★★★
()
Ответ на: комментарий от monk

Даже в примитивном описанном случае может поломаться, если будет завершение работы после транзакции, но до перевода на счёт получателя.

А вот списание+зачисление как раз в одной транзакции делаться должно.

И чем велосипедная блокировка на дополнительной колонке будет быстрее стандартной?

Какой стандартной? Ты про какую СУБД говоришь?

Например, списание со склада: будешь помечать номенклатуру?

Нормально ты решил условие задачи усложнить. Напомнить какой уровень изоляции в этом месте нужен чтоб это нормально работало в одной транзакции и какие накладные расходы это за собой потащит? Если можно перестроить бизнеспроцессы чтобы можно было жрать eventual-consistency с этом месте, надо перестраивать

Тут же тред про data-intensive распределенные системы, а иначе зачем микросервисы, и в них все трейдоф. Ну если ты конечно кусок ERP для склада пишешь, то бери RDBMS, обмазывайся сериализацией и в ус не дуй

RedPossum ★★★★★
()
Ответ на: комментарий от aist1

Делать джоины «руками» — оно, конечно, несопоставимо быстрее будет работать, и в разработке на много удобнее, чем применить SQL-федератор, непосредственно на это заточенный (нет).

Я пример с Движение.Партия.Дата через джойны и через поле в памяти сервера приложений приводил.

SQL-федератор нужен либо если есть доступ к базам в обход сервера приложений, либо если сами базы настолько огромные, что вытаскивать их в память сервера приложений невозможно.

monk ★★★★★
()
Ответ на: комментарий от RedPossum

Какой стандартной? Ты про какую СУБД говоришь?

В общем, любую, поддерживающую транзакции. Блокировку в виде дополнительной колонки последний раз в DBF видел (и в 1С при работе с интерфейсом: открывать транзакцию на время ввода пользователем данных объекта они не рискнули).

Напомнить какой уровень изоляции в этом месте нужен чтоб это нормально работало в одной транзакции и какие накладные расходы это за собой потащит?

Повторяющееся чтение. Блокировка записи по индексу номенклатура+склад в таблицу движений/остатков.

Тут же тред про data-intensive распределенные системы

А в этом случае у нас сервер приложений с текущими остатками в памяти и атомарной операцией «проверить-и-списать».

Ну если ты конечно кусок ERP для склада пишешь, то бери RDBMS, обмазывайся сериализацией и в ус не дуй

При тупом решении в лоб легко получаем время проведения документа списания в 5 секунд и (из-за сериализации) строго последовательно проведение документов (то есть больше 12 документов в минуту не провести).

monk ★★★★★
()
Ответ на: комментарий от RedPossum

Тут же тред про data-intensive распределенные системы, а иначе зачем микросервисы, и в них все трейдоф

О, а это здравая мысль: это тред про обработку объемов данных более 100 ТБ, которая не умещается на одном хосте. Правда, внезапно выяснится, что таких объемов нет ни у кого из сидящих здесь, «а иначе зачем микросервисы, и в них всё трейдоф».

byko3y ★★★★
()
Ответ на: комментарий от vbr

А про независимость ты зря хохмишь. Видимо ты не работал в крупных компаниях. Где, если ты хочешь, чтобы соседняя команда что-то сделала, тебе надо подождать несколько месяцев и то если повезёт. Для них всё, что позволяет увеличить независимость команды - благо

Чот я еще раз пропустил эту фразу через опыт работы, и свой личный и знакомых людей, и внезапно осознал, что на самом деле есть ровно один способ организации разработки приложений в крупных компаниях — это INMF-driven development (абревиатура от «It's Not My Fault»). Если соседняя команда пролюбила всё, что только можно, а у вас из-за этого встала работа — INMF-подход спасает положение, теперь у меня всё работает, а дальше это не моя проблема.

В этом свете всякие там TDD, BDD, микросервисы, XP, Scrum — это просто частные случаи INMF-driven development. Особенно активно INMF применяется на уровне менеджмента и управления проектами, когда одни дыры затыкаются созданием других дыр или демонстрацией начальству/заказчику того что нужно под нужным углом. Не проходят тесты? Подправим тесты, согласно INMF — и вуаля, тесты проходя успешно. Как выше правильно заметил anc, микросервисы дают бесконечное пространство для INMF-маневров, как в плане «наш сервис такую фичу не реализовывает, для этого нужен другой сервис», так и в плане «что быстро перезапустилось — то не падало».

Собственно, о чем и тред. Технических причин для применения микросервисов не существует. Правда, есть причины для модульности и макросервисов.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

таких объемов нет ни у кого из сидящих здесь

да ладно, во всех этих яндексах, авито и озонах точно есть лоровцы

RedPossum ★★★★★
()
Последнее исправление: RedPossum (всего исправлений: 1)
Ответ на: комментарий от byko3y

Это плюшевые TPS-ы, а не настоящие транзакций, никаких сложных транзакций записи при параллельных читателях ты сделать не сможешь даже чтобы дотянуть до уровня repeatable reads/serializable snapshot.

Самые, что ни на есть, настоящие. В LMDB Copy-on-Write и персистентная структура данных, а не блокировки записей. В такой схеме (я сейчас не про реализацию схемы в LMDB) есть всего лишь две блокировки (именно два мютекса). Одна блокировка линеаризует писателей, а вторая — огораживает историю коммитов для читателей, и берется на очень короткое время при старте читателя. Дальше читатели уже ни друг-другу, ни писателям не мешают вообще (wait-free), так как сидят в разных участках памяти. Писатель в каждый момент может быть только один, но сам писатель может внутри «распараллеливаться», вытаскивая из диска максимально возможные для него IOPS-ы, что и конвертируется в высокий TPS.

Схема идеальна для коротких точечных транзакций типа перевода денег со счета на счет. Если же нужно гнать какую-то аналитику внутри писателя, то тут уже все другие писатели будут ждать. Поскольку таких относительно долгих транзакций тоже бывает, схема имеет ограниченное применение.

CRDT

CRDT вообще не про CC. CRDT — это типы данных, для которых возможно автоматическое слияние версий в общем случае. Монотонный счетчик, множество, неупорядоченное дерево и некоторые другие. А вот для упорядоченных структур в общем виде CRDT нет. Поэтому у нас нет автоматического мержа в Git, так как текстовые файлы — упорядоченные массивы. Мерж у нас ручной, т.е. «специфический для приложений».

Если ты хочешь явным образом «работать с несогласованностью», то тебе как раз подойдет atomic commitment, как в Git. Писатели создают версии, которые потом явным и специфическим для приложения образом сливаются. От этой схемы довольно близко к «классической» СС, так как история изменений вся присутствует в явном виде и доступна для анализа.

Нет, тебе не нужны мгновенные снимки. Какая тебе разница, придет ли согласованный кусок секундой раньше или позже?

Я про SI, но чтобы без write skew.

Соответственно, это не масштабируемо и не отказоустойчиво... и твоя система оказывается в непонятном состоянии после выхода из строя той одной ячейки памяти

Страшно представить, в каком состоянии будет моя система после падения на неё метеорита. Мне кажется, что ты масштабируемость и отказоустойчивость абсолютизируешь. А это физически невозможно. Мы можем лишь минимизировать выбранные классы событий, исходя из заданных энергетических бюджетов.

RETE и forward chaining для Complex Event Processing, прямо в БД

Не знаю такого.

Вот о чем и речь. А штука сама по себе классная. На основе CEP, например, делается контроль фрода по кредитным картам через анализ комплексного потока событий вокруг кредитки и её владельца.

aist1 ★★★
()
Ответ на: комментарий от byko3y

Мне показалось, или ты предлагаешь разбивать решение SAT на много-много мелких потоков?

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

Сейчас есть только один класс акселераторов, которые умеют в динамический параллелизм (но он там другого типа) — это те самые OoOE-ядра, которые мы тут критикуем за неэффективность. GPGPU, FPGA и, особенно, ASIC-и все заточены на статический параллелизм.

aist1 ★★★
()
Ответ на: комментарий от byko3y

Сложность взаимодействия между людьми и командами растёт квадратично (на глаз) от их размера и числа. Это факт вполне объективный. Микросервисы помогают с этой сложностью бороться. INNF на уровне отдельной команды работает, но в какой-то момент уровнем выше наступает понимание наличия проблем в такой архитектуре и микросервисы в том числе решают эту проблему.

Кстати неявный плюс микросервисов — порой соседняя команда переписывает какой-нибудь сервис, тк исходный слишком плох, и на их сервис потихоньку все переползают. Эдакая естественная борьба.

vbr ★★★
()
Ответ на: комментарий от aist1

Схема идеальна для коротких точечных транзакций типа перевода денег со счета на счет

А кроме баланса счета инфы никакой хранить/менять не нужно? В таком сильно вырожденном виде никто платежные системы уже давно не делает.

А вот для упорядоченных структур в общем виде CRDT нет. Поэтому у нас нет автоматического мержа в Git, так как текстовые файлы — упорядоченные массивы. Мерж у нас ручной, т.е. «специфический для приложений»

Да, специфический для логических связей в сущностях. На самом деле, конечно же, оно не обязано быть полностью conflict-free, примерно как в упомянутом git, но для этого, как я писал изначально, нужно изначально проектировать алгоритмы вокруг работы с рассогласованностью, а не с согласованными данными.

Нет, тебе не нужны мгновенные снимки. Какая тебе разница, придет ли согласованный кусок секундой раньше или позже?

Я про SI, но чтобы без write skew

И я про них. По немгновенному снимку можно избежать асимметрии записей, если проверять, что изменяется именно то, что попало в снимок. Правда, здесь нужно заметить, что атомарные изменения нескольких записей на нескольких хостах не масштабируются — нужно либо на одном хосте, либо неатомарно с причинной согласованностью.

Мне кажется, что ты масштабируемость и отказоустойчивость абсолютизируешь. А это физически невозможно. Мы можем лишь минимизировать выбранные классы событий, исходя из заданных энергетических бюджетов

Может быть метеорит, а может и отключение одного датацентра — это довольно нередкая ситуация, между прочим. Именно под нее и проектируется отказоустойчивость. Отказ двух датацентров обычно не рассматривается.

byko3y ★★★★
()
Ответ на: комментарий от aist1

Сейчас есть только один класс акселераторов, которые умеют в динамический параллелизм (но он там другого типа) — это те самые OoOE-ядра, которые мы тут критикуем за неэффективность

Это как гопники, которые отобрали у загулявшего прохожего всё имущество, но оставили денег на такси. «Утешительная акселерация».

byko3y ★★★★
()
Ответ на: комментарий от vbr

Сложность взаимодействия между людьми и командами растёт квадратично (на глаз) от их размера и числа. Это факт вполне объективный

Да, банальный пример — рост времени митинга с ростом размера команды.

в какой-то момент уровнем выше наступает понимание наличия проблем в такой архитектуре и микросервисы в том числе решают эту проблему

Поясни, почему ядро линукса в 30 млн строк кода можно разрабатывать в формате монолита? Торвальдсу забыли рассказать про «решение этой проблемы»? Если не нравится ядро — Chromium, Firefox, PostgreSQL, etc.

Кстати неявный плюс микросервисов — порой соседняя команда переписывает какой-нибудь сервис, тк исходный слишком плох, и на их сервис потихоньку все переползают. Эдакая естественная борьба

А потом выясняется, что все эти сервисы на самом деле ничего полезного не делали изначально, а вся система держалась на единственном сервисе от трех задротов, принцип работы которого никто больше не понимает.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

А кроме баланса счета инфы никакой хранить/менять не нужно?

Точечные запросы — запросы, которые читают и пишут O(1) объектов. Сюда же обычно относится сканирование с высокой селективностью, хорошо проиндексированное. Если наше OLTP-приложение может функционировать в таком режиме, то LMDB-подобная SWMR-схема для него подойдет. Иначе — нужно смотреть.

нужно изначально проектировать алгоритмы вокруг работы с рассогласованностью

ОК. Я вижу твой поинт. Как ты себе это представляешь: «изначально проектировать алгоритмы вокруг работы с рассогласованностью»?

Вот, например, я это представляю в виде «git-подобной» (тут есть название — confluently persistent) децентрализованной БД, в которой каждая транзакция создает новую версию данных. Потом версии «мержатся». СRDT при этом могут мержится автоматически, для остального нужны будут специфические для приложения механизмы, включая привлечение человека (в особо трудных случаях). Это — т.н. схема с полной материализацией конфликта, и она универсальна с точки зрения её программной реализации, так как все версии объекта остаются доступны для анализа. Бонусом идут вожделенные для аналитики консистентные снэпшоты (консистентные при условии, что мерж не создает write skew).

aist1 ★★★
()
Ответ на: комментарий от byko3y

«Утешительная акселерация».

Ну а больше ничего пока что в динамический параллелизм не умеет даже формально. Можно, конечно, выполнять анализ структуры формулы на CPU, и моно-ветки считать на нем же, а появившиеся в товарном количестве параллельные ветки выгружать на GPU и другие статические акселераторы. Но это всё же схема, в которой присутствует достаточно быстрый CPU. Т.е. без CPU не обойтись. Поэтому, достаточно быстрые OoOE ядра всё же предусмотрены в архитектурах перспективных акселераторов приложений. Типа, 16 быстрых ядер и 1024 «минионов». Вот эти быстрые ядра, как предполагается, и будут заниматься динамическим параллелизмом.

Но вот сами одни только OoOE-ядра, без минионов, это — да. Тупик (энергоэффективности).

aist1 ★★★
()
Последнее исправление: aist1 (всего исправлений: 1)
Ответ на: комментарий от monk

Давай, я приме приведу, когда федератор становится оправданным.

(Это просто как иллюстративный пример, а не для «не надо было это всё вместе брать с самого начала»)

Есть у нас Монга, Мускуль и Эластик. Мускуль - primary source of truth, основная операционная БД. В Монге – хз что, но тоже что-то кому-то нужное. В эластике, как водится, часть мускульной и монговой БД, по которой делается поиск.

Типичный запрос – мы идем сначала в эластик, поднимаем там первичные ключи, потом идем в Мускуль, забираем там связи и еще что-нибудь. До кучи можно и в Монгу сходить, тоже что-то вебовское забрать для сайта.

Если таких запросов в системе фиксированное количество, а основная масса запросов идет в одно из хранилищ, то федератор нам не нужен. Так как лишняя сущность, которую придется кормить.

А вот если каждый новый разрабатываемый функционал так или иначе лезет сразу в несколько хранилищ, то мы либо каждый раз кодируем соотвествующий join руками, либо берем готовый SQL-федератор. У кого руки чешутся покодировать, – флаг им в эти руки. Я же федератор возьму, если он вытянет по нагрузке. Если не потянет, то я сначала попробую оптимизировать федератор.

aist1 ★★★
()
Ответ на: комментарий от byko3y

Внезапно, сам CPU занимается in-memory computing, но почему-то до сих пор играется в прозрачный доступ к RAM, что само по себе создает огромный слой неэффективности.

Можно вот тут в порядке офтопика более детальное пояснение, почему текущая модель доступа CPU к памяти неэффективна?

agentgoblin
()
Ответ на: комментарий от aist1

Точечные запросы — запросы, которые читают и пишут O(1) объектов. Сюда же обычно относится сканирование с высокой селективностью, хорошо проиндексированное. Если наше OLTP-приложение может функционировать в таком режиме, то LMDB-подобная SWMR-схема для него подойдет. Иначе — нужно смотреть

Да, я согласен с тем, что изменение одной-двух табличек по первичному ключу прекрасно сработает — я именно в таком виде продвигаю SQLite в бигдате. Другое дело, что редко где такими запросами можно удовлетвориться, нужно вот здесь еще немножко записать, и тут проверить, и там добавить, и уже куча блокировок по многим таблицам, причем, под нагрузкой все они будут конфликтовать. А продакшен — он такой, редко когда можно точно угадать, что нужно будет через полгода.

Я вижу твой поинт. Как ты себе это представляешь: «изначально проектировать алгоритмы вокруг работы с рассогласованностью»?

Вот, например, я это представляю в виде «git-подобной» (тут есть название — confluently persistent) децентрализованной БД, в которой каждая транзакция создает новую версию данных

Тоже когда-то думал о таком, и на самом деле участвовал в реализации — другое дело, что этого мало. Нужно учитывать требования к согласованности различных данных. Отдельные операции требуют строгой сериализации, но большинство операций можно безконфликтно сливать. Именно смена фундаментальной модели дает возможность перейти от фундамента сериализованности к фундаменту CRDT, от которого уже идет опциональное устрожение согласованности вплоть до глобальной сериализуемости.

Основная причина, почему так часто в разных система нужна строгая сериализуемость, заключается в том, что смена порядка операций дает разный результат — а он требуется одинаковый во все системе. Это относится в том числе к kubernetes, которому так-то на самом деле никакой строгой атомарности транзакций на самом деле не требуется, потому что смена конфигурации происходит в режиме eventual consistency, но именно для организации консенсуса по текущей конфигурации и нужен etcd, то есть «к какой конечной конфигурации мы стремимся в нашей eventual consistency».

Когда-то ZooKeeper тоже использовали для установления консенсуса, но в какой-то момент ушлый разрабы БД решили «так это ж можно через него определять порядок больших транзакций, и при этом не нужно хранить сами жирные данные в ZooKeeper — достаточно хранить уникальные ссылки на BLOB-ы, и ZooKeeper будет упорядочивать только эти ссылки». Как бы оно ни было масштабируемо по объему данных в транзакции, оно оказывается немасштабируемым по числу транзакций и вообще сложно настраивать и админить.

Однако, с уменьшением числа конфликтов между данными выясняется, что сериализовать транзакции нужно всё реже и реже. Весь смысл создания MultiPaxos, Raft, Zab заключается в том, что обычный Paxos, то есть «разослать операцию всем, получить от большинства подтверждение — уйти на аналогичный цикл подтверждение следующей операции», имеет крайне хреновую характеристику скорости подтверждения В СЛУЧАЕ КОНФЛИКТОВ, когда никто не может получить большинства голосов из-за того, что треть голосов ушло за одну операцию, треть — за другую, а последняя треть — за третью операцию, и половины не набирает никто итерацию за итерацией.

Если у тебя конфликты очень редки, то все эти усложнения не нужны, Paxos просто в 99% случаев подтверждает операцию на первой итерации. Более того, отсутствие выборов лидера позволяет устранить длительный этап выбора лидера при отказах — который прежде всего начинается только после истечения таймаута, который для георепликации должен составлять сотни миллисекунд.

Почему мне так важно вот эта скорость возобновления работы при отказах? Потому что система, которую ты описал «git-подобной» (то есть, нечто условно одноранговое с чуть более выделяющимися узлами, которые как бы выполняют роль центральных), может постоянно терять узлы, что принципиально недопустимо для MultiPaxos, Zab, и Raft, они прежде всего проектировались для БД в изначально отказоусточивых ЦОД.

Почему децентрализация? Потому что я не оракл и не гугл, мне не интересно всех привязывать к единственному серверу, как это делают они, мне интересно придумать такую систему, которая бы требовала минимум настройки, при этом максимум масштабируемости (узлы стоят где попало, а не только в ЦОД) и отказоустойчивости — той самой отказоустойчивости, от которой де-факто отказался как минимум гугл и амазон, аргументируя это тем, что «у нас хорошие админы и сети, зачем проектировать системы в расчете на отказ, который никогда не случится». Недавние инциденты с фейсбуком и амазоном показали настоящую отказойстойчивость их систем (которой нет).

byko3y ★★★★
()
Ответ на: комментарий от aist1

Поэтому, достаточно быстрые OoOE ядра всё же предусмотрены в архитектурах перспективных акселераторов приложений. Типа, 16 быстрых ядер и 1024 «минионов». Вот эти быстрые ядра, как предполагается, и будут заниматься динамическим параллелизмом

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

byko3y ★★★★
()
Ответ на: комментарий от agentgoblin

Можно вот тут в порядке офтопика более детальное пояснение, почему текущая модель доступа CPU к памяти неэффективна?

Изначально процессоры были такими, что у них вся память была устроена так же, как регистры в процессоре. К слову, так же устроена даже часть кэшей GPGPU. Чтение одного байта из такой ячейки происходит очень быстро. По этой причине в наборе инструкция x86 есть операции над значением по указателю, по этой причине в наборе инструкций раннего ARM не было возможности задать непосредственное 32-битное значение — предполагалось, что оные будут читаться по смещению, поскольку доступ к памяти бесплатный. По мере перехода на большеразмерные DRAM в 80-х очень быстро выяснилось, что доступ нифига не бесплатный, а-а-а, паника, чо делать? Влепили кэши, которые перемещали данные из DRAM в регистро-подобные ячейки, из которых они уже читались намного быстрее.

Проблема решилась, но только для операций над непрерывными блоками. Чтений одного байта тут, одного байта здесь по прежнему осталось чудовищно медленным — 50-100 циклов ядра. По-хорошему над этой памятью нельзя производить те же операции (вроде работы со связанными списками и бинарными деревьями), что и со старой RAM. Но поскольку массовая IT является чудовищно инертной индустрией, то большинство этого не поняло до сих пор.

Дальше всё стало еще хуже. Возникли многоядерные-многопроцессорные системы, интель решил «трюк удался, давайте его повторим» — и они сделали то, что нынче называется strong memory ordering, то есть, работа с памятью из нескольких ядер выглядит так, будто каждое изменение пишется прямо в оперативную память и читается другим ядром из этой оперативной памяти. Второй гвоздь в крышку гроба, от которого страдают абсолютно все современные CPU — это когерентность кэша, которая не обязательно гарантирует видимый порядок операций, но гарантирует, что если операция была сделана в одном ядре, то она будет увидена в другом ядре. То есть, каждое ядро немедленно рассылает свои операции изменения памяти другим ядрам. Естественно, эта штука никак не масштабируется при росте числа ядер, поскольку даже самая быстрая шина окажется перегружена на сотне ядер — это и есть предел для современных процессоров.

Сэкономили пять копеек в девяностых в угоду необучаемым кодерам, которые никак не могли понять, что такое кэш и распределенные вычисления — теперь нужно продавать хату, чтобы отдать техдолг, поскольку кэш и связанные с ним узлы занимают примерно 3/4 всего энергопотребления ядра. И это я только затронул вопросы кэша, а если их решить, то на первый план выйдут следующие проблемы.

byko3y ★★★★
()
Ответ на: комментарий от monk

Даже в примитивном описанном случае может поломаться, если будет завершение работы после транзакции, но до перевода на счёт получателя.

Во-первых, пополнение счёта получателя можно проводить асинхронно вообще в другом месте.

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

Например, списание со склада: будешь помечать номенклатуру? И списание с одного склада блокирует все склады?

Что? Не понял пример.

И чем велосипедная блокировка на дополнительной колонке будет быстрее стандартной?

Тем, что не блокирует сущность на время SELECT’ов и всяких проверок.

Но вот для случая продажи со склада и не очень большом ассортименте, блокировки будут почти постоянно (хлеб на 3 кассе и на 15 кассе …, пакет на 4 кассе и на 5 кассе …).

Каким образом они будут? 2 кассира одновременно проведут покупку с одним и тем же хлебом? Это ж насколько синхронно друг с другом они должны нажать на кнопку? И насколько долго должен проходить один UPDATE?

korvin_ ★★★★★
()

Всегда снижай точки отказа

точка отказа точке отказа рознь.

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

oxo
()
Последнее исправление: oxo (всего исправлений: 1)
Ответ на: комментарий от oxo

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

Если у тебя теряется 1% платежей, то от тебя уйдет 100% клиентов, а не 1%. То есть, бывает вспомогательная функциональность, без которой можно жить, а есть ядро, без которого жить нельзя. Причем, зачастую даже в микросервисах всё завязано на единственный большой монолитный сервис, вроде БД, смерть которого означает смерть всей системы. Другое дело, что отвалиться может регион — но эту проблему как раз прекрасно решают монолиты.

byko3y ★★★★
()
Ответ на: комментарий от korvin_

Во-первых, пополнение счёта получателя можно проводить асинхронно вообще в другом месте.

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

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

Вот-вот. В итоге получаем, что в одной транзакции надо производить проверку остатка (чтобы не получить списание из другого потока после проверки, но до транзакции) и обе записи (списание и поступление). У тебя вместо внешней транзакции поле updated_at. Но из-за этого появляется требование, чтобы все проверки зависели именно от него (в смысле, при любом нарушении любой проверки должно обновляться updated_at, причём в транзакции).

Что? Не понял пример.

BEGIN TRANSACTION

SELECT SUM(Количество) FROM Движения WHERE Товар = &Товар AND Склад = &Склад

Если остаток > запрошенное тогда INSERT INTO Движения VALUES (&Товар, &Склад, -&Запрошенное)

COMMIT TRANSACTION

Тем, что не блокирует сущность на время SELECT’ов и всяких проверок.

Оптимистичная блокировка в классическом блокировщике тоже не блокирует. В версионнике вообще работаешь с отдельной версией внутри транзакции.

2 кассира одновременно проведут покупку с одним и тем же хлебом?

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

И насколько долго должен проходить один UPDATE?

SELECT долго.

monk ★★★★★
()
Ответ на: комментарий от byko3y

Другое дело, что редко где такими запросами можно удовлетвориться, нужно вот здесь еще немножко записать, и тут проверить, и там добавить, и уже куча блокировок по многим таблицам, причем, под нагрузкой все они будут конфликтовать.

Это всё еще точечные транзакции, пусть и тяжелые. Неточечные — это сканирование большой таблицы или заливка таблицы. Т.е., мы трогаем O(N) блоков.

В том-то и дело, что в CoW-based SWMR блокировок на сами данные нет, поэтому нет и таких искусственных, но фундаментальных ограничений на производительность. У меня есть планы по запихиванию нижнего слоя SWMRStore из Мемории прямо в контроллер SSD, чтобы работать напрямую с флешем. Тут можно будет получить сотни тысяч TPS на запись на устройствах консьюмерсокго класса с «ценой вопроса» в $100.

Даже если какая-то часть транзакций на запись не точечная, итоговая производительность всё равно останется выше, чем у системы с «блокировками на таблицы». Просто теперь хвост распределения задержек у транзакций начнет расти.

Почему децентрализация?...

То, что ты описал, интересно само по себе, но ты или не ответил на мой вопрос, или я не понял, что ты имел в виду под «изначально проектировать алгоритмы вокруг работы с рассогласованностью».

Согласованность определяется через набор правил, которым должны соответствовать данные. Согласованность для CAP и для ACID — разная, но сводимая друг к другу. N упорядоченных элементов могут быть согласованы N! (N-факториал) разными способами, и когда мы говорим про работу с рассогласованными данными, мы должны как-то разделять такое количество вариантов на согласованные и несогласованные. Это будет, как минимум, очень трудоемко в плане просто кодирования. Не говоря уже про рантайм.

Я, например, не представляю, как это можно сделать каким-то универсальным способом, когда мы говорим об открытом фреймворке, а не об узком частном закрытом решении.

Недавние инциденты с фейсбуком и амазоном показали настоящую отказойстойчивость их систем (которой нет).

Это было эпично да. Особенно ехидные комментарии от людей вида «Эй, Амазон, как тебе тут помогли экстремальные навыки оборачивания связанных списков, которые ты меня спрашивал на собеседовании?»

aist1 ★★★
()
Ответ на: комментарий от byko3y

низкий уровень навыков программирования FPGA

У меня есть Alveo U50, с которым я иногда балуюсь. Но по большей части он просто пылится на полке. Причина в том, что прошивка для него компилируется несколько часов на моем 5950X. Этим можно было бы вполне заниматься как хобби, но у меня сейчас есть другие, более актуальные проекты. Просто «посидеть, повтыкать, поиграться» вечерами тут не получится. Это можно делать с FPGA уровня Arty A100. Там компиляция прошивки длится в районе получаса. Еще куда ни шло. FPGA печально известны своим очень долгим development iteration.

Любое что-то более-менее серьезное с FPGA — это full time job, и когда люди с ними работают на работе, у них есть бюджеты и сроки. Причем, чаще всего, жесткие (оборонка, да). Там просто некогда достигать каких-то идеалов мастерства использования, если можно просто всё непрофильное для FPGA выкинуть на присутствующее на кристалле ARM-ядро. Такие дела.

А хорошо сфокусированные хобби-проекты типа Corundum, да, могут показывать шедевры мастерства инжиниринга. Они разрабатываются по совсем другой экономической модели, нежели коммерческие проекты.

aist1 ★★★
()
Ответ на: комментарий от byko3y

А я заявляю, что таких задач нету. И я всё еще жду контрпримера.

емнип были какие-то монеты, которые специально создавались для майнинга на cpu и против майнинга на gpgpu (правда это не доказывает что там кэш играет роль)

вопрос о таких задачах можно задавать в 2 постановках: назовем их десктопной и серверной

например, для последовательности 3n+1 десктопный вариант это посчитать k-ый элемент последовательности (что ты отказываешься считать задачей, хотя это все же задача), а серверный будет «нагрузив все доступные ядра, проверить что 3n+1 возвращается к 1 для максимального числа начальных чисел за заданное время (или за минимальное время для заданного множества начальных чисел)»

а еще есть решето эратосфена

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

a--
()
Последнее исправление: a-- (всего исправлений: 3)
Ответ на: комментарий от aist1

Вот если кто напишет фреймворк, который типичные для управления состоянием задачи упакует в удобные для [пере-]использования модули, как со временем сделали с Web-ом и графикой, то — другое дело.

фреймворк — крайне подозрительное слово; если ты имел в виду «создаст методологию разработки и возможно даже формализм (а к ним — библиотеку)», то я согласен (но, кстати, для веба это до сих пор, похоже, еще не сделано)

еще добавлю, что мне было бы интересно заняться этим

a--
()
Последнее исправление: a-- (всего исправлений: 2)
Ответ на: комментарий от byko3y

Тот самый рыночек, который, дай ему волю, полностью остановит прогресс, установит монополию, и будет продавать 30 сортов говна разного цвета, периодически ротируя ассортимент цветов.

я оцениваю ситуацию в железе сейчас почти так же, как ты пишешь — но виноват тут не рыночек, виноват покупатель, согласный потреблять говно

a--
()
Последнее исправление: a-- (всего исправлений: 1)
Ответ на: комментарий от byko3y

Поздравляю, ты изобрел GraphQL.

вовсе не обязательно его (хотя емнип в конкретных реализациях GraphQL поверх базы можно обнаружить высказанные мной подходы )

a--
()
Последнее исправление: a-- (всего исправлений: 1)