LINUX.ORG.RU

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

 , ,


4

2

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


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

★★★★★

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

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

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

кстати, тут можно даже попробовать подсчитать это

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

А теперь представь, что «реальное b-tree» тоже обвешано кучей всяких оптимизаций, как и LSM

Насколько мне известно, в файловых системах деревья получается с B тоже порядка сотен. Проблема в том, что делать дерево с произвольным числом уровней при таком ветвлении чудовищно неэффективно — именно потому LevelDB взял один уровень индекса аналогичный B-tree, а вторым уровнем взял Блума. И именно потому в файловых системах обычно есть лимит по максимальному размеру файла — он происходит из жесткого лимита на число уровней дерева блоков в ФС. Потому там никаких log(N) на самом деле не существует, ведь сам логарифм является почти константой и доступ к файлу получается O(1).

Проблемы начинаются только тогда, когда я начинаю с этим деревом делать произвольные вставки и удаления (не путать с последовательным добавлением в конец), для оптимизации чего приходится снижать степень ветвления B вплоть до двойки — те же файловые системы не занимаются такими операциями, потому остаются O(1).

И да, это только «одна из оптимизаций» — но сам LSM тоже является по сути оптимизацией дерева. Деревья и графы — плохие, последовательный доступ — хороший. Так сделано всё современное железо.

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

а вот хрен тебе

Ой, ну ладно тебе. Человек ляпнул, не подумав. Ночь на дворе глубокая. Чего ты к словам привязался?)

Есть такая штука: RocketChip

Суть. Микропроцессоры и SoC можно описывать на HDL — Hardware Description Language. Например, на Verilog. А можно пойти на уровень выше, и описывать на Hardware Construction Language. Программа на HCL является метапрограммой для HDL.

RocketChip умеет генерировать SoC на основе RISC-V под заданные нами конфигурации: размеры кэшей, наборы инструкций, наличие контроллера DDR, дополнительные акселераторы, периферия на шине и т.п. HDL будет сразу оптимизирован под конкретную плату/FPGA или заточен под ASIC flow. Причем результат будет сразу correct by construction.

RocketChip написан на Scala и представляет из себя встроенный (в Scala) DSL — Chisel3. А сама техника HCL называется design space exploration.

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

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

Но если у тебя набитый разными индексами Postgres, то вылизывать каждый из них таким образом будет слишком обременительно.

ну... я бы для начала попробовал бы потребовать столько RAM, чтобы все адреса горячих данных на диске попадали бы в RAM

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

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

если ты их не встречал — то это аргумент

а еще интересней, если у тебя есть аргумент, почему их не будет на практике

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

Ты много говоришь про распределенность и масштабирование, и я понимаю твои намеки. Я намекаю на то, что нам нужно сначала научиться по-максимуму использовать локально доступное железо. Т.е. заполнить нишу scale-up и scale-down. И только потом идти в scale-out. Это просто общая стратегия, а не прямое руководство к действию

«Здесь и сейчас» проще и с гарантиями можно получить только scale-up, то есть, купить жирнее железо и не париться распределенкой. Ровно как здесь и сейчас проще не исправлять баг, а подпереть его костылём. Но в более длительной перспективе масштабирование «вверх» дает всё меньше и меньше эффекта, скорость у одного ядра не бесконечна, а масштабирование «вширь» ничем не ограничено — именно к этому и апеллировали многие ораторы в этом треде. Моя претензия к ним заключалась в том, что на самом деле микросервисы — это масштабирование курильщика, а масштабирование здорового человека должно начинаться с данных. Но ты предлагаешь крутить данные одним ядром — я считаю, что это может быть базой, как RocksDB, но не конечным решением. На этом аскетичном фундаменте конечное решение еще лепить и лепить очень долго, проблемы распределенной обработки данных оно само по себе не решает, а ведь именно распределенная обработка обычно и является камнем преткновения, а никак не выбор LevelDB/RocksDB/SQLite/BerkleyDB/LMDB, Docker Swarm или Kubernetes, прямой доступ или ФС, JSON или Protobuf.

Развитых библиотек прикладных типов данных на EC K/V за 15 лет так и не появилось из-за того, что народ счел эту затею непрактичной и вернулся к «шардингу»

Что значит «развитых»? Ты, наверное, хотел сказать «популярных и интенсивно поддерживаемых» — а это уже немножко другая штука: «развить идею» и «написать кучу тупых прокладок к популярным инструментам» — это не одно и то же. Я считаю, что PSO по сравнению с питоновым мейнстримом multiprocessing/message queue — это небо и земля, что даже тот уровень, который я реализовал — это весьма «развитая библиотека», но необходимый объем тупой работы для поддержки всех современных питоньих костылей для меня неподъемен. Даже гугл забросил в свое время подобную затею, хотя у гугла немножко больше ресурсов, чем у меня.

Когда я смотрел работу по распределенным БД, то меня поразил объем требований по знанию безнадежно отсталого наследия — это главным образом оптимизация SQL. Как ты собрался развивать eventual consystency key-value storage, если первый же клиент к тебе придет с вопросом «как тут SQL-запрос выполнить?». SQL в принципе никогда не разрабатывался ни под key-value, ни под eventual-consistency, они не совместимы. Ну и как тогда ты сделаешь эту штуку популярной? Вот «выполнить NewSQL запросы независимо на нескольких шардах» — это людям понятно, это допустимо. А key-value с eventual consistency — это какая-то маргинальщина для писателей сайтов-лендингов, нам такого не надо.

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

встроенный (в Scala) DSL

это называется eDSL и с моей точки зрения одним из важных критериев качества языка программирования общего назначения (Scal-ы в данном случае) является удобство создания в нем eDSL

Scal-у я последний раз смотрел лет 7 назад (сорри), и тогда она мне казалась переусложненной даже на уровне синтаксиса

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

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

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

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

чтобы «быстро»

я бы сказал «чтобы DRY»

меня сильно удивляет, что клиент и сервер — это отдельные программы, а не 2 target-а мейкфайла одного дерева исходников (скажем, когда я читаю программирование для zeroMQ)

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

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

где можно прочесть «что ты хотел сделать, что получилось, что не получилось или сил не хватило» ?

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

ну... я бы для начала попробовал бы потребовать столько RAM, чтобы все адреса горячих данных на диске попадали бы в RAM

Я бы тоже потребовать много RAM губу бы раскатал, да еще как раскатал-бы! Но память и для других вещей нужна, так что не раскатываем.

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

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

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

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

тут можно написать очень много, но я максимально сокращу мысль

если ты делаешь продукт для программистов, то у тебя будут программисты-клиенты и программисты-конкуренты

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

однако это не мешает иметь какой-то свой маленький альтернативный софт, который работает только в твоем облаке и только на твоем железе — и это кстати очень интересная тема (там, например, возможны вариации на тему NaCl)

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

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

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

Не, это просто один частный эпизод. Если говорить про параллельную мультипроцессорную обработку, то я предлагаю использовать функциональные структуры данных (ФСД). Только не те, что идут вместе со Scala, а более развитые в плане моделирования моделирования прикладных данных (таблицы в разных ипостасях, всякие индексы, включая постранственные, распределения вероятностей и т.п.).

ФСД интересны тем, что позволяют практически забесплатно получить эквивалент wait-free snapshot isolation аж над EC (это еще не транзакции). Плюс кучу дополнительных фишек типа графа версий. В общем, и функций много, и настройки по консистентности получаются довольно гибкие. ФСД, разумеется, имеют фундаментальный оверхед, выражающийся в том, что O(1) превращается в O(log(N)). Но там можно этот оверхед амортизировать оптимизациями. Параллельность имеет свою цену вопроса.

Серьезное ограничение ФСД, о которых обычно не говорят, — это необходимость сборщика мусора. В случае RAM это может быть обычный детерминированный GC через подсчет атомарных ссылок. А вот в распределенном случае всё становится сильно сложнее. Нужны атомарные идемпотентные счетчики, и строгая консистентность для них. Можно, конечно, делать обычный сканирующий GC, но это тоже некое ограничение по масштабированию. Другие (не-ФСД) дизайны тоже требуют GC так или иначе.

SWMR-CoW — это просто режим работы ФСД, при котором можно атомарно сбрасывать состояние RAM во внешнюю память (с минимумом прослоек). При этом там тоже возможны оптимизации. Например, писатель может сам быть внутри параллельным (и, например, молотить данные в 64 руки), но вот коммититься это будет всё одновременно, а не индивидуально. Отсюда и Single Writer.

Если же нет задачи сбрасывать коммиты на диск (inmem), или можно работать над тем же RocksDB или облачным K/V, то возможен и полноценный MWMR с множеством параллельных пистателей, коммитящих независимо. Но и стек данных будет уже куда более тяжеловесным. Меня просто сейчас интересует scale-down: запихнуть SWMRStore прямо в SSD, чтобы работать сразу с флешем, минуя FTL. Он для этого идеально подходит.

----

Чтобы пресечь потенциальное недопонимание. ФСД сами по себе не масштабируемы в том смысле, в котором это обычно понимается. Каждая запись в ФСД создает новую версию всего датасета (снепшот), которую могут увидеть читатели как только они получат ID корневого блока ФСД для этого коммита. Эта часть — 2PSet CRDT и масштабируема до сколько сможешь.

А вот если надо сливать версии (merge) в единую историю, то это уже будет масштабируемо на столько, на сколько «строгими» будут правила слияния версий.

Удаление версий из ФСД требует сборки мусора и мастабируемо на столько, на сколько масштабируем сборщик.

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

где можно прочесть «что ты хотел сделать, что получилось, что не получилось или сил не хватило» ?

Можно, читай. Собственно, на главной странице все ссылки:
https://github.com/byko3y/python-shared-objects

Я сейчас сам как бы прикидываю, и думаю «как я вообще расчитывал на то, чтобы это взлетело?». Это же получается что-то вроде запорожца с реактивным двигателем — красиво, но прикладной ценности не имеет.

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

Что значит «развитых»?

Имелось в виду покрытие пространства проблем пространством решений (или хотя бы заявка на), т.е. фундаментальность подхода. Активность в github при этом – вопрос второстепенный.

В этом плане твой PSO – развитый, но он несколько из иной области и, извини, но…, безнадежный. Потому, что это CPython и его runtime.

Чего я ожидал от NoSQL? Предположим, на дворе у нас 2010-12 годы (к вопросу о том, что у нас есть в наличии). Вот, есть у нас, скажем, Cassandra. Всё хорошо, но мы хотим хранить в ней видеоролики. Ну, вот, хотим. Так надо. При этом надо, чтобы читать такой объект можно было с любого места (перемотка). Нужна т.н. «нереляционная схема» для файл-подобного объекта над K/V хранилищем. Cassandra не умеет в сканирование, поэтому просто считать линейно возрастающий набор ключей нельзя. Нужно городить дополнительно индексную структуру, которая сгенерирует требуемый набор точечных запросов. Такая индексная структура должна уже обновляться транзакционно если мы хотим, например, дописывать в конец такого файла.

Вот появления подобных библиотек «нереляционных схем» для различных прикладных случаев я и ожидал по аналогии с тем, как мы можем использовать Hibernate для RDBMS. Но индустрия пошла по пути polyglot persistence, создавая для каждого прикладного случая своё оптимизированное хранилище. Мотив понятен и рационален. Вот только подход такой не масштабируем в инженерном плане (каково это, тащить в проекте с дюжину разных хранилищ от разных вендоров, которые не дружат друг с другом от слова «совсем»?). Я извиняюсь, но saga pattern (привет, микросервисы с состоянием, как дела?) – это убожество.

Касательно PSO и CPython. Я долго искал возможность встроить Меморию в <ваш_любимый_язык_программирования> и зарекся это делать впредь. Причина в том, что сами рантаймы этих языков не предназначены ни для ФСД, ни для STM. И если с интеграцией с типами языка еще всё более-менее, то, вот, с поддержкой файберов уже всё плохо.

Я в конце-концов пришел к идее, что под Меморию нужно делать свой язык программирования(x), изначально построенный над асинхронным рантаймом Мемории, который обеспечит простую безопасную работу с контейнерами из прикладного кода и DSL. Рантайм в Мемории Erlang-подобный. Worker threads, между ними мессаджинг и разделяемые ФСД. Конкурентность – через файберы.

(x) Речь здесь идет не о полноценном ЯП (типа, вот, С++ плохой, поэтому мы делаем Rust), а о безопасном (xx) семантическом (xxx) подмножестве С++, сделанном поверх интерпретируемого байт-кода, AOT-транслируемого в С++ и в машинный код. Секретный соус в том, что кодовую модель (байт-код, AST, метаданные, сборки и прочее) можно делать средствами самой Мемории. Она спокойно это всё потянет.

(xx) ARC для всего, немного локальной стековой аллокации, без разделяемых данных между тредами (кроме ФСД), без pointer arithmetic, без UB (контроль переполнения чисел) и т.д.

(xxx) синтаксически оно всё может сильно отличаться от С++, иметь кучу сахара, поддержку разных DSL, метапрограммирования уровня AST и т.д.

Короче, вот этот вот язык вполне может стать языком для «микросервисов с состоянием».

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

так вот, в твоем случае (насколько я его понимаю) ...

Ты всё понимаешь правильно. В моем случае проблема осложняется еще и тем, что я изначально отдаю в OSS слишком много. Практически «всё». Мои потенциальные компетиторы, если захотят, уложат меня на лопатки в два счета. Но дело в том, что я сам не собираюсь делать облачные компании, хотя и не исключаю такой возможности. Мемория — не единственный и не основной проект для меня. Просто сейчас он занимает всё моё свободное время.

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

а откуда взялось (странное на мой взгляд) решение не делать полноценный ЯП?

язык «изначально построенный над асинхронным рантаймом неважно-там-чего» вполне может быть полноценным ЯП на мой первый взгляд (особенно если рантайм Erlang-подобный)

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

В целом, если брать рынок в целом - то да.

Идеологически же, микросервисы нужны для того, чтобы выделить логические сущности в кодовую базу с минимальной связанностью кода (в эволюционном подходе DRY идёт лесом) для того, чтобы можно было их развивать независимо друг от друга. И вот тут как раз и нужен хороший архитектор (кто продумает весь ландшафт), разработчик (который сможет реализовать логическую сущность с обратной совместимостью - это важная функция полезности для МС в эволюционной теории), и хороший devops (который обеспечит CI/CD).

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

Как это понял рынок? Давайте каждую таблицу засунем в Django/Rails/Ravel/Express/Spring/ASP и будем колотить под это REST с помощью безмозглых студентов, рассказывая им о прекрасной гибкой разработке и прочем SCRUM. А на действия не связанные с CRUD у нас будет ещё и API Gateway для 2-N МС, чтобы собрать это всё безобразие в логическую сущность. И пусть DevOps’ы з**ся выстраивая CI/CD где есть строгая связанность даже старта сервисов.

small-entropy
()
Ответ на: комментарий от a--

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

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

Чем, кстати, мне очень нравится CPython, так это своим симбиозом с C/C++. Там, где Java-программисты в поте лица будут переписывать всё на Java, питон-программисты просто напишут байндинги. История показала, что ничего на Java не переписали. Но вот runtime в CPython обречен. Он, я считаю, неисправим в плане нормальной поддержки параллельного программирования.

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

А, понял. Да, это полноценный ЯП в смысле полноты по Тьюрингу. Просто он мыслится как «адаптация» С++ к проблеме продуктивной работы с данными, а не как самостоятельный универсальный ЯП.

С++, из-за минного поля UB, для работы с данными не годится как продуктивный язык.

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

«адаптация»

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

и да, подход с завязкой на с++ полностью одобряю

«для всего» («arc для всего» ) это дохлый номер, через 5-10 лет ты сам не рад этому будешь

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

«для всего» («arc для всего» ) это дохлый номер, через 5-10 лет ты сам не рад этому будешь

А какая альтернатива? Tracing GC? Сборщик мусора нужен детерминированный, так как будет использоваться высокоскоростной асинхронный ввод-вывод, а он сильно не дружит с паузами GC. Еще RAII нужен.

Еще будут активно использоваться арены и пулы, т.е. общая модель памяти приближается к Erlang-овой, просто не так «красиво».

Идея всего этого дизайна в том, что весь heavy lifting в плане прикладных данных возлагается на Меморию и обвеску вокруг неё. На «кучу» там остается совсем немного. Так что и трассирующий GC, наверное, справился бы прекрасно (при условии, что RAII сохранится). Но я пока туда не смотрю.

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

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

а gc мы еще обсудим

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

я уж точно не фанатик gc, но точно не хочу делать язык, в котором лет через 10-20 будут такие же facepalm-ы на тему «ну нафига они это прибили гвоздями» как в С и С++

а после arc тебе придется еще gc-шить циклические ссылки (хотя вроде были работы на тему «как этого избежать с помощью системы типов»)

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

Я в этом плане иду по пути Swift. Там против циклов просто слабые ссылки. Я понимаю, что «продуктивный язык» и слабые ссылки — это ну... такое. Но, как есть. Дизайн пока что не без изъянов.

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

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

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

сами по себе слабые ссылки нужны (для кэширования) даже при полноценном gc

а вот циклы тоже можно было бы собирать с помощью gc

кстати, ведь arc вроде О(N) от размера структуры данных, которую ты освобождаешь — то есть если тебе нужно освободить бинарное дерево размером 1ГБ, рандомно расположенное в современной RAM, то тебе секунд 10 придется по нему попрыгать — это ведь серьезная задержка

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

то есть если тебе нужно освободить бинарное дерево размером 1ГБ, рандомно расположенное в современной RAM, то тебе секунд 10 придется по нему попрыгать — это ведь серьезная задержка

Да. Но, прежде, чем его освободить, его нужно сначала создать. А это тоже долго (еще дольше).

Если мне нужно будет выделить 1GB дерева, которое я буду удалять всё и сразу, то оно, скорее всего, будет выделено в арене.

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

каково это, тащить в проекте с дюжину разных хранилищ от разных вендоров, которые не дружат друг с другом от слова «совсем»?

«Здравствуйте, я девопс, какое несовместимое хранилище от нового вендора мы добавим в систему сегодня?».

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

Твоя ошибка в том, что ты подразумеваешь, будто этот подход будет работать. Ну то есть будет, но очень плохо, очень медленно и неэффективно. В этом плане ОПТИМИЗИРОВАННЫЕ многопоточные, многозадачные, и распределенные системы имеют одну схожую черту — зачастую небольшое изменение алгоритма требует серьезного переписывания. Но если неэффективность многопоточных блокировок имеет стоимость в несколько тысяч циклов, то в случае распределенных систем накладные расходы составляют целые миллисекунды — именно потому я и пишу, что на самом деле массовое микросервисостроение совсем не масштабируется по нагрузке, оно борется только с проблемами, которое само и создает.

saga pattern (привет, микросервисы с состоянием, как дела?) – это убожество

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

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

Тоже к этому пришел. Пытаться прикрутить к 30-40-летнему безнадежно устаревшему ЯП новые модели — абсолютно бесполезная работа (привет фанатам C++). И с питоном дело даже не в динамической типизации — Clojure показала, что можно и с ней очень красиво делать персистентные структуры с транзакциями.

Рантайм в Мемории Erlang-подобный

Кстати, а почему не Erlang?

ARC для всего, немного локальной стековой аллокации, без разделяемых данных между тредами (кроме ФСД), без pointer arithmetic, без UB (контроль переполнения чисел) и т.д

Это будет странно звучать от меня, но «Rust?».

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

И пусть DevOps’ы з**ся выстраивая CI/CD где есть строгая связанность даже старта сервисов

Это эпично, на самом деле. Есил у сервисов есть порядок старта, то они принципиально неотказоустойчивы — если выйдет из строя часть сервисов, то после перезапуска зависящие сервисы могут просто не заработать.

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

Твоя ошибка в том, что ты подразумеваешь, будто этот подход будет работать.

Ты меня всё еще не слышишь. Я говорю именно про моделирование данных под свойства конкретного хранилища. Есть хранилище, которое дает только точечные запросы. Нужно получить линейное сканирование и, желательно, еще и с параллельным чтением диапазонов и параллельной записью (для скорости). Что-то функционально похожее на ORM, но только для NoSQL. Вот этого не было и не возникло.

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

на самом деле массовое микросервисостроение совсем не масштабируется по нагрузке, оно борется только с проблемами, которое само и создает.

В этом мы с тобой абсолютно согласны.

Тоже к этому пришел. Пытаться прикрутить к 30-40-летнему безнадежно устаревшему ЯП новые модели — абсолютно бесполезная работа (привет фанатам C++).

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

Кстати, а почему не Erlang?

Это будет странно звучать от меня, но «Rust?».

Я там выше написал, что хорошая совместимость с существующей и перспективной инфраструктурой (х) и кодовой базой С++ – императив. В первую очередь, с кодом самой Мемории, которая процветает на С++ и собирается это делать и дальше. Рантайм Мемории хорошо вписывается в рантайм С++, всё работает с файберами, включая средства разработки и большую часть библиотек. Просто С++ – не продуктивный язык, и «херак, херак – и на продакшен» на нем не получится. А надо.

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

Я С++ рассматриваю как низкоуровневый и промежуточный язык, которому нужно просто продуктивное подмножество с resynthaxing для удобства использования eDSL.

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

Clojure показала, что можно и с ней очень красиво делать персистентные структуры с транзакциями

Datomic, кстати, SWMR, но не CoW. Его архитектура очень похожа на ту, которую я тебе описывал выше для ФСД над EC K/V (EC для блоков и SC для истории коммитов).

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

Datomic, кстати, SWMR, но не CoW. Его архитектура очень похожа на ту, которую я тебе описывал выше для ФСД над EC K/V (EC для блоков и SC для истории коммитов)

https://www.usenix.org/conference/nsdi12/technical-sessions/presentation/bala...

Аналогичная БД, которая создана примерно в то же время, что Datomic.

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

А, CORFU, знаю))

Да, идея такая. Но CORFU это не совсем Datomic. То, что сейчас близко к CORFU — это Zoned Storage (ZS).

ФСД — это фундаментально больше, чем просто лог операций, потому что версии, хранящиеся в логе, сразу материализованы и немедленно доступны для чтения. Обычная же СУБД с WAL пишет данные дважды: один раз в основное хранилище, а второй раз — в WAL. ZS делается для WAL и для LSM, а не для SWMR-CoW (к моему большому сожалению). «Цена вопроса» такого функционального лога — это то, что лог размера O(M) превращается в лог размера O(M*log(N)), так как каждый апдейт — это O(log(N)), где N — размер датасета. Материализованные версии даже в ФСД — дорогое удовольствие :)

SWMRStore в Мемории — это по сути этот самый виртуальный кольцевой буфер над линейным массивом блоков. Версия — снимок всего диска, для которого хранятся только измененные блоки. Новые блоки никогда не перезатирают уже записанные предыдущими версиями, пока их версии не будут явным образом удалены. Над всем этим — функциональный аллокатор блоков, умеющий в откат на предыдущую consistency point.

У меня есть планы сделать SWMRStore модульным, нарезать на слои и всё хорошенько документировать «от и до». Будет учебное пособие по хранилищам на основе функциональной модели данных.

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

Да. Но, прежде, чем его освободить, его нужно сначала создать. А это тоже долго (еще дольше).

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

Если мне нужно будет выделить 1GB дерева, которое я буду удалять всё и сразу, то оно, скорее всего, будет выделено в арене.

а если тебе потребуется срубить 1ГБ-веточку 2ГБ-дерева? деревья ведь они такие

вообще про gc нам вдвоем-втроем реально наговорить еще на 20 страниц, так что лучше это выделить в отдельный пост

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

gc для ФСД нужен настоящий, или хватит подсчета ссылок?

У меня есть планы сделать SWMRStore модульным, нарезать на слои и всё хорошенько документировать «от и до». Будет учебное пособие по хранилищам на основе функциональной модели данных.

ммм... а вот кто-то тебе коммитит? тут (в прошивке для флешки) возможно наоборот, стоит рассмотреть закрытие кода

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

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

Это будет странно звучать от меня, но «Rust?»

ответ зависит от того, зачем берется язык — ради так скажем бэка или фронта

в с++ есть concurrency memory model — возможно что ужасная, но есть — а в расте ее нет, так что как бэк с++ получается лучше

если же рассматривать фронт, то:
«rust» — «с++» = «traits» + «borrow checker»

borrow checker для продуктового языка не особенно нужен (он заменяется arc & gc), а traits вполне делается поверх с++ (это широкий указатель; интересно, кто-то сделал такую либу для с++?)

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

С++, из-за минного поля UB, для работы с данными не годится как продуктивный язык

я бы назвал по-русски «продуктовый» или прямо продакшен, а по английский production language, а не productive language (последнее название мне не нравится, так как отдает душком)

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

интерпретируемого байт-кода

а можно ли взять dotnet-овский байткод? у него вроде есть возможность pin-ить данные, не давая gc их перемещать, кидать структуры на стек и т.п., нужное для unmanaged

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

Пытаться прикрутить к 30-40-летнему безнадежно устаревшему ЯП новые модели — абсолютно бесполезная работа (привет фанатам C++).

c++ по большей части (практически за исключением UB) не безнадежно устаревший, а хаотичный

я тебе в этой теме уже задавал вопрос насчет языка — так вот, попробуй подумать на тему, например, «какие новые модели должен поддерживать приличный ЯП» и изложить свои мысли

как бонус можно рассказать, где с++ противоречит этим моделям — это особенно интересно

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

Я, например, смотрю в сторону плотной интеграции асинхронного программирования на базе алгоритма RETE не только в рантайм, но и в сам язык.

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

a--
()
Ответ на: комментарий от a--

а если тебе потребуется срубить 1ГБ-веточку 2ГБ-дерева? деревья ведь они такие

А если еще из тыщи потоков одновременно? Давай не будем сфероконировать в ваккууме. Такие сложные структуры данных дизайнятся под конкретные требования, а не в общем случае. В «общем случае» будет все как в Java с большими кучами — печально (несмотря на все усилия по подготовке и выпуску все лучших и лучших дворников).

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

gc для ФСД нужен настоящий, или хватит подсчета ссылок?

Опять же, «зависит от». Трассирующие сборщики принципиально не масштабируемы на большие кучи. Потому, что время сборки в худшем случае — O(N). Что самое плохое, ФСД — это и есть худший случай для для generational GC. Последние, в базовом варианте, работают хорошо только тогда, когда большая часть создаваемых объектов удаляется быстро. Т.е. когда permgen или маленький, или просто статичный. Это, в первую очередь, сетевые приложения с вынесенными из кучи перманентными разделяемыми данными (кэши, СУБД и т.д.). А у нас сразу по условию задачи большая куча на «терабайты».

В общем, если создавать какой-то специфический сборщик именно для ФСД (у нас гарантированно деревья, даже не DAG), то, может быть, что-то и получится. Но высокая пропускная способность такого GC будет компенсироваться трудностями выдерживания QoS по задержкам.

ARC будет медленнее (лишь в теории, т.е. при условии, что трассирующий GC получится сделать), зато сильно проще, стабильнее и детерминированный. Я бы трассирующий GC давал как дополнительную опцию, отключенную по умолчанию.

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

ммм... а вот кто-то тебе коммитит? тут (в прошивке для флешки) возможно наоборот, стоит рассмотреть закрытие кода

Тут всё сильно сложнее, поскольку речь уже идет о новом классе устройств — SmartSSD, и они пока что существуют лишь как концепция + экспериментальные реализации. Для них пока что так же нет и интерфейсов прикладного уровня.

Если говорить о существующем стеке блочных устройств в OS, то, чтобы его не ломать об колено, а переиспользовать, можно для начала ввести в протокол состояние иммутабельности блока. Благодаря CoW, закоммиченные блоки становятся иммутабельными на уровне блочного устройства. Поэтому их случайная перезапись будет невозможной. Одно только это уже сразу существенно повысит надежность.

Перенос же функций обработки на SSD — это отдельная история, которую еще прорабатывать и прорабатывать (Storage DPU). Там есть фундаментальное ограничение — память не любит тепло, которое выделяется при вычислениях. Но потенциал, всё равно, хороший (in-memory computing(*), всё такое).

(*) Это не in-memory DBMS, а перенос вычислений прямо в чипы памяти (DRAM, NAND). Например, фильтрации/суммирования при линейном сканировании. Или rank/select для символьных последовательностей. И т.д.

Что касается закрытия кода, то Мемория это подразумевает. Можно поставлять как бинарные storage engines, так и отдельные контейнеры. Но в случае SmartSSD будет в итоге что-то более фундаментальное, типа специализированной под это дело OS (или VM) .

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

а можно ли взять dotnet-овский байткод?

Можно (если брать как идею для дизайна, а не как конкретный формат), но не нужно.

То, о чем я говорю, это не байт-код в привычном нам понимании. Это просто хранимый IR для концептуально простой стековой машины, с которого можно быстро (типа, 1-в-1) сгенерировать семантически эквивалентный текст С++ (для AOT-компиляции). Этот IR нужен, в первую очередь, для различных DSL, которые для боевого режима будут AOT-компилироваться в нативный код. А для режима разработки — интерпретироваться. JIT тоже, в принципе, возможен, если нужен.

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

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

копилот это же вроде обезьянья попытка (т.е. нейросетка), а вовсе не то направление, про которое ты пишешь в https://memoria-framework.dev/docs/d-phil/ai/

Это совсем про другое. Нейросетевики сейчас уперлись в концептуальные ограничения собственного метода черного ящика. Когда модели стали уже достаточно сложными, чтобы триггерить неподготовленного внешнего наблюдателя на тему «подлинности переживаний чат-бота». Метод черного ящика не предполагает со стороны разработчика понимания того, как же оно [не]работает. Поэтому нейросетевикам будет трудно доказать (разгневанной толпе, пришедшей их линчевать), что конкретная нейросеть сознанием не обладает и является просто высокотехнологическим говорящим чучелом. Если же стоит задача или повысить степень человекоподобия диалогов такого говорящего чучела, или вообще аргументированно показать, что оно [не]обладает сознанием, то нужен метод белого ящика. Вот о нем там и речь, по приведенной тобой ссылке.

Я же Copilot упоминал в другом ключе. Есть проблема programming in large (PnL), которую Java решал для своего времени на много лучше, чем C++. Поэтому Java является более продуктивным языком программирования, чем C++, при написании больших приложений.

В общем, и если коротко, то PnL не решается чисто языковыми методами. Идеального языка программирования не существует, и всё, что нам физически доступно здесь — это бороться с описательной сложностью привлечением вычислительных бюджетов. Это, в частности, означает использование статических анализаторов, продвинутых инструментов сборки, Copilot-подобной активной кодовой аналитики и т.д. Всё, что может разгрузить человека при работе с большими кодовыми базами. Которые, к слову, растут со временем суперлинейно. Современная программа — штука куда более многомерная, чем это было в 80-е. А вот тулинг С++, к слову, там и застрял. Современная среда разработки должна строиться над развитой мультимодельной базой данных и тесным образом интегрироваться с системой метапрограммирования ЯП.

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

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

С++ уже движется в направлении value-based metaprogramming. Я там сообщением выше дал ссылку на свои эксперименты по интеграции в Clang полноценных метафункций, через которые (имеющие и доступ к AST, и интегрированные с системой сборки над мультимодельной событийно-ориентированной БД) можно уже «подцепить к себе в компайл-тайм почти все что угодно напрямую», не насилуя совершенно не предназначенный для сложного метапрограммирования инструмент шаблонов.

aist1 ★★★
()