Работа мечты: различия между версиями
Перейти к навигации
Перейти к поиску
Artem (обсуждение | вклад) |
Artem (обсуждение | вклад) |
||
(не показано 226 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
<embedvideo service="youtube" dimensions="800x450">https://www.youtube.com/watch?v=5bId3N7QZec</embedvideo> | |||
* Facebook | * Facebook | ||
* Amazon | * Amazon | ||
* Apple | * Apple | ||
* Netflix | * Netflix | ||
* Google | |||
* Microsoft | * Microsoft | ||
= Мотивация = | |||
[[File:Penguin-Falls-Over-Rock.gif]] | |||
<pre>Характер + воспитание + обстоятельства = воля + мораль + закалка</pre> | |||
* Отрицание | |||
* Гнев | |||
* Торг | |||
* Депрессия | |||
* Принятие | |||
[[File:dream.jpeg|300px]] | |||
[[File:nu-davay.jpg|600px]] | |||
[[File:steps-motivation.jpg|600px]] | |||
<pre> | |||
Один работник заходит к хозяину и спрашивает: | |||
– А почему ты платишь мне всего рубль в неделю, в то время как Елисею – пятнадцать? Хозяин смотрит в окно и говорит: | |||
– Слышу, кто-то едет. Нам сена на зиму нужно купить. Выйди-ка, посмотри, не сено ли везут. | |||
Вышел работник. | |||
Зашел и говорит: | |||
– Правда, сено. | |||
– А не знаешь, откуда? Может, с Лукьяновских лугов? | |||
– Не знаю. | |||
– Так сходи и спроси. | |||
Пошел тот. | |||
Снова входит: | |||
– Точно, с Лукьяновских. | |||
– А сено какого укоса – первого или второго? | |||
– Не знаю. | |||
– Так сходи, узнай! | |||
Вышел работник. | |||
Возвращается: | |||
– Хозяин! Первого укоса! | |||
– А не знаешь, почем? | |||
– Не знаю. | |||
– Так сходи, узнай. | |||
Сходил. | |||
Вернулся и говорит: | |||
– Хозяин! По двадцать рублей. | |||
– А дешевле не дают? | |||
– Не знаю. | |||
В этот момент входит Елисей и говорит: | |||
– Хозяин! Мимо везли сено с Лукьяновских лугов первого укоса. Просили по 20 рублей. Сторговались по 17 за воз. Я их загнал во двор, сейчас разгружают. | |||
Хозяин поворачивается к первому: | |||
– Теперь ты понял, почему тебе платят 1 рубль, а Елисею – 15? | |||
</pre> | |||
[[File:evg-sanya.jpg|600px]] | |||
[[File:full-stack-developer.jpg|600px]] | |||
[[File:cat-developer-home.jpg|600px]] | |||
[[File:90ie.jpg|600px]] | |||
[[File:interview-vs-job.jpg|600px]] | |||
= Compensations = | = Compensations = | ||
Строка 32: | Строка 92: | ||
* https://www.kalzumeus.com/2011/10/28/dont-call-yourself-a-programmer/ | * https://www.kalzumeus.com/2011/10/28/dont-call-yourself-a-programmer/ | ||
* https://careers.google.com/stories/apm-preparation-materials/ | * https://careers.google.com/stories/apm-preparation-materials/ | ||
* https://www.criteriacorp.com/candidates/ccat-prep | |||
* https://www.amazon.jobs/content/en/our-workplace/leadership-principles | |||
* https://easyoffer.ru/ | |||
== Алгоритмы == | |||
* [[Алгоритмы]] | |||
== ООП == | |||
* Инкапсуляция (разделение доступа) | |||
* Наследование | |||
* Полиморфизм (полиморфные методы для каждого типа свой метод) | |||
== SOLID == | |||
* https://levelup.gitconnected.com/solid-principles-simplified-php-examples-based-dc6b4f8861f6 | |||
* https://web-creator.ru/articles/solid | |||
* S - Принцип единственной ответственности (The Single Responsibility Principle) | |||
** Следование принципу заключается обычно в декомпозиции сложных классов, которые делают сразу много вещей, на простые, отвественность которых очень специализирована. | |||
* O - Принцип открытости/закрытости (The Open Closed Principle) | |||
** Программные сущности (классы, модули, функции и т. п.) должны быть открыты для расширения, но закрыты для изменения | |||
* L - Принцип подстановки Барбары Лисков (The Liskov Substitution Principle) | |||
** При построении иерархий наследования создаваемые наследники должны корректно реализовывать поведение базового типа. Наследник класса дополняет, но не заменяет поведение базового класса. То есть в любом месте программы замена базового класса на класс‑наследник не должна вызывать проблем. | |||
* I - Принцип разделения интерфейса (The Interface Segregation Principle) | |||
** Заключается в создании интерфейсов, которые достаточно специфичны и требуют только необходимый минимум реализаций методов. Избыточные интерфейсы, напротив, могут требовать от реализующего класса создание большого количества методов, причём даже таких, которые не имеют смысла в контексте класса. | |||
* D - Принцип инверсии зависимостей (The Dependency Inversion Principle) | |||
** Следование принципу инверсии зависимостей «заставляет» реализовывать высокоуровневые компоненты без встраивания зависимостей от конкретных низкоуровневых классов, что, например, сильно упрощает замену используемых зависимостей как по бизнес‑требованиям, так и для целей тестирования. При этом зависимость формируется не от конкретной реализации, а от абстракции — реализуемого зависимостью интерфейса. | |||
== Паттерны проектирования == | |||
* https://designpatternsphp.readthedocs.io/ru/latest/README.html | |||
* https://www.kobzarev.com/wp-content/uploads/books/php/PHPbook.pdf | |||
* https://refactoring.guru/ru/design-patterns | |||
* Порождающие паттерны | |||
** Абстрактная фабрика | |||
** Одиночка | |||
** Прототип | |||
** Строитель | |||
** Фабричный метод | |||
* Структурные паттерны | |||
** Адаптер | |||
** Декоратор | |||
** Заместитель | |||
** Компоновщик | |||
** Мост | |||
** Приспособленец | |||
** Фасад | |||
* Паттерны поведения | |||
** Интерпретатор | |||
** Итератор | |||
** Команда | |||
** Наблюдатель | |||
** Посетитель | |||
** Посредник | |||
** Состояние | |||
** Стратегия | |||
** Хранитель | |||
** Цепочка обязанностей | |||
** Шаблонный метод | |||
== Чистая архитектура == | |||
[[File:clean-architecture.png|600px]] | |||
== Domain Driven Design == | |||
* Единый язык (Ubiquitous Language) | |||
* Домены и субдомены | |||
* Ubiquitous Language - общий язык с заказчиком | |||
* Стратегическое моделирование - стратегия управления бизнесом | |||
* Тактическое моделирование - итеративная разработка ПО | |||
* Bounded Context - граница предметной области | |||
* Context Map - как Bounded Context связан с другими | |||
* https://www.youtube.com/watch?v=6_BhdXLxiic | |||
== Паттерны микросервисов == | |||
* https://cloud.vk.com/blog/26-osnovnyh-patternov-mikroservisnoj-razrabotki | |||
* Паттерны декомпозиции на микросервисы | |||
** Шаблон «Разбиение по бизнес-возможностям» (Decompose By Business Capability) | |||
** Шаблон «Разбиение по поддоменам» (Decompose By Subdomain) | |||
* Паттерны рефакторинга для перехода на микросервисы | |||
** Шаблон «Душитель» (Strangler) | |||
** Шаблон «Уровень защиты от повреждений» (Anti-Corruption Layer) | |||
* Паттерны управления данными в микросервисной архитектуре | |||
** Шаблон «База данных на сервис» (Database Per Service) | |||
** Шаблон «API-композиция» (API Composition) | |||
** Шаблон «Разделение команд и запросов» (Command Query Responsibility Segregation, CQRS) | |||
** Шаблон «Поиск событий» (Event Sourcing) | |||
** Шаблон «Сага» (Saga) | |||
* Паттерны коммуникации микросервисов | |||
** Шаблон «API-шлюз» (API Gateway) | |||
** Шаблон «Бэкенды для фронтендов» (Backends for Frontends, BFF) | |||
* Паттерны построения пользовательского интерфейса | |||
** Шаблон «Сборка пользовательского интерфейса на стороне клиента» (Client-Side UI Composition) | |||
** Шаблон «Сборка фрагментов страниц на стороне сервера» (Server-Side Page Fragment Composition) | |||
* Паттерны обнаружения сервисов в микросервисной архитектуре | |||
** Шаблон «Обнаружение сервисов на стороне клиента» (Client-Side Service Discovery) | |||
** Шаблон «Обнаружение сервисов на стороне сервера» (Server-Side Service Discovery) | |||
* Паттерны развертывания микросервисов | |||
** Шаблон «Экземпляр сервиса на хост» (Service Instance Per Host) | |||
** Шаблон «Сине-зеленое развертывание» (Blue-Green Deployment) | |||
* Паттерны повышения отказоустойчивости | |||
** Шаблон «Автоматический выключатель» (Circuit Breaker) | |||
** Шаблон «Переборка» (Bulkhead) | |||
* Паттерны мониторинга микросервисов | |||
** Шаблон «Агрегация логов» (Log Aggregation) | |||
** Шаблон «Распределенная трассировка» (Distributed Tracing) | |||
** Шаблон «Проверки здоровья» (Health Check) | |||
* Прочие паттерны проектирования микросервисов | |||
** Шаблон «Посредник» («Посол», Ambassador) | |||
** Шаблон «Коляска» («Прицеп», Sidecar) | |||
** Шаблон «Тестирование контрактов, ориентированных на потребителя» (Consumer-Driven Contract Testing) | |||
** Шаблон «Внешняя конфигурация» (External Configuration) | |||
== Дженерики == | |||
* https://blog.skillfactory.ru/glossary/generics/ | |||
== ACID == | |||
* Atomicity — Атомарность | |||
* Consistency — Согласованность | |||
* Isolation — Изолированность | |||
* Durability — Долговечность | |||
== Уровни изоляции транзакций == | |||
* https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html | |||
* https://www.postgresql.org/docs/current/transaction-iso.html | |||
<pre> | |||
SELECT @@GLOBAL.transaction_isolation, @@GLOBAL.transaction_read_only; | |||
SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only; | |||
</pre> | |||
{| class="wikitable" | |||
|- | |||
! Уровень изоляции !! Черновое чтение !! Невоспроизводимое чтение !! Фантомное чтение !! Блокировка чтения | |||
|- | |||
| READ UNCOMMITTED || Yes || Yes || Yes || No | |||
|- | |||
| READ COMMITTED || No || Yes || Yes || No | |||
|- | |||
| REPEATABLE READ || No || No || Yes || No | |||
|- | |||
| SERIALIZABLE || No || No || No || Yes | |||
|- | |||
|} | |||
<pre> | |||
DROP TABLE IF EXISTS `money_transactions`; | |||
CREATE TABLE `money_transactions` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
`user_from_id` bigint(20) unsigned DEFAULT NULL, | |||
`user_to_id` bigint(20) unsigned DEFAULT NULL, | |||
`volume` decimal(19,6) NOT NULL, | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB; | |||
DROP TABLE IF EXISTS `money_accounts`; | |||
CREATE TABLE `money_accounts` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`user_id` bigint(20) unsigned DEFAULT NULL, | |||
`volume` decimal(19,6) NOT NULL, | |||
PRIMARY KEY (`id`), | |||
UNIQUE KEY (`user_id`) | |||
) ENGINE=InnoDB; | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), NULL, 1, 10000.0); | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), NULL, 2, 4300.0); | |||
INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); | |||
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; | |||
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; | |||
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; | |||
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; | |||
</pre> | |||
=== READ UNCOMMITTED === | |||
Суть в том, что незакрепленные транзакции видны в другой открытой транзакции | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
SET @user_id = 1; | |||
SET @user_to_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; | |||
START TRANSACTION; | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); | |||
INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
ROLLBACK; | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
SET @user_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; | |||
START TRANSACTION; | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
ROLLBACK; | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
> SELECT * FROM `money_transactions`; | |||
+----+---------------------+--------------+------------+--------------+ | |||
| id | created_at | user_from_id | user_to_id | volume | | |||
+----+---------------------+--------------+------------+--------------+ | |||
| 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | |||
| 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | |||
| 5 | 2024-02-12 14:48:29 | 1 | 2 | 3000.000000 | | |||
| 6 | 2024-02-12 14:48:29 | 2 | 1 | -3000.000000 | | |||
+----+---------------------+--------------+------------+--------------+ | |||
4 rows in set (0.00 sec) | |||
> SELECT * FROM `money_accounts`; | |||
+----+---------+-------------+ | |||
| id | user_id | volume | | |||
+----+---------+-------------+ | |||
| 1 | 1 | 7000.000000 | | |||
| 2 | 2 | 7300.000000 | | |||
+----+---------+-------------+ | |||
2 rows in set (0.00 sec) | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
> SELECT * FROM `money_transactions`; | |||
+----+---------------------+--------------+------------+--------------+ | |||
| id | created_at | user_from_id | user_to_id | volume | | |||
+----+---------------------+--------------+------------+--------------+ | |||
| 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | |||
| 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | |||
| 5 | 2024-02-12 14:48:29 | 1 | 2 | 3000.000000 | | |||
| 6 | 2024-02-12 14:48:29 | 2 | 1 | -3000.000000 | | |||
+----+---------------------+--------------+------------+--------------+ | |||
4 rows in set (0.00 sec) | |||
> SELECT * FROM `money_accounts`; | |||
+----+---------+-------------+ | |||
| id | user_id | volume | | |||
+----+---------+-------------+ | |||
| 1 | 1 | 7000.000000 | | |||
| 2 | 2 | 7300.000000 | | |||
+----+---------+-------------+ | |||
2 rows in set (0.00 sec) | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
=== READ COMMITTED === | |||
Суть в том, что если в первой транзакции был коммит - вы увидите из нее изменения, хотя находитесь в транзакции. | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
SET @user_id = 1; | |||
SET @user_to_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; | |||
START TRANSACTION; | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); | |||
INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
COMMIT; | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
SET @user_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; | |||
START TRANSACTION; | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
ROLLBACK; | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
> SELECT * FROM `money_transactions`; | |||
+----+---------------------+--------------+------------+--------------+ | |||
| id | created_at | user_from_id | user_to_id | volume | | |||
+----+---------------------+--------------+------------+--------------+ | |||
| 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | |||
| 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | |||
| 7 | 2024-02-12 15:13:40 | 1 | 2 | 3000.000000 | | |||
| 8 | 2024-02-12 15:13:40 | 2 | 1 | -3000.000000 | | |||
+----+---------------------+--------------+------------+--------------+ | |||
4 rows in set (0.00 sec) | |||
> SELECT * FROM `money_accounts`; | |||
+----+---------+-------------+ | |||
| id | user_id | volume | | |||
+----+---------+-------------+ | |||
| 1 | 1 | 7000.000000 | | |||
| 2 | 2 | 7300.000000 | | |||
+----+---------+-------------+ | |||
2 rows in set (0.00 sec) | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
> SELECT * FROM `money_transactions`; | |||
+----+---------------------+--------------+------------+--------------+ | |||
| id | created_at | user_from_id | user_to_id | volume | | |||
+----+---------------------+--------------+------------+--------------+ | |||
| 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | |||
| 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | |||
| 7 | 2024-02-12 15:13:40 | 1 | 2 | 3000.000000 | | |||
| 8 | 2024-02-12 15:13:40 | 2 | 1 | -3000.000000 | | |||
+----+---------------------+--------------+------------+--------------+ | |||
4 rows in set (0.00 sec) | |||
> SELECT * FROM `money_accounts`; | |||
+----+---------+-------------+ | |||
| id | user_id | volume | | |||
+----+---------+-------------+ | |||
| 1 | 1 | 7000.000000 | | |||
| 2 | 2 | 7300.000000 | | |||
+----+---------+-------------+ | |||
2 rows in set (0.00 sec) | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
=== REPEATABLE READ === | |||
В MySQL этот уровень по-умолчанию. Суть в том, что возможно чтение фантомных строк - закрепленных другими транзакциями. Тест показал, что транзакции не изолированы | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
SET @user_id = 1; | |||
SET @user_to_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; | |||
START TRANSACTION; | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); | |||
INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
COMMIT; | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
SET @user_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; | |||
START TRANSACTION; | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
ROLLBACK; | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
> SELECT * FROM `money_transactions`; | |||
+----+---------------------+--------------+------------+--------------+ | |||
| id | created_at | user_from_id | user_to_id | volume | | |||
+----+---------------------+--------------+------------+--------------+ | |||
| 1 | 2024-02-12 15:27:39 | NULL | 1 | 10000.000000 | | |||
| 2 | 2024-02-12 15:27:39 | NULL | 2 | 4300.000000 | | |||
| 3 | 2024-02-12 15:28:22 | 1 | 2 | 3000.000000 | | |||
| 4 | 2024-02-12 15:28:22 | 2 | 1 | -3000.000000 | | |||
+----+---------------------+--------------+------------+--------------+ | |||
4 rows in set (0.00 sec) | |||
> SELECT * FROM `money_accounts`; | |||
+----+---------+-------------+ | |||
| id | user_id | volume | | |||
+----+---------+-------------+ | |||
| 1 | 1 | 7000.000000 | | |||
| 2 | 2 | 7300.000000 | | |||
+----+---------+-------------+ | |||
2 rows in set (0.00 sec) | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
> SELECT * FROM `money_transactions`; | |||
+----+---------------------+--------------+------------+--------------+ | |||
| id | created_at | user_from_id | user_to_id | volume | | |||
+----+---------------------+--------------+------------+--------------+ | |||
| 1 | 2024-02-12 15:27:39 | NULL | 1 | 10000.000000 | | |||
| 2 | 2024-02-12 15:27:39 | NULL | 2 | 4300.000000 | | |||
| 3 | 2024-02-12 15:28:22 | 1 | 2 | 3000.000000 | | |||
| 4 | 2024-02-12 15:28:22 | 2 | 1 | -3000.000000 | | |||
+----+---------------------+--------------+------------+--------------+ | |||
4 rows in set (0.00 sec) | |||
> SELECT * FROM `money_accounts`; | |||
+----+---------+-------------+ | |||
| id | user_id | volume | | |||
+----+---------+-------------+ | |||
| 1 | 1 | 7000.000000 | | |||
| 2 | 2 | 7300.000000 | | |||
+----+---------+-------------+ | |||
2 rows in set (0.00 sec) | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
=== SERIALIZABLE === | |||
Суть в том, что вставка в левой сессии заблокируется, т.к. было чтение из правой сессии. Блокируется чтение - поэтому вы не сможете получить данные. | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #D44;float:left;"> | |||
SET @user_id = 1; | |||
SET @user_to_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; | |||
START TRANSACTION; | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); | |||
INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); | |||
INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
COMMIT; | |||
</pre> | |||
<pre style="white-space: pre;max-width:40%;overflow-x:scroll;color:#fff;background-color: #44D;float:left;"> | |||
SET @user_id = 2; | |||
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; | |||
START TRANSACTION; | |||
SELECT * FROM `money_transactions`; | |||
SELECT * FROM `money_accounts`; | |||
ROLLBACK; | |||
</pre> | |||
<pre style="clear:both;"></pre> | |||
== Алгоритмы == | == Алгоритмы == | ||
* Не забываем про рекурсию | * Не забываем про рекурсию | ||
=== Сложность алгоритмов === | |||
<embedvideo service="youtube" dimensions="800x450">https://www.youtube.com/watch?v=47GRtdHOKMg</embedvideo> | |||
== PHP == | == PHP == | ||
* [[PHP]] | |||
== JavaScript == | |||
* [[JavaScript]] | |||
== TypeScript == | |||
== Angular == | |||
== Python == | == Python == | ||
Строка 43: | Строка 569: | ||
== Golang == | == Golang == | ||
* [[Golang]] | |||
* [https://habr.com/ru/articles/654569/ Собеседование Golang разработчика (теоретические вопросы), Часть I] | |||
** [https://habr.com/ru/companies/nixys/articles/492056/ 4 примера iota-перечислений] | |||
* [https://habr.com/ru/articles/670974/ Собеседование Golang разработчика (теоретические вопросы), Часть II. Что там с конкурентностью?] | |||
** [https://gobyexample.com/waitgroups Go by Example: WaitGroups] | |||
== SQL == | == SQL == | ||
= Linux Boot = | |||
<embedvideo service="youtube" dimensions="800x450">https://www.youtube.com/watch?v=XpFsMB6FoOs</embedvideo> | |||
= Поведенческие вопросы = | = Поведенческие вопросы = | ||
* | * | ||
= Решение задач = | = Решение задач = | ||
Строка 67: | Строка 600: | ||
= Дизайн систем = | = Дизайн систем = | ||
== Схема ответа == | |||
* Сбор функциональных требований (что должно быть) | |||
* Сбор нефункциональных требований (как оно должно быть) + некая вводная | |||
* Расчет ресурсов RPS write, RPS read, потоки данных, объемы хранилищ | |||
* Проектирование API (основные методы, схема) | |||
* Проектирование архитектуры (сервисы, блоки, базы данных, очереди, кэши) | |||
* Проектирование БД (таблицы в бд сервисов) | |||
* Оценка отказоустойчивости и масштабируемости системы | |||
* Расчет железа и сети | |||
* Сценарии отказов | |||
* Логгирование | |||
* Мониторинги | |||
== Ссылки == | |||
* https://habr.com/ru/companies/yandex/articles/564132/ | |||
* https://www.educative.io/courses/grokking-modern-system-design-interview-for-engineers-managers | |||
* https://github.com/donnemartin/system-design-primer | * https://github.com/donnemartin/system-design-primer | ||
* https://docs.google.com/document/d/1w3qb6SS1Hycyce5Fg5mVMdzkGYXTRskSf57IoD98ZQw/edit | * https://docs.google.com/document/d/1w3qb6SS1Hycyce5Fg5mVMdzkGYXTRskSf57IoD98ZQw/edit | ||
Строка 73: | Строка 624: | ||
* YouTube Playlist - https://www.youtube.com/playlist?list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX | * YouTube Playlist - https://www.youtube.com/playlist?list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX | ||
== Не функциональные | == Время отклика систем == | ||
[[File:latency.png]] | |||
<pre> | |||
Latency Comparison Numbers | |||
-------------------------- | |||
L1 cache reference 0.5 ns | |||
Branch mispredict 5 ns | |||
L2 cache reference 7 ns 14x L1 cache | |||
Mutex lock/unlock 25 ns | |||
Main memory reference 100 ns 20x L2 cache, 200x L1 cache | |||
Compress 1K bytes with Zippy 10,000 ns 10 us | |||
Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us | |||
Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD | |||
Read 1 MB sequentially from memory 250,000 ns 250 us | |||
Round trip within same datacenter 500,000 ns 500 us | |||
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory | |||
HDD seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip | |||
Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD | |||
Read 1 MB sequentially from HDD 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD | |||
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms | |||
Notes | |||
----- | |||
1 ns = 10^-9 seconds | |||
1 us = 10^-6 seconds = 1,000 ns | |||
1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns | |||
</pre> | |||
* https://ping-admin.ru/free_ping/ | |||
* До МСК | |||
** Европа < 50 | |||
** До Урала < 50 | |||
** Владивосток 100 | |||
** США-Канада 150-250 | |||
** Южная Америка 200-300 | |||
** Азия 200-300 | |||
** Австралия 300 | |||
=== Расположение датацентров в мире === | |||
<gallery widths=300px heights=200px> | |||
File:google-data-centers.png|Google | |||
File:amazon-data-centers.png|Amazon | |||
File:alibaba-data-centers.png|Alibaba | |||
File:cloudflare-data-centers.png|Cloudflare | |||
File:ms-azure-data-centers.jpg|MS Azure | |||
</gallery> | |||
== Не функциональные характеристики систем == | |||
=== Availability / Доступность === | === Availability / Доступность === | ||
<math>A(%) = \frac{T_{period} - T_{downtime}}{T_{period}}</math> | |||
{| class="wikitable" | |||
|- | |||
! Доступность % !! Недоступность в год !! Недоступность в месяц !! Недоступность в неделю | |||
|- | |||
| 90% (1 девяток) || 36.5 дней || 72 часов || 16.8 часов | |||
|- | |||
| 99% (2 девяток) || 3.65 дней || 7.20 часов || 1.68 часов | |||
|- | |||
| 99.5% (2 девяток) || 1.83 дней || 3.60 часов || 50.4 минут | |||
|- | |||
| 99.9% (3 девяток) || 8.76 часов || 43.8 минут || 10.1 минут | |||
|- | |||
| 99.99% (4 девяток) || 52.56 минут || 4.32 минут || 1.01 минут | |||
|- | |||
| 99.999% (5 девяток) || 5.26 минут || 25.9 секунд || 6.05 секунд | |||
|- | |||
| 99.9999% (6 девяток) || 31.5 секунд || 2.59 секунд || 0.605 секунд | |||
|- | |||
| 99.99999% (7 девяток) || 3.15 секунд || 0.259 секунд || 0.0605 секунд | |||
|- | |||
|} | |||
=== Reliability / Надежность === | |||
Среднее время между отказами (MTBF) | |||
<math>MTBF = \frac{T_{total}-\sum{}{}{T_{downtime}}}{N_{downtime}}</math> | |||
Среднее время отказа (MTTF) | |||
<math>MTTF = \frac{\sum{}{}{T_{downtime}}}{N_{downtime}}</math> | |||
Среднее время восстановления(MTTR) | |||
<math>MTTR = \frac{T_{total maintence}}{N_{repair}}</math> | |||
* https://habr.com/ru/company/itsumma/blog/435662/ | |||
=== Scalability / Масштабируемость === | |||
* Вертикальное масштабирование - увеличение мощности узлов (CPU(Frequency, # of cores), MEM(Volume, Frequency), HDD->SSD->NVMe) | |||
* Горизонтальное масштабирование - увеличение количества узлов | |||
=== Maintainability / Поддерживаемость === | |||
* Главный параметр - MTTR | |||
* Легкость кода и прозрачность разработки | |||
=== Fault Tolerance / Устойчивость к сбоям === | |||
* Отказоустойчивость - способность системы обслуживать запросы даже при отказе ее частей. | |||
* Можно достичь шардингом и репликацией | |||
== Сколько нужно серверов? == | |||
<math>CPU = \frac{N_{CPU\ Threads}}{T\ for\ handle\ 1\ request} = \frac{32}{200ms} = 160\ RPS</math> | |||
<math>MEM = \frac{N_{MEM\ Size}}{MEM\ for\ handle\ 1\ request} = \frac{128GB}{300MB} = 436.90\ RPS</math> | |||
== Блоки систем == | |||
* DNS | |||
* Load balancers - Балансировщики | |||
* Databases - Базы данных | |||
* KV Storage - Хранилища Ключ Значение | |||
* CDN - Сеть доставки контента | |||
* Sequencer - генератор идентификаторов | |||
* Мониторинг | |||
* Распределенный кэш | |||
* Распределенная очередь сообщений | |||
* Издатель-подписчик | |||
* Ограничитель нагрузки | |||
* Файловое хранилище | |||
* Распределенный поиск | |||
* Распределенное логгирование | |||
* Распределенное задачи по расписанию | |||
* Шардированные счетчики. | |||
= Mock интервью = | = Mock интервью = | ||
Строка 84: | Строка 763: | ||
* https://replit.com/ | * https://replit.com/ | ||
= | = Демотиваторы = | ||
[[File:qs-vs-real.png|600px]] | |||
[[File: | [[File:nizkoopl-programmist.jpg|600px]] | ||
[[File:chatgpt-meme.jpeg|600px]] | |||
[[File:nothing-to-eat.jpg|600px]] | |||
[[File:suk-sidish.gif]] | |||
[[File:moskvich-bez-raboty.jpg|600px]] | |||
[[File:digital-zavod.jpg|600px]] | |||
[[File:pravki-po-makety.gif]] | |||
[[File:son-of-owner.jpg]] | |||
[[File:eboshit.jpeg]] | |||
<embedvideo service="youtube" dimensions="800x450">https://www.youtube.com/watch?v=mj1dd0Kcq8A</embedvideo> |
Текущая версия от 21:12, 8 ноября 2024
- Amazon
- Apple
- Netflix
- Microsoft
Мотивация
Характер + воспитание + обстоятельства = воля + мораль + закалка
- Отрицание
- Гнев
- Торг
- Депрессия
- Принятие
Один работник заходит к хозяину и спрашивает: – А почему ты платишь мне всего рубль в неделю, в то время как Елисею – пятнадцать? Хозяин смотрит в окно и говорит: – Слышу, кто-то едет. Нам сена на зиму нужно купить. Выйди-ка, посмотри, не сено ли везут. Вышел работник. Зашел и говорит: – Правда, сено. – А не знаешь, откуда? Может, с Лукьяновских лугов? – Не знаю. – Так сходи и спроси. Пошел тот. Снова входит: – Точно, с Лукьяновских. – А сено какого укоса – первого или второго? – Не знаю. – Так сходи, узнай! Вышел работник. Возвращается: – Хозяин! Первого укоса! – А не знаешь, почем? – Не знаю. – Так сходи, узнай. Сходил. Вернулся и говорит: – Хозяин! По двадцать рублей. – А дешевле не дают? – Не знаю. В этот момент входит Елисей и говорит: – Хозяин! Мимо везли сено с Лукьяновских лугов первого укоса. Просили по 20 рублей. Сторговались по 17 за воз. Я их загнал во двор, сейчас разгружают. Хозяин поворачивается к первому: – Теперь ты понял, почему тебе платят 1 рубль, а Елисею – 15?
Compensations
- https://www.levels.fyi/
- http://www.tax-rates.org/income-tax-calculator/?ref=nav_income - налоговый калькулятор США
Jobs Websites
- https://linkedin.com
- https://indeed.com
- https://glassdoor.com/
- https://www.toptal.com/
- https://www.crunchbase.com/
Подготовка
- Cracking the coding interview
- Алгоритмы. Построение и анализ | Кормен Томас Х., Лейзерсон Чарльз И.
- https://www.topcoder.com/
- https://www.learneroo.com/subjects/8
- https://www.careercup.com/
- https://www.interviewbit.com/
- https://www.kalzumeus.com/2011/10/28/dont-call-yourself-a-programmer/
- https://careers.google.com/stories/apm-preparation-materials/
- https://www.criteriacorp.com/candidates/ccat-prep
- https://www.amazon.jobs/content/en/our-workplace/leadership-principles
- https://easyoffer.ru/
Алгоритмы
ООП
- Инкапсуляция (разделение доступа)
- Наследование
- Полиморфизм (полиморфные методы для каждого типа свой метод)
SOLID
- https://levelup.gitconnected.com/solid-principles-simplified-php-examples-based-dc6b4f8861f6
- https://web-creator.ru/articles/solid
- S - Принцип единственной ответственности (The Single Responsibility Principle)
- Следование принципу заключается обычно в декомпозиции сложных классов, которые делают сразу много вещей, на простые, отвественность которых очень специализирована.
- O - Принцип открытости/закрытости (The Open Closed Principle)
- Программные сущности (классы, модули, функции и т. п.) должны быть открыты для расширения, но закрыты для изменения
- L - Принцип подстановки Барбары Лисков (The Liskov Substitution Principle)
- При построении иерархий наследования создаваемые наследники должны корректно реализовывать поведение базового типа. Наследник класса дополняет, но не заменяет поведение базового класса. То есть в любом месте программы замена базового класса на класс‑наследник не должна вызывать проблем.
- I - Принцип разделения интерфейса (The Interface Segregation Principle)
- Заключается в создании интерфейсов, которые достаточно специфичны и требуют только необходимый минимум реализаций методов. Избыточные интерфейсы, напротив, могут требовать от реализующего класса создание большого количества методов, причём даже таких, которые не имеют смысла в контексте класса.
- D - Принцип инверсии зависимостей (The Dependency Inversion Principle)
- Следование принципу инверсии зависимостей «заставляет» реализовывать высокоуровневые компоненты без встраивания зависимостей от конкретных низкоуровневых классов, что, например, сильно упрощает замену используемых зависимостей как по бизнес‑требованиям, так и для целей тестирования. При этом зависимость формируется не от конкретной реализации, а от абстракции — реализуемого зависимостью интерфейса.
Паттерны проектирования
- https://designpatternsphp.readthedocs.io/ru/latest/README.html
- https://www.kobzarev.com/wp-content/uploads/books/php/PHPbook.pdf
- https://refactoring.guru/ru/design-patterns
- Порождающие паттерны
- Абстрактная фабрика
- Одиночка
- Прототип
- Строитель
- Фабричный метод
- Структурные паттерны
- Адаптер
- Декоратор
- Заместитель
- Компоновщик
- Мост
- Приспособленец
- Фасад
- Паттерны поведения
- Интерпретатор
- Итератор
- Команда
- Наблюдатель
- Посетитель
- Посредник
- Состояние
- Стратегия
- Хранитель
- Цепочка обязанностей
- Шаблонный метод
Чистая архитектура
Domain Driven Design
- Единый язык (Ubiquitous Language)
- Домены и субдомены
- Ubiquitous Language - общий язык с заказчиком
- Стратегическое моделирование - стратегия управления бизнесом
- Тактическое моделирование - итеративная разработка ПО
- Bounded Context - граница предметной области
- Context Map - как Bounded Context связан с другими
Паттерны микросервисов
- Паттерны декомпозиции на микросервисы
- Шаблон «Разбиение по бизнес-возможностям» (Decompose By Business Capability)
- Шаблон «Разбиение по поддоменам» (Decompose By Subdomain)
- Паттерны рефакторинга для перехода на микросервисы
- Шаблон «Душитель» (Strangler)
- Шаблон «Уровень защиты от повреждений» (Anti-Corruption Layer)
- Паттерны управления данными в микросервисной архитектуре
- Шаблон «База данных на сервис» (Database Per Service)
- Шаблон «API-композиция» (API Composition)
- Шаблон «Разделение команд и запросов» (Command Query Responsibility Segregation, CQRS)
- Шаблон «Поиск событий» (Event Sourcing)
- Шаблон «Сага» (Saga)
- Паттерны коммуникации микросервисов
- Шаблон «API-шлюз» (API Gateway)
- Шаблон «Бэкенды для фронтендов» (Backends for Frontends, BFF)
- Паттерны построения пользовательского интерфейса
- Шаблон «Сборка пользовательского интерфейса на стороне клиента» (Client-Side UI Composition)
- Шаблон «Сборка фрагментов страниц на стороне сервера» (Server-Side Page Fragment Composition)
- Паттерны обнаружения сервисов в микросервисной архитектуре
- Шаблон «Обнаружение сервисов на стороне клиента» (Client-Side Service Discovery)
- Шаблон «Обнаружение сервисов на стороне сервера» (Server-Side Service Discovery)
- Паттерны развертывания микросервисов
- Шаблон «Экземпляр сервиса на хост» (Service Instance Per Host)
- Шаблон «Сине-зеленое развертывание» (Blue-Green Deployment)
- Паттерны повышения отказоустойчивости
- Шаблон «Автоматический выключатель» (Circuit Breaker)
- Шаблон «Переборка» (Bulkhead)
- Паттерны мониторинга микросервисов
- Шаблон «Агрегация логов» (Log Aggregation)
- Шаблон «Распределенная трассировка» (Distributed Tracing)
- Шаблон «Проверки здоровья» (Health Check)
- Прочие паттерны проектирования микросервисов
- Шаблон «Посредник» («Посол», Ambassador)
- Шаблон «Коляска» («Прицеп», Sidecar)
- Шаблон «Тестирование контрактов, ориентированных на потребителя» (Consumer-Driven Contract Testing)
- Шаблон «Внешняя конфигурация» (External Configuration)
Дженерики
ACID
- Atomicity — Атомарность
- Consistency — Согласованность
- Isolation — Изолированность
- Durability — Долговечность
Уровни изоляции транзакций
- https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html
- https://www.postgresql.org/docs/current/transaction-iso.html
SELECT @@GLOBAL.transaction_isolation, @@GLOBAL.transaction_read_only; SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only;
Уровень изоляции | Черновое чтение | Невоспроизводимое чтение | Фантомное чтение | Блокировка чтения |
---|---|---|---|---|
READ UNCOMMITTED | Yes | Yes | Yes | No |
READ COMMITTED | No | Yes | Yes | No |
REPEATABLE READ | No | No | Yes | No |
SERIALIZABLE | No | No | No | Yes |
DROP TABLE IF EXISTS `money_transactions`; CREATE TABLE `money_transactions` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `user_from_id` bigint(20) unsigned DEFAULT NULL, `user_to_id` bigint(20) unsigned DEFAULT NULL, `volume` decimal(19,6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; DROP TABLE IF EXISTS `money_accounts`; CREATE TABLE `money_accounts` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `user_id` bigint(20) unsigned DEFAULT NULL, `volume` decimal(19,6) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY (`user_id`) ) ENGINE=InnoDB; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), NULL, 1, 10000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), NULL, 2, 4300.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
READ UNCOMMITTED
Суть в том, что незакрепленные транзакции видны в другой открытой транзакции
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 5 | 2024-02-12 14:48:29 | 1 | 2 | 3000.000000 | | 6 | 2024-02-12 14:48:29 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 5 | 2024-02-12 14:48:29 | 1 | 2 | 3000.000000 | | 6 | 2024-02-12 14:48:29 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
READ COMMITTED
Суть в том, что если в первой транзакции был коммит - вы увидите из нее изменения, хотя находитесь в транзакции.
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; COMMIT;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 7 | 2024-02-12 15:13:40 | 1 | 2 | 3000.000000 | | 8 | 2024-02-12 15:13:40 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 7 | 2024-02-12 15:13:40 | 1 | 2 | 3000.000000 | | 8 | 2024-02-12 15:13:40 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
REPEATABLE READ
В MySQL этот уровень по-умолчанию. Суть в том, что возможно чтение фантомных строк - закрепленных другими транзакциями. Тест показал, что транзакции не изолированы
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; COMMIT;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 15:27:39 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 15:27:39 | NULL | 2 | 4300.000000 | | 3 | 2024-02-12 15:28:22 | 1 | 2 | 3000.000000 | | 4 | 2024-02-12 15:28:22 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 15:27:39 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 15:27:39 | NULL | 2 | 4300.000000 | | 3 | 2024-02-12 15:28:22 | 1 | 2 | 3000.000000 | | 4 | 2024-02-12 15:28:22 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
SERIALIZABLE
Суть в том, что вставка в левой сессии заблокируется, т.к. было чтение из правой сессии. Блокируется чтение - поэтому вы не сможете получить данные.
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; COMMIT;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
Алгоритмы
- Не забываем про рекурсию
Сложность алгоритмов
PHP
JavaScript
TypeScript
Angular
Python
Golang
- Golang
- Собеседование Golang разработчика (теоретические вопросы), Часть I
- Собеседование Golang разработчика (теоретические вопросы), Часть II. Что там с конкурентностью?
SQL
Linux Boot
Поведенческие вопросы
Решение задач
- https://www.leetcode.com/
- https://www.hackerrank.com/
- https://www.interviewbit.com/
- https://www.careercup.com/
- https://www.algoexpert.io/
- https://www.educative.io/
- https://www.pluralsight.com/
- https://www.learneroo.com/
- https://coderbyte.com/
Дизайн систем
Схема ответа
- Сбор функциональных требований (что должно быть)
- Сбор нефункциональных требований (как оно должно быть) + некая вводная
- Расчет ресурсов RPS write, RPS read, потоки данных, объемы хранилищ
- Проектирование API (основные методы, схема)
- Проектирование архитектуры (сервисы, блоки, базы данных, очереди, кэши)
- Проектирование БД (таблицы в бд сервисов)
- Оценка отказоустойчивости и масштабируемости системы
- Расчет железа и сети
- Сценарии отказов
- Логгирование
- Мониторинги
Ссылки
- https://habr.com/ru/companies/yandex/articles/564132/
- https://www.educative.io/courses/grokking-modern-system-design-interview-for-engineers-managers
- https://github.com/donnemartin/system-design-primer
- https://docs.google.com/document/d/1w3qb6SS1Hycyce5Fg5mVMdzkGYXTRskSf57IoD98ZQw/edit
- https://www.hiredintech.com/app#system-design
- Educative - https://www.educative.io/path/scalability-system-design
- YouTube Playlist - https://www.youtube.com/playlist?list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX
Время отклика систем
Latency Comparison Numbers -------------------------- L1 cache reference 0.5 ns Branch mispredict 5 ns L2 cache reference 7 ns 14x L1 cache Mutex lock/unlock 25 ns Main memory reference 100 ns 20x L2 cache, 200x L1 cache Compress 1K bytes with Zippy 10,000 ns 10 us Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD Read 1 MB sequentially from memory 250,000 ns 250 us Round trip within same datacenter 500,000 ns 500 us Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory HDD seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD Read 1 MB sequentially from HDD 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms Notes ----- 1 ns = 10^-9 seconds 1 us = 10^-6 seconds = 1,000 ns 1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
- https://ping-admin.ru/free_ping/
- До МСК
- Европа < 50
- До Урала < 50
- Владивосток 100
- США-Канада 150-250
- Южная Америка 200-300
- Азия 200-300
- Австралия 300
Расположение датацентров в мире
Не функциональные характеристики систем
Availability / Доступность
Доступность % | Недоступность в год | Недоступность в месяц | Недоступность в неделю |
---|---|---|---|
90% (1 девяток) | 36.5 дней | 72 часов | 16.8 часов |
99% (2 девяток) | 3.65 дней | 7.20 часов | 1.68 часов |
99.5% (2 девяток) | 1.83 дней | 3.60 часов | 50.4 минут |
99.9% (3 девяток) | 8.76 часов | 43.8 минут | 10.1 минут |
99.99% (4 девяток) | 52.56 минут | 4.32 минут | 1.01 минут |
99.999% (5 девяток) | 5.26 минут | 25.9 секунд | 6.05 секунд |
99.9999% (6 девяток) | 31.5 секунд | 2.59 секунд | 0.605 секунд |
99.99999% (7 девяток) | 3.15 секунд | 0.259 секунд | 0.0605 секунд |
Reliability / Надежность
Среднее время между отказами (MTBF)
Среднее время отказа (MTTF)
Среднее время восстановления(MTTR)
Scalability / Масштабируемость
- Вертикальное масштабирование - увеличение мощности узлов (CPU(Frequency, # of cores), MEM(Volume, Frequency), HDD->SSD->NVMe)
- Горизонтальное масштабирование - увеличение количества узлов
Maintainability / Поддерживаемость
- Главный параметр - MTTR
- Легкость кода и прозрачность разработки
Fault Tolerance / Устойчивость к сбоям
- Отказоустойчивость - способность системы обслуживать запросы даже при отказе ее частей.
- Можно достичь шардингом и репликацией
Сколько нужно серверов?
Блоки систем
- DNS
- Load balancers - Балансировщики
- Databases - Базы данных
- KV Storage - Хранилища Ключ Значение
- CDN - Сеть доставки контента
- Sequencer - генератор идентификаторов
- Мониторинг
- Распределенный кэш
- Распределенная очередь сообщений
- Издатель-подписчик
- Ограничитель нагрузки
- Файловое хранилище
- Распределенный поиск
- Распределенное логгирование
- Распределенное задачи по расписанию
- Шардированные счетчики.