cookie

We use cookies to improve your browsing experience. By clicking «Accept all», you agree to the use of cookies.

avatar

Microservices | Вопросы с Собеседований

Вопросы и авторские статьи по микросервисам, архитектуре, БД Контент по Kotlin/Java: t.me/KotlinQuestions

Show more
Advertising posts
3 406
Subscribers
-124 hours
-97 days
+530 days

Data loading in progress...

Subscriber growth rate

Data loading in progress...

Матчится ли контент с названием канала?)Anonymous voting
  • Да
  • Нет
0 votes
🔥 5 2 2 1
Придумать эффективный запрос Есть таблица, описывающая некоторые задачи
create table tasks
(
    id        bigserial    not null primary key,
    parent_id bigint       null,
    status    varchar(128) not null,
    data      jsonb        not null
);
У задач иерархичная структура, которая задается с помощью id, parent_id. Задача должна начать выполняться только тогда, когда все дочерние задачи выполнены. Для простоты можно считать что status принимает значения PENDING и COMPLETED Хочется придумать эффективный способ доставать задачи, которые нужно выполнить. То есть те, у которых все дочерние задачи выполнены Ограничения: - В конкретный момент PENDING задач около 1млн - В конкретных момент PENDING задач, у которых все дочерние COMPLETED около 100 - У одной задачи не более 10 дочерних
Show all...
🤔 14💅 2🔥 1
Photo unavailableShow in Telegram
Token bucket rate limiting Один из алгоритмов для ограничения числа входящих запросов. На данный момент используется во многих системах, например, AWS. Принцип работы: Есть ограниченный набор токенов, наличие токена = право исполнить запрос. Когда приходит входящий запрос, сначала проверяем, есть ли свободный токен, если есть - забираем его и исполняем запрос, если нет - отдаем 429. И поскольку токены назад не возвращаются, их надо как-то восстанавливать. Этим занимается фоновый процесс, который по крону (обычно раз в секунду) восстанавливает число свободных токенов до максимума.
Show all...
👍 28🔥 6 2💅 1
⚡Пара подходов к описанию деревьев в реляционной БД Зачастую требуется хранить какие-то иерархичные данные, например, подобие файловой системы или какую-то организационную структуру. 1. id + parent_id
create table folders
(
    id              bigserial not null,
    parent_id bigint      null references folders (id),
    data          jsonb      not null
); 
Самый простой подход, при котором храним идентификатор родительской сущности (либо null, если сущность и так корневая). Плюсы: - Простота модели - Простая вставка - Простой перенос поддерева Минусы: - “Дерево” может стать не деревом - МД не запрещает циклические ссылки - Рекурсивные запросы, чтобы доставать поддерево по id корня 2. id, path + parent_id, parent_path Помимо id добавляется path - путь по айдишникам до текущей сущности. Это нам позволяет сделать более интересные констрейнты и гарантировать, что мы гарантированно имеем дело с деревом.
create table folders
(
    id          bigserial not null,
    path        varchar   not null,
    parent_id   bigint    null,
    parent_path varchar   null,
    data        jsonb     not null

    constraint ck__folders__path
            check (path = coalesce(parent_path, '/') || id || '/'),

    -- нужен для FK
    constraint uc__folders__path__id
        unique (path, id),

    constraint fk__folders__parent_id__parent_path
        foreign key (parent_path, parent_id) references folders (path, id)
            match full
);
Здесь мы гарантируем, что 1) path корневой папки - это /<id>/ 2) path некорневой папки - это <parent_path><id>/ Что позволяет обеспечить отсутствие циклов Плюсы: - Гарантия отсутствия циклов - Простой запрос поддерева - where path like ‘/1/2/3/%’ Минусы: - Сложность модели - Более сложная вставка - Сложный перенос поддерева
Show all...
👍 31🔥 3 3🤔 1 1
Caching patterns При работе с кешом возникает вопрос “в какой момент нужно синхронизировать данные из бд и кеша?”. Рассмотрим три часто встречающихся паттерна: 1. Read-aside caching Наиболее простой и часто используемый паттерн. Как происходит чтение: - Пробуем достать данные из кеша - Если не получилось, идем в БД, складываем в кеш Как происходит запись: - Просто пишем в БД 2. Write-aside caching Паттерн с чтением аналогичным предыдущему варианту, но при записи сразу обновляем и кеш, что в теории может позволить увеличить hit rate ценой того, что в кеш могут попадать данные, которые не нужны для чтения. Как происходит чтение: - Пробуем достать данные из кеша - Если не получилось, идем в БД, складываем в кеш Как происходит запись: - Пишем в БД - Пишем в кеш 3. Full caching Кеш (обычно по крону) сам себя обновляет, подгружая все необходимые данные из БД. Подходит для случаев, когда хотим добиться ~100% hit rate, и данные целиком влезают в кеш. Как происходит чтение: - Просто читаем из кеша Как происходит запись: - Просто пишем в БД
Show all...
👍 27🔥 6💅 3 2
Школы unit-тестирования Лондонская: - Все зависимости (изменяемые) заменяются на моки - Под юнитом подразумевается один класс - Акцент на проверку взаимодействия компонентов Пример:
@Test
fun `test user creation`() {
    // given
    val userSaver = mock<UserSaver>()
    val userService = UserService(userSaver)
    // when
    userService.createUser("username")
    // then
    verify(userSaver).save(any<User>())
}
Классическая: - За редким исключением только внепроцессные зависимости (БД, брокер) заменяются на моки - Под юнитом может подразумеваться набор классов - Акцент на проверку результатов вызова методов и состояния
@Test
fun `test user creation`() {
    // given
    val userService = UserService(UserSaver())
    // when
    userService.createUser("username")
    // then
    assertEquals(User(“username”), userService.getUser(“username”))
}
Лондонская школа позволяет разрабатывать в стиле TDD, начиная с высокоуровневых тестов, поскольку нам не требуются реальные зависимости. И проверяют какой-то аспект поведения класса (что был вызов UserSaver::save при вызове UserService::createUser). В классической школе зачастую проверяется корректная работа конкретного сценария (что UserService::createUser корректно сохранил пользователя). А какую школу используете вы и почему?
Show all...
💅 8👍 6🔥 5
Testcontainers ❓Проблема: В рамках интеграционного тестирования хочется не мокать, а честно поднимать зависимости, такие как БД, брокер сообщений и т.д. ✅ Решение: Testcontainers - фреймворк, позволяющий запускать контейнеры с различными зависимостями прямо из кода. Пример на Java:
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(
  "postgres:15-alpine"
);

@BeforeAll
static void beforeAll() {
  postgres.start();
}

@AfterAll
static void afterAll() {
  postgres.stop();
}
На данный момент поддержано более 50 заранее сконфигурированных контейнеров, включая Postgres, Kafka, Elasticsearch, MySQL. И сама реализация фреймворка существует для .NET, Go, Java, Node.js, также есть кастомные пользовательские реализации для многих других языков.
Show all...
👍 29🔥 13💅 4
Photo unavailableShow in Telegram
Temporal Temporal - оркестрационный движок, который координирует работу распределенных воркеров, сохраняет промежуточные результаты, делает ретраи и т.д. Temporal cluster состоит из следующих компонентов: - Frontend gateway: авторизация, rate limit - History subsystem: хранит состояние задач в БД - Matching subsystem: управляет очередьми задач - Worker Service: исполняет внутренние (не пользовательские) фоновые процессы ❗️Пользовательские workflow исполняются не temporal кластером, а внешними пользовательскими воркерами. Temporal лишь координирует их работу. Возможности: - Обработка распределенных транзакций - Запускание задач по крону - Исполнение стейт машин - И еще некоторые вещи Как описываются задачи: Activity - некоторое атомарное действие, например, вызов API или запрос в базу. Это действие должно быть идемпотентным, чтобы, например, в случае ретраев из-за сетевых проблем не сделать некоторое действие дважды. Workflow состоят из вызовов activity и некоторой дополнительной логики. И как раз в местах вызова activity сохраняются промежуточные результаты workflow. Всё это описывается с помощью SDK на стороне приложения, на текущий момент существуют реализации для Go, Java, PHP, Python, Typescript, .NET. Посмотреть пример описания workflow можно тут.
Show all...
👍 12🔥 7💅 5
Ставьте 💅 на этот пост, если нужен рассказ про возможности Temporal
Show all...
Open Source Durable Execution

Build invincible apps with Temporal's open-source durable execution platform to guarantee successful execution, even in the presence of failures.

💅 141 1🤔 1
Durable executions Представим, что есть некоторая задача
workflow {
    firstCall()
    sleep(1 hour)
    secondCall()
    sleep(1 hour)
    thirdCall()
}
Если мы ее запустим, то нужно, чтобы воркер, который ее будет исполнять, был жив минимум два часа подряд. Если по-середине ожидания что-то пойдет не так, то весь прогресс потеряется. Именно на этом примере можно описать концепцию Durable executions: После того, как мы сделали firstCall(), мы не будем ждать, а сделаем следующее: - Сохраним в состояние задачи, что мы уже сделали firstCall() - Зашедулим ее на +1 час Спустя час какой-то другой воркер сможет взять эту задачу и продолжить с прыдыдущего “чекпоинта”. То есть мы сохраняем прогресс по определенным частям задачи, что позволяет переживать отказы воркеров и позволяет исполнять задачу по частям разными воркерами. И сейчас существует довольно много Workflow engines, которые строятся на этой концепции.
Show all...
GitHub - meirwah/awesome-workflow-engines: A curated list of awesome open source workflow engines

A curated list of awesome open source workflow engines - meirwah/awesome-workflow-engines

👍 24🔥 7💅 5
Choose a Different Plan

Your current plan allows analytics for only 5 channels. To get more, please choose a different plan.