All streams
Search
Write a publication
Pull to refresh
63
0.5
Михаил @michael_v89

Программист

Send message

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

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

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

Видимо надо еще подробнее объяснить.

1. Языки в проектах, где я работаю, и вообще многие языки, не поддерживают hot reload на продакшене. Поэтому любой деплой означает полную выгрузку процесса из памяти со всеми данными. Деплой происходит несколько раз в неделю.
2. Бизнес не хочет терять данные несколько раз в неделю, и вообще ни разу. Особенно связанные с финансами. И не хочет платить за проверку логов и исправление при их потере.
3. Бизнес хочет предоставлять аналитикам доступ к базе, где им нужны актуальные данные на текущий момент, которые они получают с помощью произвольных SQL-запросов.
4. Бизнес хочет иметь для себя админку, где он может задать фильтр по статусу заказа и получить актуальный список заказов в этом статусе. Бизнес хочет иметь актуальные данные когда ему нужно, а не в конце дня.

И всё это решается одним простым вызовом "save()" после внесения изменений в переменную (и локом на id при загрузке). Мне не надо медленно и неэффективно анализировать логи, не надо писать отдельный расчет баланса после закрытия магазина, не надо объяснять бизнесу, что он должен забить на некорректные данные, и не надо решать проблемы с бизнес-логикой в джобах. Производительности хватает для довольно больших нагрузок, а проблемы с масштабированием если и возникают, то на масштабах Тиндера и Амазона, до которых развивается не каждый бизнес. Именно поэтому я выбираю такой подход - потому что для этих задач и в этих условиях он подходит лучше. Да, ваш подход производительнее ценой меньшей консистентности данных и дополнительной работы программиста, но повышать производительность мне нет необходимости, поэтому преимущества этого подхода в моей работе ничего не изменят, и останутся только недостатки.

Если бы я знал, что спор идёт про N+1

Цитаты и возражения про N+1 написаны в самом первом комментарии этой ветки. Этого достаточно, чтобы знать.

архитектура любого приложения на акторной модели — во время написания первой строки кода с N+1 буквально закричит

Код, который вы показали в статье, ничего такого не кричит. А кричит прямо противоположное - чтобы получить значение поля из сущности, надо к ней обратиться по одному id.

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

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

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

"Неувиливание" было бы сказать "Конкретно с заказами имеет смысл копировать состояние товара на момент заказа, но в целом вы правы, N+1 в некоторых сценариях возможна и в моем подходе". А вы вместо этого сказали "А я ваш пример по-другому сделаю, бе-бе-бе", а про основную тему ничего не сказали, хотя пример был нужен только для демонстрации этой темы. Единственная причина существования N+1 это запрос информации с удаленного сервера по единичному id несколько раз. Если у вас есть такая операция, значит эта проблема возможна, и это не зависит от того, база у вас на этом сервере или не база, а чтобы ее избежать, надо специальным образом проектировать взаимодействие. Непризнание этого это и есть то, что я назвал увиливанием.

у человека в руках молоток, и он хочет им заколачивать всё вокруг

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

Спор в этой ветке идет о проблеме N+1 и утверждении, что она появляется из-за чтения из базы, а если читать из процесса на другой ноде, то ее не будет. Это ложь. Если мы привязываем процессы к id сущностей, значит хотим в каких-то сценариях получать информацию, имея только id сущности. Единственный способ ее избежать это загружать информацию сразу по нескольким id в одном сетевом запросе от одной ноды к другой. Никакие деревья супервизоров на этих нодах не изменят механизм работы сети.

ElasticSearch есть у 90%

"В каких-то нишах они подходят и используются, как и любой инструмент."

Вы не понимаете бо́льшей половины того, что я говорю

"В тексте этого действительно нет"
"Я легко мог бы и тут показать, как такие задачи решаются без реляций, но не буду"
Наверно потому что вы говорите не всё? И не способны оценить, как выглядят ваши слова для собеседника?

а я использую лексикон для домохозяек

Может в этом и причина, что вас не понимают?

Вы критикуете Пастернака, которого не читали.

Мне достаточно того, что об этом сообщает тот, кто его читал. Вы говорите "надо по камерам отслеживать все неоплаченные колбасы, это медленно и неэффективно", и я вам верю.

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

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

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

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

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

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

В-третьих, у вас реляционность головного мозга.

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

С намеренно реализованной системой транзакций, которая имеет защиту от сбоев в середине записи
транзакционное обращение к состоянию процесса

Как я написал в самом начале, я говорил про транзакционную запись на диск для защиты от сбоев. Что означает 1) для одного процесса отсутствие ситуации, когда записалась только половина нового имени пользователя, а потом произошел сбой, и процесс после перезапуска возвращает в поле name половину старых данных и половину новых, и 2) для нескольких процессов отсутствие ситуации, когда при отправке статьи на модерацию надо создать новую запись ModerationRequest и поменять Article.state = ON_MODERAION, но произошел сбой, и состояние ModerationRequest сохранилось, а состояние Article нет. Бизнесу такие ситуации почему-то не нравятся, и он просит сделать так, чтобы их было как можно меньше.

В любом языке, причем. Это же контракт.

Я не знаю, что вы имеете в виду, в тех языках с которыми я работал, никакие логи при записи нового значения в переменную state магически сами не пишутся.

Потому что вы не можете просто разнести кэш

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

Это утверждение основано на «с диском я работал, и мне нравится»

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

я прямо в него добавляю товары

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

Вы загрузили всех Developer на одну ноду, потом выводите список задач на другой ноде, у каждой задачи надо вывести имя ответственного разработчика. Если человек поменял имя (например, девушка вышла замуж), должно выводиться текущее имя, если человек уволился, должен выводиться статус, что он уволился, поэтому копированием состояния при создании задачи вы это не решите. При выводе будет точно такая же проблема N+1. Аналогично список статей на Хабре. Пользователь поменял ник или аватарку, должно выводиться текущее состояние.

При создании заказа с вашим подходом она тоже возможна, если есть задача, чтобы "add to cart" поддерживал добавление нескольких товаров сразу. Аналогично несколько категорий в новости, хабы в статье на Хабре, и любые другие запросы на создание с множественными идентификаторами. Поэтому утверждение, что в вашем подходе ее нет потому что нет работы с базой, не соответствует действительности.

Процесс, конечно же, имеет механизм транзакций.

Ну вот с этого и надо было начинать. "Не используйте одни транзакции, используйте другие".

Нет конечно, реализаций Event Log’а полно́ на любой вкус и цвет.

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

И не бывает двух процессов для одного товара (если только этого зачем-то специально не захотел программист).

У нас 2 ноды, которые обрабатывают веб-запросы, обе запросили товар 321, процесса для которого еще нет. Они обе выполняют state = :db.read(321), запускают для него receive_loop, и записывают в свою область памяти, обозначенную в коде названием master, разные pid. Я верю, что Эрланг имеет какие-то средства для защиты от этого, но из вашего кода они неочевидны.

диск — хорошо, память — плохо

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

Медленнее, у́же бутылочное горлышко, в разы хуже и сложнее масштабируется, но — лучше.

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

Нет у меня никакого :idList

Я именно про это и говорю. Нет idList, значит есть N запросов по сети к ноде с товарами от ноды, которая работает с заказом, и по этому критерию ваш подход ничем не лучше базы. Джаваскрипт тут ни при чем. Сart тоже ни при чем, я говорю про отображение уже созданного заказа.

Чтобы отправлять к ноде с товарами не N сообщений, аналогичных по действию SELECT name FROM product WHERE id = :id, а одно SELECT name FROM product WHERE id IN (:idList). Иначе у вас такой же N+1, и работает он примерно столько же времени, потому что сеть работает одинаково что для базы, что для ноды Эрланга.

его сначала нужно откуда-то (из базы) достать. Отсюда все эти N+1 проблемы
pid будет работоспособным, вне зависимости от того, на какой ноде процесс в результате запущен

Проблема N+1 идет не из того, что надо что-то достать из базы. Потому что доставать из базы можно и без N+1. Она появляется из-за повторений относительно долгой операции в цикле.
В вашем подходе она тоже возможна. Если вы загрузили все товары из базы в виде таких процессов на одну ноду, заказ 123 на другую ноду, и выводите все его order items с названием товара, то у вас будет N запросов по сети с одной ноды на другую для получения названия товара по item.productId. Возможно это будет немного быстрее чем с базой, но проблема все равно присутствует. Чтобы ее избежать, надо специальным образом проектировать взаимодействие, чтобы выполнять несколько операций за одно обращение, так же как и с запросами в базу.

а в вашем мире «БАЗА» — это такое магическое существо, волшебно сохраняющее всё навсегда

Нет. В моем мире «БАЗА» — это такое приложение, сохраняющее всё в файлы на жесткий диск. Не волшебно, не безотказно, и не навсегда, просто сохраняющее. С намеренно реализованной системой транзакций, которая имеет защиту от сбоев в середине записи. В отличие от состояния процесса, которое находится в оперативной памяти, на жесткий диск не сохраняется, и системы транзакций не имеет.

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

Откуда у вас такая слепая вера в Великую Базу

Ниоткуда, потому что это не вера и не слепая. А знание о том, как работают базы, и зачем нужны походы в них.

Чем процесс хуже?

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

RabbitMQ и даже местами Kafka. Там нет базы. Но вы их, наверное, могли бы использовать безоглядно, так?

В RabbitMQ и Kafka есть персистентность, для ее корректной работы там написано много кода. Но они не являются источником данных, а просто передают их от источника к получателю. И да, если надо гарантировать отправку сообщений после сохранения изменений, то используется подход transactional outbox, который внезапно подразумевает использование базы данных.

Мы можем его изменять ... и всё это без походов в базу.
Но доступ на чтение уж точно может обойтись без похода в базу.

Вы же говорили про "изменять без походов в базу"? Теперь оказывается, что это только для чтения подходит?)

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

писать event log, сохранять критические изменения состояний

А, ну то есть вместо того, чтобы ходить в уже написанную базу, вы предлагаете писать свою базу и ходить в нее. Как-то не выглядит похоже на "без походов в базу". Выглядит как дополнительная работа, а не как преимущество, которым вы пытались его представить.

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

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

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

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

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

исчезающе малое количество людей, что у меня есть сложившееся мнение

Возможно, большинство тех, кто не понимает ваше изложение, просто не считают нужным сообщать это вам?

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

Захотят — поймут

Это зависит не только от их желания, а еще и от достаточности информации в статье для понимания.

Мой текст вы прочитать (или понять) не удосужились

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

нуждается в обёртке, которая знает, что сделать, если сервис сбойнул. Такая обёртка для S3, скорее всего, будет делать что-то наподобие

Я именно про такую обертку и говорю.

потом сгрузить в доступное back-up хранилище

"В доступное хранилище" оно и так уже загружено во время запроса пользователя. Если оба недоступны, ему будет показана ошибка "Не удалось загрузить файл". Задача в том, чтобы загрузить во второе позже. Это и есть система backup-хранилищ. Если одно недоступно когда надо скачать файл, система получит его из другого.

и запустить процесс типа watchdog, который будет мониторить S3

А что значит "мониторить"-то?) Наверно периодически проверять доступность с достаточным интервалом? А если так, зачем между попытками держать запущенным отдельный процесс для каждого файла, если они ничего не делают?

Information

Rating
2,001-st
Location
Россия
Registered
Activity