LINUX.ORG.RU

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

 , ,


4

2

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


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

★★★★★

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

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

гыгыгы

твои нормальные формы я 20 лет назад уже знал, и они не про поведение, а про данные — и совершенно не учитывают возможность полиморфизма даже в простейшей форме

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

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

ну так практический пример на раскладку чего-нить полиморфного в БД от тебя будет или нет? да, разрешается начать с проектирования именно базы данных, а не классов/объектов

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

да, разрешается начать с проектирования именно базы данных, а не классов/объектов

ЧТД

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

вот и пошел разговор о том, как в базу класть объекты классов Base, Derived1, Derived2, Derived3 так, чтобы SQL это понимал на уровне связей между таблицами

Я пишу в виде Type + Ref. То есть связи есть только с точки зрения интерфейса (если куда-то можно ссылку на Derived, значит туда можно ссылку на Base). Контроль того, что в Derived должны быть все поля, которые есть в Base, решается надбазовыми средствами.

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

У вас всё так же не будет связности таблиц в виде внешних ключей.

Можно сделать

CREATE VIEW ВсеПартии
AS
SELECT &ТипПоступления КАК Тип, Ссылка FROM Поступления
UNION ALL
SELECT &ТипОприходования КАК Тип, Ссылка FROM Оприходования
UNION ALL
...


CREATE TABLE ДвиженияСклада
(
    Партия int,
    ТипПартии int,
    ...
    CONSTRAINT Партия_fk 
       FOREIGN KEY (ТипПартии, Партия)  REFERENCES ВсеПартии (Тип, Ссылка)
)
monk ★★★★★
()
Ответ на: комментарий от a--

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

CREATE TABLE Base ...;

CREATE TABLE Base2 ...;

CREATE TABLE Derived ...; -- from Base, Base2

CREATE View AllBase
SELECT 1 AS Type, * FROM Base
UNION ALL
SELECT 3 AS Type, ... FROM Derived;

CREATE View AllBase2
SELECT 2 AS Type, * FROM Base2
UNION ALL
SELECT 3 AS Type, ... FROM Derived;
monk ★★★★★
()
Ответ на: комментарий от anc

Это и значит, что не связаны

И если не связаны, то что? Вы поддерживаете идею вытаскивать всё на клиент из несвязанных таблиц и работать с ними там?

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

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

Предлагаете таблицу проводок на 600 колонок?

Ужасть. Неужто Вам других решений в голову не приходило?

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

Ужасть. Неужто Вам других решений в голову не приходило?

Предложите. Мой вариант (тип + ссылка). Вам не нравится.

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

Мне не нравится только вариант с left join, те подразумевающий отсутствие данных. А сами по себе, как одноуровневые так и многоуровневые связи давным давно описаны сотни раз.

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

Мой вариант (тип + ссылка).

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

в sqlite мне удалось создать таблицу

CREATE VIEW my_union AS SELECT * FROM t1 UNION ALL SELECT * FROM t2;

CREATE TABLE test
(
  id INT NOT NULL,
  FOREIGN KEY (id) REFERENCES my_union(id)
);

но дальше sqlite в своем типичном динамическом (говно)стиле отказался что-то вставлять:

insert into t1   values (18),(19) ;
insert into t2   values (28),(29) ;
insert into test values (18),(19) ;
Error: foreign key mismatch - "test" referencing "my_union" 

— его видимо волнует уникальность и индексы; но с уникальным индексом на вьюху он тоже не согласился: Error: views may not be indexed

как вариант можно попробовать check constaint но это неполноценно смотрится

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

постгрес 9 тоже пишет ERROR: referenced relation «заботливо_созданная_мной_вьюха» is not a table

при том что она даже и не union, а простая select * where ...

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

sqlite даже на CHECK constraints не соглашается: Error: subqueries prohibited in CHECK constraints

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

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

FOREIGN KEY на VIEW только Oracle обещает (правда по документации неясно, проверяет ли).

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

у тебя есть feature list языка программирования, который бы тебя устраивал?

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

Если говорить про «на чем бы ты писал», то, как говорится, «я бы и на собаке писал». Если говорить про некий идеал, то прежде всего затык в процессорах, которые довольно давно намертво оптимизированы под исполнение сишного кода (это прежде всего когерентный кэш), и в ближайшие 20 лет ситуация не изменится, как, собственно, не менялась она и прошедшие 20 лет. Современные языки подошли неприятно близко к потолку того, что можно написать на сишечке, и выше уже особо не прыгнешь. Как железячник, я вижу, что сами реализации ЦП уже давно не имеют ничего общего с машиной Тьюринга, но всё равно играются в эту машинку для рыночка. За счет этой абстракции возникает огромная неэффективность использования железа, но, мало того, эта абстракция еще и неудобна сама по себе, софт на ней получается глючный и строго однозадачный.

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

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

Сейчас такая мода на микросервисы..

Да вроде прошла давным давно эта мода, вы где-то в 2018.

Притом админ при каждом обновлении фронта и бэка ставиться бешенной собакой

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

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

Притом админ при каждом обновлении фронта и бэка ставиться бешенной собакой

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

Кто сказал «монолит»?

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

он про девопсину скорее всего, когда с гита одним кликом всё. конпеляция, тесты,деплой и вот это вот всё.

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

как в базу класть объекты классов Base, Derived1, Derived2, Derived3

Лично я советую класть в одну таблицу.

id, type, base1, …, baseN, derived1, …, derivedM, derived2, …, derivedK, …

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

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

он про девопсину скорее всего, когда с гита одним кликом всё. конпеляция, тесты,деплой и вот это вот всё

С гита одним кликом и я могу, девопёс не для этого нужен, он нужен, чтобы костыли 24/7 городить и чинить то, что опять отвалилось.

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

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

С таким подходом вообще надо разные таблицы не делать, а делать одну со всеми полями и колонкой «имя таблицы».

Работает не очень хорошо из-за блокировок и кучи NULL в каждой строке. Если типов наследников немного, тогда подходит.

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

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

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

Я указал на узкое место в вашей реализации.

Ещё раз перечитал наш диалог. Всё равно не понял. Можете ещё раз указать?

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

left | right join тяжелые операции. Они даже могут работать по началу, но с накоплением данных, бывает что достаточно внезапно, превращаются в тыкву, работала, работала такая конструкция за 0.5сек и вот фигак уже минута, прошло пять дней и вот уже 20 минут.

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

left | right join тяжелые операции

left join b on ... = b.id, где id – первичный ключ всегда работает достаточно быстро

И изначально было неприятие вытаскивания базы (я же даже ссылку привёл). Но в любом случае вытаскивание поля из базы — это доли секунды. Вытаскивание этого же поля из памяти — доли миллисекунды. Разница в тысячу раз. Затащить разово в память пару гигабайтов при запуске — 20-30 секунд.

Главное, чтобы в эту базу никто в обход сервера приложений не писал.

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

left join b on ... = b.id, где id – первичный ключ всегда работает достаточно быстро

Никогда не говорите «всегда».

И изначально было неприятие вытаскивания базы

Оно никуда не делось.

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

Никогда не говорите «всегда».

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

Оно никуда не делось.

Но Вы же согласились, что так работает быстрее. Или нет?

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

Но Вы же согласились, что так работает быстрее. Или нет?

Я согласился с тем что у вас с left join работает медленно, а это немного другое :)

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

Ну тут в теме проскальзывало 500 типов, для такого, конечно, нужно совсем другие расклады использовать, нереляционные скорей всего. Мой вариант это - да, 3-10 типов по 5-10 полей, с чем я сталкивался. Делал в разных таблицах, в итоге было очень много джойнов, очень сложно разбираться в простых запросах, и база часто лажала с планами. На одной таблице все проблемы исчезли.

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

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

Я согласился с тем что у вас с left join работает медленно, а это немного другое :)

Думаете, если переписать с inner join, станет быстрее, чем чтение из поля в памяти?

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

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

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

NULL занимает столько же места, сколько любое другое значение (нет у СУБД компактного хранения разреженных баз), а значит если у нас 20 числовых полей, а используется именно в текущем типе только 4, то таблица будет в 5 раз больше.

Если бы это было неважно, то можно было бы вообще всё в одной таблице хранить.

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

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

1С на реляционной базе работает. До 2008 MS SQL была проблема, что в одном запросе не более 256 таблиц поддерживалось. С 2008 всё работает отлично.

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

NULL занимает столько же места, сколько любое другое значение (нет у СУБД компактного хранения разреженных баз), а значит если у нас 20 числовых полей, а используется именно в текущем типе только 4, то таблица будет в 5 раз больше.

Истину глаголите!

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

Я правильно понял, что

VAL = SQLQuery("SELECT B.VAL FROM A INNER JOIN B ON A.F = B.ID WHERE A.ID = ?ID", A.ID).VAL

должно быстрее выполниться, чем

VAL = A.F.VAL

?

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

если переписать с inner join, станет быстрее, чем чтение из поля в памяти

146% не дам, бывают национальные нюансы, но судя по вашему запросу 99% что да

Я привёл пример кода. Первая часть — чтение поля из СУБД через INNER JOIN. Вторая - того же поля из памяти на клиенте.

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

Вот если отвечать на ваш вопрос прямо, безусловно второй вариант быстрее. Но сам вопрос в духе: что будет быстрее printf("%s",s); или printf("%d",d);? При этом откуда берется значение s и d мы как бэ не говорим. Надеюсь аналогия понятна.

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

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

Понятно, что есть отчёты, которые быстрее делать через SQL (стандартные отборы/суммы/сортировки). Но всё остальное в SQL ужасно медленно.

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

ЗЫ И раз речь идет о данных, тут ещё не хватает информации насколько важна актуальность данных. Поясню, предположим у вас таблица с полем F(int), в котором есть запись со значением 10, два клиента вытащили себе всю таблицу целиком, первый клиент меняет значение с 10 на 15, но второй об этом не знает и продолжать в своей работе ориентироваться на значение 10. В результате мы имеем двух клиентов которые думают что работают с одной и той же информацией, а по факту это не так и чем дальше в лес тем больше получаем расхождений по самой информации. Следовательно, для того что бы у всех клиентов была не противоречивая информация, нам придется на каждое изменение вытаскивать полный набор данных, что при большом количестве клиентов приведет к тому что уткнется в сеть.

anc ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.