Initial commit
This commit is contained in:
commit
e324c5a253
71
.drone.yml
Normal file
71
.drone.yml
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: docker-build-and-push
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
|
||||
image_pull_secrets:
|
||||
- DOCKER_AUTH
|
||||
|
||||
steps:
|
||||
- name: build site
|
||||
# https://hub.docker.com/r/library/docker
|
||||
pull: always
|
||||
image: docker.struchkov.dev/quartz:develop
|
||||
environment:
|
||||
GITHUB_SSH:
|
||||
from_secret: GITHUB_SSH
|
||||
commands:
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
- echo "$GITHUB_SSH" >> ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- git clone --depth 1 --single-branch --branch master https://git.struchkov.dev/upagge/digital-garden.git /usr/src/app/content
|
||||
- cd /usr/src/app/content
|
||||
# - git remote add github git@github.com:uPagge/digital-garden.git
|
||||
# - git push github
|
||||
- cd /usr/src/app
|
||||
- cp ./content/.quartz/quartz.config.ts .
|
||||
- cp ./content/.quartz/quartz.layout.ts .
|
||||
- npx quartz build
|
||||
- mv public /drone/src
|
||||
- name: publish to server
|
||||
image: private.docker.struchkov.dev/mkdocs:latest
|
||||
environment:
|
||||
SSH_DEPLOY_KEY:
|
||||
from_secret: SSH_DEPLOY_KEY
|
||||
SSH_DEPLOY_HOST:
|
||||
from_secret: SSH_DEPLOY_HOST
|
||||
SSH_DEPLOY_PORT:
|
||||
from_secret: SSH_DEPLOY_PORT
|
||||
SSH_DEPLOY_PATH:
|
||||
from_secret: SSH_DEPLOY_PATH
|
||||
SSH_DEPLOY_USER:
|
||||
from_secret: SSH_DEPLOY_USER
|
||||
commands:
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_DEPLOY_KEY" >> ~/.ssh/id_rsa
|
||||
- chmod 700 ~/.ssh
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- ssh-keyscan -p $SSH_DEPLOY_PORT $SSH_DEPLOY_HOST >> ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- tar czf - -C ./public . | ssh -p $SSH_DEPLOY_PORT $SSH_DEPLOY_USER@$SSH_DEPLOY_HOST "cd $SSH_DEPLOY_PATH/ru-new && tar xzf -"
|
||||
- ssh -p $SSH_DEPLOY_PORT $SSH_DEPLOY_USER@$SSH_DEPLOY_HOST "rm -rf $SSH_DEPLOY_PATH/ru/* && mv $SSH_DEPLOY_PATH/ru-new/* $SSH_DEPLOY_PATH/ru"
|
||||
|
||||
|
||||
# drone sign --save upagge/digital-garden
|
||||
---
|
||||
kind: signature
|
||||
hmac: 136d4effa27f318fb6ff0cf16bc1bf7b20b428610832f7bdd8224c164a804e69
|
||||
|
||||
...
|
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
.obsidian/workspace.json
|
||||
.obsidian/workspace-mobile.json
|
||||
|
||||
# Ignore Smart Connections folder because embeddings file is large and updated frequently
|
||||
.smart-connections
|
||||
|
||||
.DS_Store
|
||||
.idea/
|
||||
/meta/files/zip_image.sh
|
||||
/meta/files/zip_image_compression.log
|
||||
/meta/files/zip_image_error.log
|
91
.quartz/quartz.config.ts
Normal file
91
.quartz/quartz.config.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { QuartzConfig } from "./quartz/cfg"
|
||||
import * as Plugin from "./quartz/plugins"
|
||||
|
||||
/**
|
||||
* Quartz 4.0 Configuration
|
||||
*
|
||||
* See https://quartz.jzhao.xyz/configuration for more information.
|
||||
*/
|
||||
const config: QuartzConfig = {
|
||||
configuration: {
|
||||
pageTitle: "Struchkov's Garden 🪴",
|
||||
enableSPA: false,
|
||||
enablePopovers: true,
|
||||
locale: "ru-RU",
|
||||
baseUrl: "garden.struchkov.dev/ru",
|
||||
ignorePatterns: ["private", "templates", ".obsidian"],
|
||||
defaultDateType: "modified",
|
||||
theme: {
|
||||
fontOrigin: "googleFonts",
|
||||
cdnCaching: true,
|
||||
typography: {
|
||||
header: "Montserrat",
|
||||
body: "Noto Sans",
|
||||
code: "Fira Code",
|
||||
},
|
||||
colors: {
|
||||
lightMode: {
|
||||
light: "#faf8f8",
|
||||
lightgray: "#e5e5e5",
|
||||
gray: "#b8b8b8",
|
||||
darkgray: "#292929",
|
||||
dark: "#2b2b2b",
|
||||
secondary: "#2c678d",
|
||||
tertiary: "#84a59d",
|
||||
highlight: "rgba(0, 80, 219, 0.15)",
|
||||
textHighlight: "#fff3bc",
|
||||
shareIcon: "https://garden.struchkov.dev/ru/static/social-sprite-color.svg"
|
||||
},
|
||||
darkMode: {
|
||||
light: "#161618",
|
||||
lightgray: "#393639",
|
||||
gray: "#646464",
|
||||
darkgray: "#d4d4d4",
|
||||
dark: "#ebebec",
|
||||
secondary: "#7b97aa",
|
||||
tertiary: "#84a59d",
|
||||
highlight: "rgba(143, 159, 169, 0.15)",
|
||||
textHighlight: "#8b651d",
|
||||
shareIcon: "https://garden.struchkov.dev/ru/static/social-sprite.svg"
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
transformers: [
|
||||
Plugin.FrontMatter(),
|
||||
Plugin.CreatedModifiedDate({
|
||||
priority: ["git", "frontmatter"],
|
||||
}),
|
||||
Plugin.SyntaxHighlighting({
|
||||
theme: {
|
||||
light: "github-light",
|
||||
dark: "vitesse-dark",
|
||||
},
|
||||
keepBackground: false,
|
||||
}),
|
||||
Plugin.HardLineBreaks(),
|
||||
Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }),
|
||||
Plugin.GitHubFlavoredMarkdown(),
|
||||
Plugin.TableOfContents(),
|
||||
Plugin.CrawlLinks({ markdownLinkResolution: "relative", lazyLoad: true }),
|
||||
Plugin.Description(),
|
||||
],
|
||||
filters: [Plugin.RemoveDrafts()],
|
||||
emitters: [
|
||||
Plugin.AliasRedirects(),
|
||||
Plugin.ComponentResources(),
|
||||
Plugin.ContentPage(),
|
||||
Plugin.FolderPage(),
|
||||
Plugin.TagPage(),
|
||||
Plugin.ContentIndex({
|
||||
enableSiteMap: true,
|
||||
enableRSS: true,
|
||||
}),
|
||||
Plugin.Assets(),
|
||||
Plugin.Static(),
|
||||
Plugin.NotFoundPage(),
|
||||
],
|
||||
},
|
||||
}
|
||||
export default config
|
64
.quartz/quartz.layout.ts
Normal file
64
.quartz/quartz.layout.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import {PageLayout, SharedLayout} from "./quartz/cfg"
|
||||
import * as Component from "./quartz/components"
|
||||
|
||||
// components shared across all pages
|
||||
export const sharedPageComponents: SharedLayout = {
|
||||
head: Component.Head(),
|
||||
header: [],
|
||||
afterBody: [
|
||||
Component.Backlinks(),
|
||||
// Component.SocialShare(),
|
||||
Component.Remark({
|
||||
options: {
|
||||
host: 'https://comments.struchkov.dev',
|
||||
siteId: 'gardenru',
|
||||
locale: 'ru',
|
||||
}
|
||||
}),
|
||||
Component.YandexMetrika(),
|
||||
],
|
||||
footer: Component.Footer({
|
||||
links: {
|
||||
"About Me": "https://mark.struchkov.dev/cv/",
|
||||
"B.log": "https://struchkov.dev",
|
||||
"Telegram": "https://t.me/struchkov_dev",
|
||||
},
|
||||
}),
|
||||
}
|
||||
const githubSourceConfig = {
|
||||
repoLink: "https://github.com/upagge/digital-garden",
|
||||
branch: "master"
|
||||
}
|
||||
// components for pages that display a single page (e.g. a single note)
|
||||
export const defaultContentPageLayout: PageLayout = {
|
||||
beforeBody: [
|
||||
Component.Breadcrumbs({showCurrentPage: false}),
|
||||
Component.ArticleTitle(),
|
||||
Component.ContentMeta({showReadingTime: false}),
|
||||
Component.TagList()
|
||||
],
|
||||
left: [
|
||||
Component.PageTitle(),
|
||||
Component.MobileOnly(Component.Spacer()),
|
||||
Component.Search(),
|
||||
Component.DesktopOnly(Component.RecentNotes({ showTags: false, limit: 4 })),
|
||||
Component.DesktopOnly(Component.Ads()),
|
||||
Component.Darkmode(),
|
||||
],
|
||||
right: [
|
||||
Component.DesktopOnly(Component.TableOfContents()),
|
||||
Component.DesktopOnly(Component.GithubSource(githubSourceConfig)),
|
||||
],
|
||||
}
|
||||
|
||||
// components for pages that display lists of pages (e.g. tags or folders)
|
||||
export const defaultListPageLayout: PageLayout = {
|
||||
beforeBody: [Component.Breadcrumbs(), Component.ArticleTitle(), Component.ContentMeta()],
|
||||
left: [
|
||||
Component.PageTitle(),
|
||||
Component.MobileOnly(Component.Spacer()),
|
||||
Component.Search(),
|
||||
Component.Darkmode(),
|
||||
],
|
||||
right: [],
|
||||
}
|
33
awareness/Медитация.md
Normal file
33
awareness/Медитация.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: "[[2023-09-20]]"
|
||||
aliases:
|
||||
- медитация
|
||||
- релаксация
|
||||
- релакс
|
||||
- медитацией
|
||||
- медитацию
|
||||
- медитации
|
||||
---
|
||||
Медитация работает на физиологическом уровне: замедляет дыхание и частоту сердечных сокращений. [Замедляет](https://www.psychologytoday.com/blog/the-mysteries-love/201503/how-deep-relaxation-affects-brain-chemistry) [[../../../knowledge/human/строение/Симпатическая нервная система|симпатическую нервную систему]]. Как результат - снижается уровень [кортизола](Кортизол.md).
|
||||
|
||||
После сессии медитации меняется даже активность мозга во время сна - это видно в исследованиях, проведенных с использованием ЭЭГ. Также эффективный и [доказанный](https://www.researchgate.net/publication/227735096_Practitioners_of_vipassana_meditation_exhibit_enhanced_slow_wave_sleep_and_REM_sleep_states_across_different_age_groups) способ увеличить долю ценного [глубокого сна](Фазы%20сна.md).
|
||||
|
||||
Помимо влияния на сон, медитация имеет много других подтвержденных эффектов, влияющих на продуктивность и не только. В англоязычной Википедии есть [большая статья,](https://en.wikipedia.org/wiki/Research_on_meditation) посвященная не в целом медитации, а именно ее научно доказанным свойствам. В частности, она очень эффективна против [стресса](Стресс.md). А в [[2019]] году в течение 3-недельного эксперимента благодаря медитации испытуемые [стали удерживать внимание на 24% эффективнее.](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6329416/)
|
||||
|
||||
Многие ошибочно полагают, что медитировать можно только сидя в позе лотоса, с закрытыми глазами и обязательно под музыку или речь диктора. Но это совсем не так. Медитировать и тренировать внимание можно во время любых действий, которые обычно делаешь на [[Режим автопилота мозга|автоматизме]].
|
||||
|
||||
Медитация помогает расслабиться и эмоционально, за счет [удаления](https://academic.oup.com/scan/article/2/4/259/1676806/Mindfulness-training-and-neural-integration) ранее сформированных нервных связей.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Осознанность|00 Осознанность]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2023-09-20]]
|
||||
### Дополнительные материалы
|
||||
- [Effects of meditation - Wikipedia](https://en.wikipedia.org/wiki/Effects_of_meditation#Changes_in_the_brain)
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
21
awareness/Практики осознанности.md
Normal file
21
awareness/Практики осознанности.md
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2025-01-11
|
||||
---
|
||||
Практики осознанности имеют отличную доказанную эффективность в этом деле, что было показано во [многих исследованиях.](https://en.wikipedia.org/wiki/Effects_of_meditation#cite_note-Walsh_e10844-18) К примеру, в [[2019]] году в течение 3-недельного эксперимента благодаря [[Медитация|медитации]] испытуемые [стали удерживать внимание на 24% эффективнее.](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6329416/)
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Осознанность|00 Осознанность]]
|
||||
**Родитель**:: [[../Практики|Практики]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2025-01-11]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
24
awareness/Режим автопилота мозга.md
Normal file
24
awareness/Режим автопилота мозга.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
aliases:
|
||||
- автопилот
|
||||
- автопилоте
|
||||
- автопилота
|
||||
- автоматизме
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: "[[2023-10-18]]"
|
||||
---
|
||||
Существенная часть жизни людей проходит в «режиме автопилота». Человеческий мозг стремится к оптимизации и экономии [[../../../knowledge/human/ресурсы/Энергия организма|энергии]]. Чтобы делать твое существование более эффективным, часть действий [не осознается](https://www.researchgate.net/publication/227344004_Mindless_Eating_The_200_Daily_Food_Decisions_We_Overlook) и предпринимается на автомате.
|
||||
|
||||
В общем и целом, такой режим весьма полезен — он позволяет не тратить [мыслетопливо](Мыслетопливо.md) на повторяющуюся [рутину](Рутина.md). Но некоторые так сильно привыкают к автопилоту, что ручное управление уже просто не включается. Практики [осознанности](../../../garden/ru/meta/zero/00%20Осознанность.md) как раз помогают сосредоточить свое внимание на текущем моменте и прожить его полноценно.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Осознанность|00 Осознанность]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2023-10-18]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
52
dev/Code Review.md
Normal file
52
dev/Code Review.md
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../../../meta/files/Pasted image 20241103220651.png]]
|
||||
|
||||
- **Code Style (Стиль кода)**:
|
||||
- Применен ли стиль форматирования проекта?
|
||||
- Достаточно ли [[Читаемый код|читаем код]] (длина методов и т.п.)?
|
||||
- Соблюдается ли принцип DRY (Don't Repeat Yourself)?
|
||||
- Соответствует ли именование общепринятым соглашениям?
|
||||
- **Tests (Тесты)**:
|
||||
- Проходят ли все тесты?
|
||||
- Новые функции протестированы?
|
||||
- Покрыты ли крайние случаи?
|
||||
- Используются ли юнит-тесты и интеграционные тесты?
|
||||
- Есть ли тесты для нефункциональных требований, например, производительность?
|
||||
- **Documentation (Документация)**:
|
||||
- Есть ли документация для новых функций?
|
||||
- Покрыты ли различные виды документации: README, API, user guide и др.?
|
||||
- Понятны ли документы, нет ли ошибок в типографике и грамматике?
|
||||
- **Implementation Semantics (Семантика реализации)**:
|
||||
- Соответствует ли реализация исходным требованиям?
|
||||
- Корректна ли логика?
|
||||
- Нет ли излишней сложности?
|
||||
- Надежна ли реализация (вопросы конкурентности, обработки ошибок и т.д.)?
|
||||
- Хорошая ли производительность?
|
||||
- Безопасна ли (например, отсутствие SQL-инъекций)?
|
||||
- Можно ли наблюдать за реализацией (метрики, логирование и т.д.)?
|
||||
- Тянут ли новые зависимости свой вес, приемлема ли их лицензия?
|
||||
- **API Semantics (Семантика API)**:
|
||||
- Насколько компактно API, оно достаточно большое или наоборот?
|
||||
- Есть ли один способ достижения цели, без множественных подходов?
|
||||
- API предсказуемо, следует ли оно принципу наименьшего удивления?
|
||||
- Являются ли внутренности API скрытыми от пользователя?
|
||||
- Нет ли изменений, ломающих обратную совместимость?
|
||||
- Насколько полезно и не слишком специфично API?
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Разработка|00 Разработка]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
29
dev/GraphQL.md
Normal file
29
dev/GraphQL.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../meta/files/images/Pasted image 20241103004648.png]]
|
||||
|
||||
- Предоставляет клиентам единую конечную точку для запроса именно тех данных, которые им нужны.
|
||||
- Клиенты указывают точные поля, требуемые во вложенных запросах, и сервер возвращает оптимизированный ответ, содержащую только эти поля.
|
||||
- Поддерживает модификации для изменения данных и подписки на уведомления в режиме реального времени.
|
||||
- Отлично подходит для объединения данных из нескольких источников и хорошо работает с быстро меняющимися требованиями к интерфейсу.
|
||||
- Однако это переносит сложность на сторону клиента и может допускать некорректные запросы, если они не защищены должным образом.
|
||||
- Стратегии кэширования могут быть более сложными, чем [[architecture/Representation State Transfer|REST]].
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[architecture/Протоколы коммуникаций|Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
21
dev/Key-Value хранилище.md
Normal file
21
dev/Key-Value хранилище.md
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
aliases:
|
||||
- ключ-значение
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-24
|
||||
---
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Разработка|00 Разработка]]
|
||||
**Родитель**:: [[Тип хранилища данных|Тип хранилища данных]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-24]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
33
dev/Tombstone.md
Normal file
33
dev/Tombstone.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
aliases:
|
||||
- софт-удаление
|
||||
- мягкое удаление
|
||||
- soft-удаление
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-31
|
||||
---
|
||||
**Tombstone** — это маркер, указывающий, что запись удалена логически, но физически все еще находится в базе данных. Такой подход позволяет системе лучше справляться с репликацией и конфликтами данных, а также обеспечивает корректное выполнение запросов к данным, которые могли быть удалены.
|
||||
|
||||
**Плюсы:**
|
||||
- **Репликация данных**: Tombstones упрощают [[architecture/highload/Репликация БД|репликацию]]. Поскольку данные могут реплицироваться между множеством узлов, простое удаление записи на одном узле не гарантирует, что она будет удалена на всех узлах. Tombstone помогает согласовать состояние данных между узлами.
|
||||
- **История данных**: В системах, где данные удаляются, но запросы могут возвращаться к старым версиям данных, tombstones позволяют системе правильно обрабатывать такие запросы, показывая, что данные были удалены, а не просто отсутствуют.
|
||||
|
||||
**Особенности:**
|
||||
- **Процесс Compaction**: Со временем, когда гарантируется, что все узлы системы обновили свое состояние и больше не требуется хранение информации об удалении, tombstones могут быть удалены, чтобы освободить место и улучшить производительность системы. Этот процесс называется compaction.
|
||||
- **Проблема накопления tombstones**: Накопление большого количества tombstones может замедлить производительность базы данных, так как системе приходится пропускать эти маркеры при выполнении запросов. Это особенно актуально для систем с высокой частотой удаления записей.
|
||||
- [[database/Частичный индекс|Частичный индекс]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Реляционная база данных|00 Реляционная база данных]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-10-31]]
|
||||
**Автор**:: [[2024-10-31]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
147
dev/Universal Unique IDentifier.md
Normal file
147
dev/Universal Unique IDentifier.md
Normal file
@ -0,0 +1,147 @@
|
||||
---
|
||||
aliases:
|
||||
- UUID
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2023-11-12
|
||||
zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
**UUID (Universal Unique IDentifier)** — это 128-битный идентификатор, представленный в виде строки. Однако для пользовательских данных доступно только 122 бита, так как 6 бит зарезервировано:
|
||||
- 4 бита используются для указания версии UUID;
|
||||
- 2 бита определяют вариант UUID.
|
||||
|
||||
![](../meta/files/images/Pasted%20image%2020231112132644.png)
|
||||
|
||||
**Заполнение 122 бит зависит от версии UUID:**
|
||||
- **Специальные UUID**:
|
||||
- **Nil UUID** — все биты равны 0.
|
||||
- **Max UUID** — все биты равны 1 (или “f” в шестнадцатеричной записи).
|
||||
- **Стандартные версии UUID** (по спецификации RFC 4122) — всего 5 версий.
|
||||
- **Новые версии** — три дополнительных варианта, не описанных в RFC 4122.
|
||||
|
||||
## UUID V1
|
||||
![](../meta/files/images/Pasted%20image%2020231112133236.png)
|
||||
|
||||
UUID версии 1 использует текущее время по григорианскому календарю и имеет следующие особенности:
|
||||
- Время записывается в обратном порядке, что делает невозможной сортировку UUID по времени создания.
|
||||
- Включает случайную компоненту для увеличения уникальности.
|
||||
- Node ID привязан к сетевому оборудованию (обычно к MAC-адресу). Это значение рекомендуется подменять на псевдослучайное для повышения конфиденциальности.
|
||||
|
||||
**Недостатки:**
|
||||
- Не подходит для сортировки по времени.
|
||||
|
||||
**Преимущества:**
|
||||
- Быстрая вставка в базу данных, независимо от размера данных.
|
||||
- UUID сложно перебрать за счет высокой энтропии.
|
||||
- Возможность извлечь метку времени из идентификатора.
|
||||
## UUID V3
|
||||
![](../meta/files/images/Pasted%20image%2020231112133916.png)
|
||||
|
||||
UUID версии 3 (V3) — это идентификатор, основанный на алгоритме хеширования [[cryptography/MD5|MD5]]. В отличие от UUID версии 1, который использует текущее время, UUID V3 генерируется на основе имени (строки) и пространства имен (namespace). Основная идея заключается в том, что при использовании одинаковых имени и пространства имен результатом всегда будет один и тот же UUID.
|
||||
|
||||
**Пример использования:** Когда нужно сгенерировать уникальный идентификатор для имени домена в сети, применяется UUID V3 с пространством имен **DNS** и строкой, содержащей доменное имя. Например:
|
||||
|
||||
```
|
||||
UUID(DNS, "example.com") → 5df41881-3aed-3515-88a7-2f4a814cf09e
|
||||
```
|
||||
|
||||
**Преимущества:**
|
||||
- **Детерминированность**: один и тот же вход (имя + пространство имен) всегда генерирует одинаковый UUID, что удобно, если требуется уникальный идентификатор для конкретного объекта, который может быть повторно создан.
|
||||
|
||||
**Недостатки:**
|
||||
- **Зависимость от MD5**: Алгоритм [[cryptography/MD5|MD5]] считается криптографически уязвимым, что делает UUID V3 неподходящим для использования в приложениях, требующих высокой безопасности.
|
||||
- **Не случайный**: В отличие от UUID версии 1 или 4, UUID V3 предсказуем, так как основывается на статическом входе.
|
||||
## UUID V4
|
||||
![](../meta/files/images/Pasted%20image%2020231112133824.png)
|
||||
|
||||
UUID версии 4 (V4) — это случайный идентификатор, где большинство битов генерируются случайным образом. Вся структура UUID V4 почти полностью случайна, за исключением 6 бит, зарезервированных для указания версии и варианта.
|
||||
|
||||
**Преимущества:**
|
||||
- **Сложность перебора**: Из-за случайной природы UUID V4 крайне сложно предугадать следующий идентификатор или перебрать все возможные значения. Всего существует 2^{122} возможных вариантов UUID V4, что делает их практически уникальными в реальных условиях.
|
||||
- **Простота генерации**: Процесс создания UUID V4 не требует внешних данных (время, имя или пространство имен), что делает его проще в реализации и использовании.
|
||||
- **Конфиденциальность**: Поскольку в UUID V4 нет привязки к времени или аппаратному обеспечению (в отличие от V1), он не раскрывает никакой дополнительной информации, такой как метка времени или MAC-адрес устройства.
|
||||
|
||||
**Недостатки:**
|
||||
- **Не сортируемый**: UUID V4 нельзя отсортировать по времени или другим критериям, так как он полностью основан на случайных данных.
|
||||
- **Замедленная вставка в БД**: В больших базах данных, по мере увеличения количества записей, время вставки новых записей с UUID V4 может расти. Это связано с тем, что случайные значения распределяются неравномерно, что может вызывать фрагментацию [[database/Индекс базы данных|индексов]], особенно при использовании кластеризованных индексов.
|
||||
- **Не содержит полезной информации**: В отличие от UUID версий 1 и 3, UUID V4 не хранит никаких дополнительных данных (например, метку времени или привязку к конкретному объекту).
|
||||
## UUID V5
|
||||
![](../meta/files/images/Pasted%20image%2020231112134012.png)
|
||||
|
||||
UUID версии 5 (V5) очень похож на UUID версии 3 (V3), с той лишь разницей, что вместо [[cryptography/Хеш-функция|хеш-функции]] [[cryptography/MD5|MD5]] используется более современная и безопасная [[cryptography/Хеш-функция|хеш-функция]] SHA-1. Как и в случае с V3, UUID V5 генерируется на основе входных данных — имени и пространства имен (namespace).
|
||||
|
||||
**Преимущества:**
|
||||
- **Детерминированность**: Как и UUID V3, версия 5 всегда генерирует один и тот же UUID для одного и того же сочетания имени и пространства имен.
|
||||
- **Современная хеш-функция**: В отличие от устаревшего и криптографически слабого [[cryptography/MD5|MD5]], SHA-1 обеспечивает более высокую безопасность, хотя и не является идеальной для криптографических приложений в наше время.
|
||||
- **Уникальность в пределах пространства имен**: Гарантирует уникальность идентификаторов при использовании различных пространств имен.
|
||||
|
||||
**Недостатки:**
|
||||
- **Время вставки в базу данных**: В больших базах данных с увеличением количества записей может увеличиваться время вставки, особенно если UUID используется как индекс. Это связано с неравномерностью распределения случайных значений.
|
||||
- **Не сортируемый**: Как и UUID V4, идентификаторы версии 5 не могут быть отсортированы по времени или другим логическим критериям, поскольку они зависят от хеширования входных данных.
|
||||
- **Не хранит полезной информации**: UUID V5 не содержит дополнительных данных, таких как метка времени, информация о хосте или устройстве.
|
||||
## UUID V6
|
||||
![](../meta/files/images/Pasted%20image%2020231112133512.png)
|
||||
|
||||
UUID версии 6 (V6) был разработан для устранения одного из ключевых недостатков UUID версии 1 (V1) — невозможности сортировки. UUID V6 сохраняет идею использования времени для генерации идентификатора, но изменяет порядок записи временной метки, что позволяет идентификаторам быть сортируемыми по времени.
|
||||
|
||||
**Преимущества:**
|
||||
- **Сортируемость**: Главное отличие UUID V6 от V1 — это возможность сортировки идентификаторов по времени их создания. UUID V6 можно отсортировать по времени.
|
||||
- **Метка времени**: UUID V6 сохраняет возможность извлечения метки времени из идентификатора, что полезно для некоторых приложений, где важно отслеживать время создания записи.
|
||||
- **Конфиденциальность**: Как и в V1, UUID V6 может включать привязку к оборудованию (например, MAC-адрес), но рекомендуется использовать псевдослучайные данные для повышения конфиденциальности.
|
||||
|
||||
**Недостатки:**
|
||||
- **Сложность в использовании с кластеризованными индексами**: Хотя UUID V6 улучшает сортировку, время вставки в базу данных может увеличиваться при большом количестве записей, особенно если используется кластеризованный индекс, который требует поддержания порядка.
|
||||
- **Не случайный**: В отличие от UUID V4, версия 6 не является полностью случайной, что может быть недостатком в сценариях, где важна непредсказуемость.
|
||||
## UUID V7
|
||||
![](Pasted%20image%2020231112133651.png)
|
||||
|
||||
UUID версии 7 (V7) представляет собой новую версию UUID, которая использует Unix-время вместо григорианского, применяемого в UUID версии 1 (V1). Такой подход делает UUID V7 более компактным и эффективным для хранения временных меток, поскольку Unix-время занимает меньше места по сравнению с григорианским временем.
|
||||
|
||||
**Преимущества:**
|
||||
- **Сортируемость**: UUID V7 сохраняет временные метки в формате Unix, что делает его естественно сортируемым по времени создания. Это полезно для реляционных баз данных, где важен порядок записей.
|
||||
- **Константное время вставки**: Поскольку UUID V7 монотонно увеличивается со временем и включает случайные данные, вставка в базу данных происходит с постоянным временем.
|
||||
- **Метка времени**: UUID V7 сохраняет метку времени, что позволяет извлечь момент создания идентификатора.
|
||||
- **Сложность перебора**: UUID V7 сохраняет высокий уровень уникальности за счет случайных битов, что делает его труднопредсказуемым и сложным для перебора.
|
||||
|
||||
**Недостатки:**
|
||||
- **Меньшая случайность в начальной части**: Поскольку первые биты связаны с временной меткой, это снижает уровень случайности в первой части UUID. Однако это компенсируется случайной частью идентификатора.
|
||||
|
||||
UUID V7 может иметь несколько типов генерации, в зависимости от требуемого уровня случайности и последовательности.
|
||||
1. **Тип 1 (по умолчанию)**: `UuidCreator.getTimeOrderedEpoch();`
|
||||
- **Плюсы**: Сортируемый, достаточно быстрый, подходит для большинства приложений, где важна как уникальность, так и последовательность.
|
||||
- **Минусы**: Более низкий уровень случайности по сравнению с другими типами.
|
||||
2. **Тип 2 (плюс 1)**: `UuidCreator.getTimeOrderedEpochPlus1();`
|
||||
- Обеспечивает более высокую уникальность и последовательность за счет монотонного увеличения.
|
||||
- **Плюсы**: Подходит для приложений, требующих строгого соблюдения порядка идентификаторов.
|
||||
- **Минусы**: Менее случаен, чем Тип 3.
|
||||
- **Производительность**: Генерируется в 20 раз быстрее, чем `UUID.randomUUID()`.
|
||||
3. **Тип 3 (плюс n)**: `UuidCreator.getTimeOrderedEpochPlusN()`;
|
||||
- **Особенности**: Максимальная уникальность за счет случайного увеличения.`
|
||||
- **Плюсы**: Подходит для сценариев, требующих высокой уникальности без строгих требований к последовательности.
|
||||
- **Минусы**: Меньшая предсказуемость и последовательность по сравнению с Типами 1 и 2.
|
||||
- **Производительность**: Генерируется в два раза быстрее, чем `UUID.randomUUID()`.
|
||||
## Производительность
|
||||
Генерируем по 200000 идентификаторов в цикле, после чего вставляем эти данные.
|
||||
|
||||
![](../meta/files/images/Pasted%20image%2020231112141139.png)
|
||||
|
||||
Массовое чтение, через IN
|
||||
![](../meta/files/images/Pasted%20image%2020231112141352.png)
|
||||
|
||||
![](../meta/files/images/Pasted%20image%2020231112141530.png)
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../meta/zero/00 Разработка|00 Разработка]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2023-11-12]]
|
||||
### Дополнительные материалы
|
||||
- [ID-баттл: UUID vs автоинкремент / Валентин Удальцов - YouTube](https://www.youtube.com/watch?v=Xr_SNd9LIng&t=1762s)
|
||||
- [Библиотека для генерации UUID в Java. Все версии](https://github.com/f4b6a3/uuid-creator)
|
||||
- [[../../../_inbox/Автоинкремент|Автоинкремент]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
28
dev/algorithm/Adaptive Replacement Cache.md
Normal file
28
dev/algorithm/Adaptive Replacement Cache.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
- "[[Алгоритм вытеснения кэша]]"
|
||||
linked:
|
||||
---
|
||||
Объединяет преимущества: [Last Frequently Used](Last%20Frequently%20Used.md) и [Least Recently Used](Least%20Recently%20Used.md).
|
||||
|
||||
Принцип работы:
|
||||
- Сохраняет два списка: недавно используемые элементы и давно не используемые
|
||||
- Может динамически менять размер этих списков
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**:: [[Алгоритм вытеснения кэша]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-17]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
46
dev/algorithm/GZIP.md
Normal file
46
dev/algorithm/GZIP.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-14
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Разработка|00 Разработка]]"
|
||||
parents:
|
||||
- "[[../fundamental/Сжатие данных|Сжатие данных]]"
|
||||
linked:
|
||||
---
|
||||
GZIP (GNU ZIP) — это формат сжатия данных и программное обеспечение, разработанное для сжатия и распаковки файлов. GZIP был создан в 1992 году Жан-Лу Гейли и Марком Адлером как замена более ранних программ сжатия данных, таких как Compress. GZIP основан на алгоритме DEFLATE, который сочетает в себе методы LZ77 (Lempel-Ziv 1977) и кодирование Хаффмана для эффективного сжатия данных.
|
||||
|
||||
**Основные характеристики GZIP:**
|
||||
- **Эффективное сжатие**: GZIP обеспечивает высокую степень сжатия данных, что позволяет значительно уменьшить размер файлов, особенно текстовых.
|
||||
- **Скорость**: GZIP работает быстро и является эффективным как для сжатия, так и для распаковки данных.
|
||||
- **Поддержка различных форматов**: GZIP сжимает данные в формате .gz, но не сохраняет структуру файлов и директорий (для этого используются архиваторы вроде tar).
|
||||
- **Универсальность**: GZIP широко поддерживается в Unix-подобных системах (Linux, BSD), а также доступен на Windows и других платформах.
|
||||
- **Использование заголовков**: GZIP добавляет к сжатому файлу заголовок, который содержит метаданные, такие как имя оригинального файла, временная метка и контрольная сумма CRC32 для проверки целостности данных.
|
||||
|
||||
**Применения GZIP:**
|
||||
- **Сжатие файлов**: Используется для сжатия отдельных файлов, что экономит место на диске и уменьшает время передачи данных.
|
||||
- **Веб-технологии**: GZIP часто используется для сжатия веб-контента (HTML, CSS, JavaScript) перед отправкой с сервера на клиент, что ускоряет загрузку веб-страниц.
|
||||
- **Архивирование**: В Unix-подобных системах GZIP часто используется вместе с утилитой tar для создания архивов (tar.gz или .tgz), которые содержат несколько файлов и директорий.
|
||||
- **Протоколы передачи данных**: Протоколы, такие как HTTP и FTP, поддерживают сжатие GZIP для уменьшения объема передаваемых данных.
|
||||
|
||||
**Реализации:**
|
||||
- [[../../../../_inbox/Реализация GZIP в Java|Реализация GZIP в Java]]
|
||||
- [[../devops/nginx/GZIP сжатие в Nginx|GZIP сжатие в Nginx]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]]
|
||||
**Родитель**:: [[../fundamental/Сжатие данных|Сжатие данных]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-14]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Реализация GZIP в Java]]
|
||||
- [[GZIP сжатие в Nginx]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
26
dev/algorithm/Last Frequently Used.md
Normal file
26
dev/algorithm/Last Frequently Used.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
aliases:
|
||||
- LFU
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
- "[[Алгоритм вытеснения кэша]]"
|
||||
linked:
|
||||
- "[[Most Recently Used]]"
|
||||
---
|
||||
Наиболее редко используемые данные вытесняются.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**:: [[Алгоритм вытеснения кэша]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-17]]
|
||||
### Дополнительные материалы
|
||||
- [[Most Recently Used]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
45
dev/algorithm/Least Recently Used.md
Normal file
45
dev/algorithm/Least Recently Used.md
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
aliases:
|
||||
- LRU
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-05-24
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
- "[[Алгоритм вытеснения кэша]]"
|
||||
linked:
|
||||
- "[[Most Recently Used]]"
|
||||
- "[[Псевдо-LRU]]"
|
||||
---
|
||||
Least Recently Used (LRU) — это алгоритм управления кэш-памятью, который выбирает для удаления тот элемент, который давно не использовался. Этот алгоритм часто используется в системах, где ограничены ресурсы памяти, и необходимо эффективно управлять кэшированием данных.
|
||||
|
||||
**Принцип работы:**
|
||||
1. **Отслеживание использования**: Каждый элемент в кэше имеет метку времени или счетчик, который обновляется каждый раз, когда элемент используется.
|
||||
2. **Удаление устаревших элементов**: Когда необходимо освободить место в кэше для нового элемента, удаляется элемент с наименьшим значением метки времени или счетчика, то есть наименее недавно использованный элемент.
|
||||
|
||||
**Преимущества**:
|
||||
- Эффективное управление памятью.
|
||||
- Простота реализации и понятная логика работы.
|
||||
|
||||
**Недостатки**:
|
||||
- Высокие накладные расходы на обновление меток времени или счетчиков. Поэтому чаще всего используют [Псевдо-LRU](Псевдо-LRU.md).
|
||||
- Возможность неэффективной работы в некоторых специфических случаях, когда часто используемые элементы могут вытесняться из кэша.
|
||||
|
||||
**Примеры использования:**
|
||||
- [[../architecture/Кэширование|Кэширование]] страниц в веб-браузерах.
|
||||
- Управление оперативной памятью в [[../../../../knowledge/dev/pc/Операционная система|операционных системах]].
|
||||
- Кэширование данных в базах данных и других системах хранения.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**:: [[Алгоритм вытеснения кэша]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-05-24]]
|
||||
### Дополнительные материалы
|
||||
- [[Most Recently Used]]
|
||||
- [[Псевдо-LRU]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
34
dev/algorithm/Most Recently Used.md
Normal file
34
dev/algorithm/Most Recently Used.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
aliases:
|
||||
- MRU
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
- "[[Алгоритм вытеснения кэша]]"
|
||||
linked:
|
||||
- "[[Least Recently Used]]"
|
||||
---
|
||||
Наименее редко используемые данные вытесняются.
|
||||
|
||||
**Принцип работы:**
|
||||
|
||||
**Преимущества**:
|
||||
|
||||
**Недостатки**:
|
||||
|
||||
**Примеры использования:**
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**:: [[Алгоритм вытеснения кэша]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-17]]
|
||||
### Дополнительные материалы
|
||||
- [[Least Recently Used]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
41
dev/algorithm/Алгоритм вытеснения кэша.md
Normal file
41
dev/algorithm/Алгоритм вытеснения кэша.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
aliases:
|
||||
- алгоритмы замещения кэша
|
||||
- Алгоритмы вытеснения
|
||||
- алгоритмов замещения
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-11
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
- "[[../architecture/highload/Инвалидация кэша|Инвалидация кэша]]"
|
||||
linked:
|
||||
---
|
||||
Алгоритмы вытеснения кэша определяют, какие данные должны быть удалены из кэша, когда он заполняется.
|
||||
|
||||
- Алгоритм Белади. Несуществующий идеальный алгоритм. Храним только нужную информацию, не нужную не храним.
|
||||
- [Least Recently Used](Least%20Recently%20Used.md). Один из наиболее популярных. Отслеживает, какие данные использовались недавно, и удаляет те, которые не использовались дольше всего
|
||||
- [Псевдо-LRU](Псевдо-LRU.md)
|
||||
- [Most Recently Used](Most%20Recently%20Used.md)
|
||||
- [Last Frequently Used](Last%20Frequently%20Used.md)
|
||||
- [Adaptive Replacement Cache](Adaptive%20Replacement%20Cache.md)
|
||||
- **FIFO (First In, First Out)** работает по принципу "первым пришел — первым ушел", удаляя данные в том порядке, в котором они были загружены в кэш. Хотя этот алгоритм проще, он не всегда эффективен, так как не учитывает, что старые данные могут по-прежнему быть востребованными.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**:: [[../architecture/highload/Инвалидация кэша|Инвалидация кэша]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-11]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Adaptive Replacement Cache]]
|
||||
- [[Last Frequently Used]]
|
||||
- [[Least Recently Used]]
|
||||
- [[Most Recently Used]]
|
||||
- [[Псевдо-LRU]]
|
||||
<!-- SerializedQuery END -->
|
38
dev/algorithm/Бинарный поиск.md
Normal file
38
dev/algorithm/Бинарный поиск.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-04-07
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Один их самых простых алгоритмов – это поиск элемента в отсортированном массиве. Это самая базовая алгоритмическая задача, которую нередко спрашивают на собеседованиях.
|
||||
|
||||
С одной стороны, для подобных алгоритмов используют уже готовые функции стандартной библиотеки, с другой – подобные вопросы на собеседованиях позволяют узнать полезное о кандидате.
|
||||
|
||||
Первое что приходи на ум: перебор элементов в массиве до нужного, тогда если количество элементов равно n и нужный нам элемент будет последним, нам потребуется сделать n проверок элементов до нахождения нужного, про такой случай и говорят что сложность алгоритма равна O(n).
|
||||
|
||||
Рассмотрим другой подход - бинарный поиск – возьмем средний элемент отсортированного массива и сравним его c искомым. Если элемент меньше – продолжим поиск в левой части массива, если больше в правой, пока не останется нужный элемент. Таким образом нам понадобится число операций равное тому, сколько раз нам нужно поделить массив размером n пополам.
|
||||
|
||||
Например, для массива в 16 элементов мы сначала поделим его на два по 8, потом 8 на два по 4, потом 4 на два по 2 и на конец 2 пополам, те всего 4 операции в худшем случае. Такое число равно двоичному логарифму.
|
||||
|
||||
Реализации:
|
||||
- [Бинарный поиск на Java](../java/Бинарный%20поиск%20на%20Java.md)
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**:: [[2024-04-07]]
|
||||
**Создана**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Бинарный поиск на Java]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
31
dev/algorithm/Псевдо-LRU.md
Normal file
31
dev/algorithm/Псевдо-LRU.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-18
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Алгоритм|00 Алгоритм]]"
|
||||
parents:
|
||||
- "[[Алгоритм вытеснения кэша]]"
|
||||
linked:
|
||||
- "[[Least Recently Used]]"
|
||||
---
|
||||
В отличие от [LRU](Least%20Recently%20Used.md) уменьшает накладные расчеты на обновление меток времени и счетчиков.
|
||||
|
||||
**Принцип работы:**
|
||||
- У каждого ключа есть какой-то бит данных
|
||||
- В цикле бегут потоки и снимают бит этим ключам
|
||||
- Когда данные по ключу читаются бит помечается прочитанным
|
||||
- Если нам нужно вытеснить информацию из кэша, то мы идем по ключам в поиске ключей со снятым битиком.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Алгоритм|00 Алгоритм]]
|
||||
**Родитель**:: [[Алгоритм вытеснения кэша]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-18]]
|
||||
### Дополнительные материалы
|
||||
- [[Least Recently Used]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
57
dev/architecture/12-Factor App.md
Normal file
57
dev/architecture/12-Factor App.md
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
aliases:
|
||||
- двенадцатифакторное приложение
|
||||
tags:
|
||||
- maturity/🌱
|
||||
- content/experience
|
||||
date: 2024-12-08
|
||||
---
|
||||
**Двенадцатифакторное приложение (12-Factor App)** — это методология разработки приложений, предложенная инженерами Heroku. Она описывает набор из 12 принципов, которые помогают создавать программное обеспечение, подходящее для облачных сред.
|
||||
|
||||
Основные цели этой методологии:
|
||||
- Простое масштабирование.
|
||||
- Портативность между средами.
|
||||
- Упрощение разработки и развертывания.
|
||||
|
||||
Эти принципы применимы ко всем видам приложений, но особенно полезны для веб-приложений и микросервисов.
|
||||
|
||||
**Принципы двенадцатифакторного приложения**
|
||||
|
||||
**Единая кодовая база** должна управляться в системе контроля версий и использоваться во всех средах. Все ветки и деплойменты одного микросервиса привязаны к одному репозиторию. Не должно быть такого, чтобы на один стенд деплой происходил из одного репозитория, а на другой из другого.
|
||||
|
||||
> Думал, а как можно нарушить этот принцип. И вспомнил случай. После переименования сервиса в GitLab пришлось сделать для одного стенда форк репозитория, чтобы собраться со старым названием для фикса. Это было связано с тем, что все стенды зависели от названия репозитория, поэтому было невозможно переименовать сервис только для одного стенда.
|
||||
|
||||
**Зависимости**. Явное объявление и изоляция зависимостей. Используйте менеджеры зависимостей.
|
||||
|
||||
**Конфигурация**. Храните конфигурацию отдельно от кода. Используйте переменные окружения для настройки среды. Пример: URL базы данных, секреты или ключи API задаются через ENV, а не в коде.
|
||||
|
||||
**Внешние ресурсы**. Базы данных, очереди, файловые хранилища рассматриваются как прикрепляемые ресурсы. Пример: База данных PostgreSQL или очередь RabbitMQ могут быть заменены без изменения кода.
|
||||
|
||||
**Сборка, выпуск, выполнение**. Четкое разделение стадий: сборка приложения, создание релиза и его выполнение.
|
||||
|
||||
**Процессы**. Приложение должно быть построено из одного или нескольких независимых процессов. Каждый процесс приложения отвечает за свою задачу (например, обработка HTTP-запросов, фоновые задания).
|
||||
|
||||
**Stateless**. Приложение не должно хранить данные или состояние внутри процессов. Все состояния хранятся во внешних ресурсах. Пример: Сессии пользователей сохраняются в Redis, а не в оперативной памяти приложения. Если процесс падает или перезапускается, состояние не теряется, так как оно хранится в Redis, базе данных или другой внешней системе.
|
||||
|
||||
**Привязка портов**. Приложение экспортирует HTTP (или другой) сервис через привязанный порт.
|
||||
|
||||
**Параллелизм**. Процессы должны быть разделены на масштабируемые модули.
|
||||
|
||||
**Среда разработки = среда продакшена**. Минимизируйте различия между стендами разработки и продакшеном.
|
||||
|
||||
**Журналирование**. Приложение пишет события в поток вывода (stdout), а обработкой логов занимается внешняя система. Пример: Логи собираются через Elasticsearch или Datadog.
|
||||
|
||||
**Административные задачи**. Запускайте административные задачи, такие как миграции базы данных, вместе с запуском сервиса.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-08]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
29
dev/architecture/API Gateway.md
Normal file
29
dev/architecture/API Gateway.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103020227.png|600]]
|
||||
|
||||
**Шаг 1**: Клиент отправляет [[../network/HyperText Transfer Protocol|HTTP]]-запрос на API-шлюз.
|
||||
**Шаг 2**: API-шлюз анализирует и проверяет атрибуты запроса.
|
||||
**Шаг 3**: API-шлюз выполняет проверки по спискам разрешений и запретов (allow-list/deny-list).
|
||||
**Шаг 4**: API-шлюз взаимодействует с поставщиком идентификаций для аутентификации и авторизации.
|
||||
**Шаг 5**: К запросу применяются правила ограничения скорости. Если превышен лимит, запрос отклоняется.
|
||||
**Шаги 6 и 7**: После прохождения базовых проверок API-шлюз ищет нужный сервис для маршрутизации, сопоставляя путь запроса.
|
||||
**Шаг 8**: API-шлюз преобразует запрос в нужный протокол и отправляет его на [[бэкенд]] микросервисов.
|
||||
**Шаги 9-12**: API-шлюз обрабатывает ошибки и справляется с длительными сбоями (circuit break). Также он может использовать стек ELK (Elastic-Logstash-Kibana) для логирования и мониторинга. Иногда данные кэшируются в самом API-шлюзе.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
40
dev/architecture/Architecture Significant Requirement.md
Normal file
40
dev/architecture/Architecture Significant Requirement.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
- ASR
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-17
|
||||
---
|
||||
Architecture Significant Requirement (ASR), или архитектурно значимое требование, — это требование, которое существенно влияет на архитектурные решения системы. ASR определяет, какие аспекты архитектуры должны быть приоритетными для обеспечения нужных характеристик системы:
|
||||
- Производительность
|
||||
- Доступность
|
||||
- Поддерживаемость
|
||||
- Масштабируемость
|
||||
- Удобство использования
|
||||
- Совместимость
|
||||
- Тестируемость
|
||||
- Модифицируемость
|
||||
- Переносимость
|
||||
- Функциональность
|
||||
- Переиспользуемость
|
||||
- Диагностируемость
|
||||
- Надежность
|
||||
|
||||
**Основные характеристики ASR:**
|
||||
- **Влияние на архитектуру:** Эти требования требуют определённых архитектурных решений или ограничений, чтобы обеспечить нужное поведение системы. Например, требование к высокой доступности системы может повлиять на выбор распределённой архитектуры.
|
||||
- **Непосредственное влияние на атрибуты качества:** ASR нацелены на достижение или улучшение одного или нескольких атрибутов качества системы. Например, требования к времени отклика будут влиять на решения, касающиеся оптимизации производительности.
|
||||
- **Долгосрочный эффект:** ASR обычно имеют долговременные последствия, так как изменение архитектурных решений позднее в процессе разработки может быть сложным и дорогостоящим.
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-17]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
32
dev/architecture/Bottlneck.md
Normal file
32
dev/architecture/Bottlneck.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
- узкое место
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-01
|
||||
---
|
||||
Узкое место (bottleneck) — компонент системы, ограничивающий её производительность или пропускную способность. Даже один неэффективный элемент может стать причиной снижения эффективности всей [[../../../../_inbox/Информационная система|информационной системы]].
|
||||
|
||||
Боттлнеки могут скрываться в любом элементе системы. Вот некоторые возможные области:
|
||||
- [[highload/Балансировка нагрузки|Балансировщик нагрузки]]. Проблемы с распределением трафика.
|
||||
- [[Бэкенд|Приложение]]. Ограничения на уровне кода или инфраструктуры.
|
||||
- [[../../meta/zero/00 Реляционная база данных|База данных]]. Медленная обработка запросов, нехватка соединений.
|
||||
- Распределенный [[Кэширование|кэш]]. Недостаток ресурсов или медленный доступ.
|
||||
- [[Брокер сообщений]]. Ограничения на пропускную способность.
|
||||
- Пропускная способность диска. Узкие места в файловых системах.
|
||||
|
||||
**Пример в** [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]].
|
||||
Рассмотрим систему с несколькими микросервисами и сервисом аутентификации. Если общий объем запросов составляет 1000 rps, а сервис аутентификации может обработать только 100 rps, то он становится узким местом, замедляя работу всей системы.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-01]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
43
dev/architecture/Bounded Context.md
Normal file
43
dev/architecture/Bounded Context.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
aliases:
|
||||
- Ограниченный контекст
|
||||
- ограниченных контекстов
|
||||
- ограниченного контекста
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-24
|
||||
---
|
||||
Ограниченный контекст (Bounded Context) — это ==логическая граница, внутри которой используется своя уникальная модель предметной области.== Он применяется в разработке для структурирования сложных систем, особенно когда бизнес-логика состоит из множества разрозненных частей.
|
||||
|
||||
Основные характеристики:
|
||||
- **Локализация моделей:** Модель, используемая внутри одного контекста, не должна быть напрямую применима в других контекстах. Например, "Заказ клиента" в контексте управления складом может включать данные о весе и объеме, а в контексте бухгалтерии — только финансовую информацию.
|
||||
- **Изоляция логики и терминологии:**. Один и тот же термин может означать разные вещи в разных контекстах. Например, "Клиент" в маркетинговом контексте — это целевая аудитория, а в контексте продаж — это покупатель с историей заказов.
|
||||
- **Границы и ответственность:** Каждый контекст имеет свои четко определенные границы, и все, что относится к этому контексту (термины, сущности, события), остается внутри этих границ.
|
||||
- **Интеграция контекстов:** Разные контексты взаимодействуют через явно определенные способы, такие как события, API, шины сообщений. Это позволяет минимизировать зависимость между контекстами.
|
||||
|
||||
Представим систему интернет-магазина. Возможные ограниченные контексты:
|
||||
- **Каталог продуктов** — управление списком товаров и их характеристиками.
|
||||
- **Управление заказами** — отслеживание состояния заказов.
|
||||
- **Склад** — управление инвентарем и логистикой.
|
||||
- **Бухгалтерия** — расчеты, счета и налоги.
|
||||
|
||||
Каждый из этих контекстов оперирует своей моделью данных и логикой, при этом данные могут пересекаться. Например, "Товар" есть в каталоге и на складе, но в каждом из контекстов он будет описан по-разному.
|
||||
|
||||
|
||||
Польза
|
||||
- [[../efficiency/Снижение когнитивной нагрузки при разработке|Снижение когнитивной нагрузки]] за счет локализации сложных моделей.
|
||||
- Улучшение читаемости и тестируемости кода.
|
||||
- Уменьшение зависимости между различными частями системы.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**::
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-24]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Single Responsibility Principle]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
318
dev/architecture/Builder Pattern.md
Normal file
318
dev/architecture/Builder Pattern.md
Normal file
@ -0,0 +1,318 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-04
|
||||
zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Builder Pattern — это [[порождающий паттерн проектирования]], который используется для пошагового создания сложных объектов. Этот паттерн особенно полезен, когда объект может иметь множество конфигураций или параметров, которые делают его создание через конструкторы неудобным или даже невозможным.
|
||||
|
||||
Основные концепции
|
||||
- **Разделение построения и представления**. Билдер позволяет отделить логику создания объекта от его конечной структуры. Это делает код более чистым и поддерживаемым.
|
||||
- **Пошаговая сборка**. Позволяет добавлять параметры или части объекта последовательно, при этом сам процесс создания может контролироваться и меняться независимо от основной логики объекта.
|
||||
- **Иммутабельность**. Паттерн билдер часто применяется для создания неизменяемых объектов. После сборки объекта его нельзя изменить, что улучшает предсказуемость и безопасность.
|
||||
|
||||
## Пример применения
|
||||
Рассмотрим создание объекта `Car`, у которого много настроек, таких как тип двигателя, количество дверей, цвет и т.д.
|
||||
|
||||
Без использования паттерна «Билдер» мы можем столкнуться с такой проблемой: необходимо создавать различные конструкторы, что ухудшает читаемость и поддержку кода. Паттерн «Билдер» помогает избежать этого, при этом используя [[Fluent API|fluent API]] стиль — подход, при котором методы возвращают сам объект билдера, позволяя вызывать их цепочкой. Это делает код более выразительным и легким для чтения.
|
||||
|
||||
```java
|
||||
public class Car {
|
||||
private String engine;
|
||||
private int doors;
|
||||
private String color;
|
||||
|
||||
private Car(CarBuilder builder) {
|
||||
this.engine = builder.engine;
|
||||
this.doors = builder.doors;
|
||||
this.color = builder.color;
|
||||
}
|
||||
|
||||
public static class CarBuilder {
|
||||
private String engine;
|
||||
private int doors;
|
||||
private String color;
|
||||
|
||||
public CarBuilder setEngine(String engine) {
|
||||
this.engine = engine;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CarBuilder setDoors(int doors) {
|
||||
this.doors = doors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CarBuilder setColor(String color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Car build() {
|
||||
return new Car(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Использование паттерна:
|
||||
```java
|
||||
Car car = new Car.CarBuilder()
|
||||
.setEngine("V8")
|
||||
.setDoors(4)
|
||||
.setColor("Red")
|
||||
.build();
|
||||
|
||||
System.out.println(car);
|
||||
```
|
||||
|
||||
**Преимущества**
|
||||
1. **Чистый код**. Конфигурация объектов становится ясной и понятной, даже если у объекта множество параметров.
|
||||
2. **Гибкость в создании объектов**. Можно не указывать все параметры сразу, а добавлять их по мере необходимости, что делает процесс сборки более гибким.
|
||||
3. **Поддержка иммутабельности**. Объекты могут быть неизменяемыми после создания, так как параметры устанавливаются только в процессе сборки.
|
||||
4. **Минимизация перегрузок конструкторов**. Это позволяет избежать множества конструкторов для различных комбинаций параметров.
|
||||
|
||||
**Недостатки**
|
||||
- **Усложнение кода**. Добавление класса-билдера может увеличить объем кода, особенно если объект не настолько сложен, чтобы оправдать использование паттерна.
|
||||
- **Многословность**. Если объект требует только нескольких параметров, то использование билдера может казаться излишним и создавать ненужную многословность.
|
||||
|
||||
**Когда применять?**
|
||||
- Когда объект имеет множество конфигураций и параметров.
|
||||
- Когда нужен гибкий процесс создания объектов с возможностью пошагового добавления параметров.
|
||||
- Когда объект должен быть неизменяемым, и после сборки его состояние не должно меняться.
|
||||
|
||||
## Продвинутый билдер
|
||||
### Обязательные поля
|
||||
Одной из распространенных проблем является ==отсутствие явного указания на обязательные поля== при использовании билдера. Если объект имеет поля, которые обязательны для заполнения (например, идентификатор или имя), но их установка не контролируется билдером, это может привести к созданию некорректных или невалидных объектов.
|
||||
|
||||
**Решение**:
|
||||
- Обязательные поля можно передавать через конструктор билдера, чтобы их указание было обязательным. Остальные параметры можно указывать через цепочку методов.
|
||||
|
||||
Пример:
|
||||
```java
|
||||
public class Car {
|
||||
private final String engine; // Обязательное поле
|
||||
private final String model; // Обязательное поле
|
||||
private int doors; // Необязательное поле
|
||||
private String color; // Необязательное поле
|
||||
|
||||
// Приватный конструктор для сборки объекта через билдер
|
||||
private Car(CarBuilder builder) {
|
||||
this.engine = builder.engine;
|
||||
this.model = builder.model;
|
||||
this.doors = builder.doors;
|
||||
this.color = builder.color;
|
||||
}
|
||||
|
||||
// Статический метод для создания билдера с обязательными полями
|
||||
public static CarBuilder builder(String engine, String model) {
|
||||
return new CarBuilder(engine, model);
|
||||
}
|
||||
|
||||
public static class CarBuilder {
|
||||
private final String engine; // Обязательное поле
|
||||
private final String model; // Обязательное поле
|
||||
private int doors = 4; // Значение по умолчанию
|
||||
private String color = "Black"; // Значение по умолчанию
|
||||
|
||||
// Конструктор билдера с обязательными полями
|
||||
public CarBuilder(String engine, String model) {
|
||||
if (engine == null || engine.isEmpty()) {
|
||||
throw new IllegalArgumentException("Engine is required");
|
||||
}
|
||||
if (model == null || model.isEmpty()) {
|
||||
throw new IllegalArgumentException("Model is required");
|
||||
}
|
||||
this.engine = engine;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
// Методы для установки необязательных полей
|
||||
public CarBuilder setDoors(int doors) {
|
||||
this.doors = doors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CarBuilder setColor(String color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Метод для сборки объекта Car
|
||||
public Car build() {
|
||||
return new Car(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Теперь обязательные поля передаются при создании билдера:
|
||||
```java
|
||||
Car car = Car.builder("V8", "Sedan") // Передача обязательных полей через статический метод
|
||||
.setDoors(2) // Опциональные поля
|
||||
.setColor("Red")
|
||||
.build();
|
||||
```
|
||||
### Валидация создания объекта
|
||||
Ещё одна частая проблема заключается в том, что во время процесса построения ==не проверяются ограничения на совместимость полей.== Например, не всегда проверяется корректность значений или логика взаимодействия между параметрами, что может привести к созданию некорректного объекта.
|
||||
|
||||
**Решение**:
|
||||
Добавляйте в билдер логику валидации и проверки состояния перед созданием объекта. Это позволит убедиться, что все параметры совместимы и объект корректен.
|
||||
|
||||
Пример:
|
||||
```java
|
||||
public Car build() {
|
||||
if (doors < 2 || doors > 6) {
|
||||
throw new IllegalArgumentException("Invalid number of doors");
|
||||
}
|
||||
return new Car(this);
|
||||
}
|
||||
```
|
||||
### Многократный вызов методов
|
||||
Когда методы билдера вызываются несколько раз, каждый вызов может перезаписывать значение параметра, что может остаться незамеченным или вызвать непредсказуемое поведение.
|
||||
|
||||
Предположим, что у нас есть билдер для создания объекта `Car`, и метод для установки количества дверей (`setDoors`) был вызван дважды:
|
||||
```java
|
||||
Car car = new Car.CarBuilder("V8")
|
||||
.setDoors(4)
|
||||
.setDoors(2) // Этот вызов перезапишет предыдущее значение
|
||||
.setColor("Red")
|
||||
.build();
|
||||
```
|
||||
|
||||
В результате объект car будет создан с двумя дверями, хотя программист мог ожидать, что будет 4 двери (из-за первого вызова). Такая ситуация особенно распространена, когда объект конфигурируется динамически, или когда несколько разработчиков работают с билдером, не зная всех деталей.
|
||||
#### Возможные решения проблемы
|
||||
**Введение проверок на повторный вызов.** Чтобы избежать многократных вызовов одного и того же метода, можно добавить логику проверки, которая будет отслеживать, был ли метод уже вызван ранее. Если метод вызывается повторно, можно выбросить исключение или проигнорировать повторный вызов.
|
||||
|
||||
```java
|
||||
public static class CarBuilder {
|
||||
private String engine;
|
||||
private int doors;
|
||||
private String color;
|
||||
private boolean doorsSet = false; // Флаг, указывающий на то, что метод setDoors уже был вызван
|
||||
|
||||
public CarBuilder(String engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
public CarBuilder setDoors(int doors) {
|
||||
if (doorsSet) {
|
||||
throw new IllegalStateException("Doors can only be set once");
|
||||
}
|
||||
this.doors = doors;
|
||||
doorsSet = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CarBuilder setColor(String color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Car build() {
|
||||
return new Car(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Логирование перезаписи параметров.** Если необходимо разрешить многократные вызовы методов, но при этом важно отслеживать перезапись параметров, можно добавлять логирование, чтобы было видно, когда параметр перезаписывается новым значением.
|
||||
|
||||
```java
|
||||
public CarBuilder setDoors(int doors) {
|
||||
if (this.doors != 0) {
|
||||
System.out.println("Warning: Doors value is being overwritten from " + this.doors + " to " + doors);
|
||||
}
|
||||
this.doors = doors;
|
||||
return this;
|
||||
}
|
||||
```
|
||||
|
||||
**Использование** [[Fluent API#Step building|Fluent API Step building]]. Позволит конфигурировать объект в определенной последовательности.
|
||||
|
||||
```java
|
||||
public class Car {
|
||||
private final String engine; // Обязательное поле
|
||||
private final int doors; // Обязательное поле
|
||||
private final String color; // Обязательное поле
|
||||
|
||||
// Приватный конструктор для сборки через пошаговую сборку
|
||||
private Car(String engine, int doors, String color) {
|
||||
this.engine = engine;
|
||||
this.doors = doors;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
// Интерфейс для первого шага: выбор двигателя
|
||||
public interface EngineStep {
|
||||
DoorsStep setEngine(String engine);
|
||||
}
|
||||
|
||||
// Интерфейс для второго шага: выбор дверей
|
||||
public interface DoorsStep {
|
||||
ColorStep setDoors(int doors);
|
||||
}
|
||||
|
||||
// Интерфейс для третьего шага: выбор цвета
|
||||
public interface ColorStep {
|
||||
BuildStep setColor(String color);
|
||||
}
|
||||
|
||||
// Интерфейс для финального шага: завершение сборки
|
||||
public interface BuildStep {
|
||||
Car build();
|
||||
}
|
||||
|
||||
// Класс, который реализует пошаговую сборку
|
||||
public static class Builder implements EngineStep, DoorsStep, ColorStep, BuildStep {
|
||||
private String engine;
|
||||
private int doors;
|
||||
private String color;
|
||||
|
||||
@Override
|
||||
public DoorsStep setEngine(String engine) {
|
||||
this.engine = engine;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorStep setDoors(int doors) {
|
||||
this.doors = doors;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildStep setColor(String color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Car build() {
|
||||
return new Car(engine, doors, color);
|
||||
}
|
||||
}
|
||||
|
||||
// Метод для запуска пошаговой сборки
|
||||
public static EngineStep builder() {
|
||||
return new Builder();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]]
|
||||
**Родитель**:: [[Порождающий паттерн проектирования]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-10-04]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
28
dev/architecture/CAP теорема.md
Normal file
28
dev/architecture/CAP теорема.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-12
|
||||
---
|
||||
![[../../meta/files/images/Pasted image 20241103022605.png]]
|
||||
|
||||
CAP теорема — это принцип, описывающий фундаментальные ограничения, с которыми сталкиваются распределённые вычислительные системы в контексте обеспечения следующих трёх свойств:
|
||||
- **Согласованность (Consistency)**: Каждый раз, когда данные читаются, возвращается самое последнее записанное значение или ошибка. С другими словами, операции с данными выглядят так, будто выполняются в некоторой строгой последовательности, одна за другой
|
||||
- Доступность ([[../../../../_inbox/Availability|Availability]]): Каждый запрос на получение или запись данных получает ответ, независимо от состояния системы, даже если некоторые части системы вышли из строя.
|
||||
- **Устойчивость к разделению (Partition Tolerance)**: Система продолжает функционировать, даже если произошло "разделение" — потеря связи между узлами в распределённой сети. То есть система способна переносить произвольное число сообщений, которые задерживаются или теряются в сети.
|
||||
|
||||
==Согласно теореме CAP, в любой момент времени система может обеспечивать только два из этих трёх свойств.== Это означает, что при разработке системы приходится принимать компромисс между этими свойствами в зависимости от требований приложения и условий эксплуатации. Например, если для системы критически важна согласованность данных и её устойчивость к разделению, возможно придётся пожертвовать её доступностью в некоторых сценариях.
|
||||
## Свободные заметки
|
||||
- Google заявляет, что их продукт Google Spanner якобы нарушает CAP теорему.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-12]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
41
dev/architecture/Database per service.md
Normal file
41
dev/architecture/Database per service.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
aliases:
|
||||
- separate data store
|
||||
- своя база данных
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-24
|
||||
---
|
||||
В [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]] [[Паттерн проектирования|паттерн]] "Database per Service" означает, что у каждого сервиса есть своя собственная, независимая [[../../meta/zero/00 Реляционная база данных|база данных]]. Это позволяет полностью изолировать данные, что обеспечивает независимость и автономность каждого микросервиса. При таком подходе, на этапе выполнения, сервисы не блокируют друг друга, и ни одному из них не приходится ждать из-за конкуренции за доступ к общей базе данных.
|
||||
|
||||
Этот паттерн подразумевает, что каждый [[микросервис]] владеет своим хранилищем данных и несёт ответственность за его структуру и управление. ==Это не означает, что для каждого сервиса необходимо выделять отдельный сервер базы данных — вполне возможно использование одного физического сервера с несколькими логически изолированными базами данных== или базой с разными схемами для разных сервисов.
|
||||
|
||||
**Преимущества подхода:**
|
||||
1. **Изоляция данных**. Каждый сервис владеет своими данными, и другие сервисы не имеют прямого доступа к этим данным. Это повышает безопасность и уменьшает вероятность ошибок, вызванных некорректным использованием данных другими сервисами.
|
||||
2. **Независимость разработки и деплоя**. Каждый микросервис может развиваться, тестироваться и развёртываться независимо, так как изменение структуры данных в одном сервисе не затрагивает другие.
|
||||
3. **Устранение конкуренции за ресурсы**. Сервис не будет блокирован другим сервисом, который интенсивно использует общую базу данных. Это улучшает производительность и уменьшает задержки.
|
||||
4. **Масштабируемость**. Каждый сервис может масштабироваться независимо, в том числе и его база данных. Это позволяет учитывать конкретные требования к нагрузке каждого сервиса.
|
||||
|
||||
Проблемы
|
||||
- **Невозможность глобальных транзакций (ACID)**. В случае, когда бизнес-логика требует согласованности данных на уровне нескольких микросервисов, использование ACID-транзакций на уровне всего приложения становится невозможным. Для решения этой проблемы применяются паттерны, такие как [Saga](Реализация%20повествования%20(Saga).md), которые позволяют координировать распределённые транзакции через цепочку локальных операций.
|
||||
- [[Избыточность данных|Избыточность данных]] и консистентность. Поскольку каждый микросервис владеет своими данными, иногда возникает необходимость дублирования данных между сервисами для обеспечения эффективной работы. Это может привести к проблемам с поддержанием консистентности данных и усложняет управление изменениями.
|
||||
- **Усложнение запросов**. Если бизнес-логика требует данных из нескольких микросервисов, выполнение сложных запросов становится трудной задачей, поскольку прямое обращение к базе данных другого сервиса не разрешено. В таких случаях приходится использовать API или механизмы синхронизации данных, что усложняет архитектуру.
|
||||
|
||||
Лучшие практики
|
||||
- **Чёткие границы владения данными**. Определите чёткие границы владения данными для каждого сервиса, - [[Bounded Context|Ограниченный контекст]]. Это помогает избежать пересечений и зависимостей между сервисами, а также упрощает управление данными.
|
||||
- [[Событийно-ориентированная архитектура|Событийно-ориентированная архитектура]]. Для обеспечения согласованности данных между микросервисами можно использовать события. Например, при изменении данных в одном сервисе он отправляет событие, на которое подписаны другие сервисы, которым эти данные могут быть нужны.
|
||||
- **Реализация паттернов для согласованности**. Используйте паттерны, такие как [Saga](Реализация%20повествования%20(Saga).md), чтобы координировать действия между несколькими микросервисами и гарантировать согласованность данных без использования глобальных транзакций.
|
||||
- **API вместо прямого доступа к данным**. Доступ к данным одного микросервиса другими должен осуществляться только через публичные API. Это помогает соблюдать [[Инкапсуляция|инкапсуляцию]] и обеспечивает безопасное взаимодействие между сервисами.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-24]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Shared Database|Shared Database]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
70
dev/architecture/Dependency Injection.md
Normal file
70
dev/architecture/Dependency Injection.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
aliases:
|
||||
- DI
|
||||
- внедрение зависимостей
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2023-10-26
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
- "[[Inversion of Control]]"
|
||||
- "[[Паттерн проектирования]]"
|
||||
linked:
|
||||
---
|
||||
**Dependency Injection (DI)** — это паттерн проектирования, который используется для реализации принципа [[Inversion of Control]] (IoC). DI позволяет передавать зависимости объектам извне, вместо того чтобы объекты сами создавали их. Это ослабляет связь между компонентами системы, что делает код более гибким и удобным для поддержки.
|
||||
|
||||
В **Java** DI часто используется через фреймворки, такие как [[../../meta/zero/00 SpringBoot|Spring]] или [[../../meta/zero/00 Quarkus|Quarkus]], где зависимости внедряются автоматически. Основные способы внедрения зависимостей включают:
|
||||
- **Внедрение через конструктор**: зависимости передаются через параметры конструктора.
|
||||
- **Внедрение через сеттеры**: зависимости устанавливаются через методы.
|
||||
- **Внедрение через поля**: зависимости могут быть внедрены напрямую в поля класса с использованием аннотаций.
|
||||
|
||||
Пример внедрения через конструктор с использованием Spring:
|
||||
|
||||
```java
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@Component
|
||||
class Engine {
|
||||
public void start() {
|
||||
System.out.println("Engine started");
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
class Car {
|
||||
private final Engine engine;
|
||||
|
||||
@Autowired
|
||||
public Car(Engine engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
public void drive() {
|
||||
engine.start();
|
||||
System.out.println("Car is moving");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
В этом примере Spring автоматически создаёт и инжектирует объект Engine в Car, благодаря аннотации `@Autowired`. Это упрощает управление зависимостями и позволяет легче изменять их без изменения логики программы.
|
||||
|
||||
Главные преимущества DI:
|
||||
- **Лёгкость тестирования**: можно подменять зависимости, что упрощает создание модульных тестов.
|
||||
- **Масштабируемость**: система легче адаптируется к изменениям.
|
||||
- **Упрощение архитектуры**: бизнес-логика отделена от процесса создания зависимостей.
|
||||
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[Inversion of Control]], [[Паттерн проектирования]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2023-10-06]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
101
dev/architecture/Dependency Inversion Principle.md
Normal file
101
dev/architecture/Dependency Inversion Principle.md
Normal file
@ -0,0 +1,101 @@
|
||||
---
|
||||
aliases:
|
||||
- DIP
|
||||
- Принцип инверсии зависимостей
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
- "[[SOLID|SOLID]]"
|
||||
linked:
|
||||
---
|
||||
**Принцип инверсии зависимостей (Dependency Inversion Principle, DIP)** гласит: [[высокоуровневые модули]] не должны зависеть от низкоуровневых модулей. Оба должны зависеть от абстракций. Это означает, что вместо использования конкретных реализаций, классы должны работать с абстракциями — интерфейсами или абстрактными классами. DIP делает код более гибким, модульным и легко расширяемым.
|
||||
|
||||
**Как соблюдать DIP**
|
||||
1. **Работайте с абстракциями:** Замените зависимости на интерфейсы или абстрактные классы.
|
||||
2. **Инвертируйте зависимости:** Используйте внедрение зависимостей ([[Dependency Injection]]) через конструктор, сеттер или контейнеры.
|
||||
3. Минимизируйте жёсткую [[связанность]]: Высокоуровневые модули должны оставаться независимыми от деталей реализации низкоуровневых модулей.
|
||||
|
||||
**Преимущества соблюдения DIP**
|
||||
1. **Гибкость:** Замена низкоуровневых модулей (реализаций) не требует изменения высокоуровневых модулей.
|
||||
2. **Улучшенная тестируемость:** Высокоуровневые модули можно тестировать с помощью моков или заглушек, так как они зависят от абстракций.
|
||||
3. **Снижение связанности:** Высокоуровневый код становится независимым от деталей реализации.
|
||||
4. **Расширяемость:** Новые реализации интерфейсов можно добавлять без изменений в существующем коде.
|
||||
## Пример нарушения DIP
|
||||
Рассмотрим пример с выключателем, который управляет лампой:
|
||||
|
||||
```java
|
||||
public class Lamp {
|
||||
public void turnOn() {
|
||||
// Лампа включена
|
||||
}
|
||||
}
|
||||
|
||||
public class Switch {
|
||||
private Lamp lamp;
|
||||
|
||||
public Switch(Lamp lamp) {
|
||||
this.lamp = lamp;
|
||||
}
|
||||
|
||||
public void toggle() {
|
||||
lamp.turnOn(); // Нарушение DIP — жёсткая зависимость от класса Lamp
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
В данном случае класс `Switch` напрямую зависит от конкретной реализации класса `Lamp`. Если потребуется заменить лампу на другое устройство (например, вентилятор), придётся модифицировать код `Switch`.
|
||||
|
||||
Используем интерфейс для абстрагирования устройств:
|
||||
|
||||
```java
|
||||
public interface Switchable {
|
||||
void turnOn();
|
||||
}
|
||||
|
||||
public class Lamp implements Switchable {
|
||||
@Override
|
||||
public void turnOn() {
|
||||
// Лампа включена
|
||||
}
|
||||
}
|
||||
|
||||
public class Fan implements Switchable {
|
||||
@Override
|
||||
public void turnOn() {
|
||||
// Вентилятор включен
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Теперь `Switch` зависит от интерфейса `Switchable`, а не от конкретного класса:
|
||||
|
||||
```java
|
||||
public class Switch {
|
||||
private Switchable device;
|
||||
|
||||
public Switch(Switchable device) {
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public void toggle() {
|
||||
device.turnOn(); // Зависимость инверсирована — Switch работает с абстракцией
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Для изменения устройства достаточно передать новую реализацию интерфейса `Switchable` при создании объекта `Switch`, не модифицируя его код.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[SOLID]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
50
dev/architecture/Event Loop.md
Normal file
50
dev/architecture/Event Loop.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
aliases:
|
||||
- событийного цикла
|
||||
- событийный цикл
|
||||
- single-threaded execution loop
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2023-10-26
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
- "[[Реактивное программирование]]"
|
||||
linked:
|
||||
---
|
||||
**Event loop** (цикл событий) — это фундаментальная концепция в асинхронном программировании, которая позволяет системе обрабатывать большое количество задач без создания множества [[../fundamental/Поток процесса ОС|потоков]].
|
||||
|
||||
По сути, Event Loop - это реализация [шаблона Reactor](http://design-pattern.ru/patterns/reactor.html). Он используется в языках и фреймворках, которые должны обрабатывать большое количество операций [[../../../../_inbox/Ввод-вывод|ввода-вывода]] (I/O) эффективно, минимизируя затраты на создание и управление потоками. Цикл событий стал особенно популярным в таких технологиях, как JavaScript (Node.js), Python (asyncio), и современных реактивных фреймворках на Java (Vert.x, [[../../meta/zero/00 Quarkus|Quarkus]]).
|
||||
|
||||
Цикл событий представляет собой непрерывную петлю, которая ожидает появления событий, таких как запросы клиентов, завершение операций I/O, сигналы от системных ресурсов и другие задачи. Когда событие происходит, цикл событий вызывает соответствующий обработчик, который выполняется без блокировки основной петли ([[../../../../_inbox/Не блокирующийся ввод-вывод|неблокирующийся ввод-вывод]]).
|
||||
|
||||
![](../../meta/files/images/Pasted%20image%2020231026115508.png)
|
||||
|
||||
Основные шаги работы event loop:
|
||||
1. **Ожидание событий.** Цикл событий ожидает появления новых задач (например, клиентских запросов, ответов от базы данных, сообщений от других сервисов).
|
||||
2. **Помещение задачи в очередь.** Когда событие происходит (например, пришел запрос от клиента), оно добавляется в очередь задач, ожидающих обработки.
|
||||
3. **Выполнение задачи.** Цикл событий начинает обработку задачи, извлекая её из очереди и вызывая соответствующий обработчик.
|
||||
4. **Завершение задачи.** Когда задача завершена (например, отправлен ответ клиенту), цикл переходит к следующему событию в очереди.
|
||||
|
||||
**Преимущества**
|
||||
- **Эффективное использование ресурсов.** Event loop позволяет системе обрабатывать большое количество запросов без необходимости создания множества потоков. Это снижает накладные расходы на память и процессорное время.
|
||||
- **Масштабируемость.** Благодаря асинхронной модели, event loop может обрабатывать сотни тысяч запросов одновременно, что делает его идеальным решением для [[../../meta/zero/00 HighLoad|высоконагруженных систем]].
|
||||
- **Неблокирующее выполнение.** В отличие от традиционных моделей, где операции ввода-вывода блокируют поток ([[Блокирующий вызов]]), в модели event loop такие операции выполняются асинхронно, освобождая поток для выполнения других задач.
|
||||
- Минимум [[../fundamental/Переключение контекста|контекстных переключений]]. Цикл событий снижает количество переключений между потоками, что снижает накладные расходы на переключение контекста и увеличивает производительность.
|
||||
|
||||
**Недостатки**
|
||||
- **Ограниченная поддержка CPU-ориентированных задач.** Модель event loop идеально подходит для операций ввода-вывода, но для задач, требующих интенсивных вычислений, такая модель не так эффективна. В таком случае ==поток может быть занят длительное время, блокируя выполнение других задач.==
|
||||
- **Сложность управления.** Асинхронные операции требуют управления состояниями и корректной обработки событий, что усложняет разработку и отладку. ==Ошибки в одном обработчике могут затронуть другие запросы, обрабатываемые тем же циклом событий.==
|
||||
- **“Заблокированный” цикл.** Если цикл событий заблокирован долгой синхронной операцией, это может затормозить выполнение всех задач, так как весь поток будет занят одной задачей.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[Реактивное программирование|Реактивное программирование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
43
dev/architecture/Event Sourcing.md
Normal file
43
dev/architecture/Event Sourcing.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-02
|
||||
---
|
||||
Event Sourcing — это [[архитектурный паттерн]], при котором состояние системы не сохраняется напрямую, а восстанавливается путем воспроизведения последовательности событий. Каждое событие отражает изменение в системе и сохраняется в неизменяемом журнале событий (event log).
|
||||
|
||||
**Принципы:**
|
||||
- **Неизменяемость событий**. Каждое событие записывается единожды и не подлежит изменению.
|
||||
- **Воспроизведение событий**. Текущее состояние объекта вычисляется путем последовательного применения событий, начиная с исходного состояния.
|
||||
- **Хранилище событий**. Все события хранятся в базе данных, которая может быть оптимизирована для их последовательной записи.
|
||||
|
||||
**Преимущества:**
|
||||
- **Аудит и прозрачность**. Хранилище событий предоставляет полный лог изменений, что упрощает аудит и диагностику.
|
||||
- **Производительность и масштабирование**. Увеличение производительности за счет использования хранилища событий и построения проекций для чтения.
|
||||
- **Восстановление состояния**. Легкость восстановления системы после сбоя путем проигрывания всех событий.
|
||||
- **Возможности для анализа**. Хранилище событий может использоваться для ретроспективного анализа данных.
|
||||
|
||||
**Ограничения:**
|
||||
- **Усложнение системы**. Требуется дополнительная логика для обработки событий, создания проекций и управления хранилищем событий.
|
||||
- **Версионирование событий**. Необходимость в управлении версиями событий при изменении их структуры.
|
||||
- **Увеличение объема данных**. Хранение всех событий может привести к быстрому росту объема данных.
|
||||
- **Задержка восстановления состояния**. При большом числе событий восстановление состояния может занимать много времени.
|
||||
|
||||
**Применение:**
|
||||
1. **Финансовые системы**. Для учета транзакций и обеспечения полного логирования операций.
|
||||
2. **E-commerce**. Хранение всех изменений корзины пользователя или заказов.
|
||||
3. **IoT**. Сохранение событий от датчиков для анализа в реальном времени или ретроспективы.
|
||||
4. Паттерн [[../../../../knowledge/dev/архитектура/паттерн/CQRS|CQRS]]. Часто используется совместно с Event Sourcing для разделения операций чтения и записи.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[Архитектурный паттерн]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-02]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
27
dev/architecture/Fingerprint.md
Normal file
27
dev/architecture/Fingerprint.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-10
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]"
|
||||
parents:
|
||||
- "[[highload/Инвалидация кэша|Инвалидация кэша]]"
|
||||
linked: []
|
||||
---
|
||||
При реализации [[highload/Кэширование на стороне браузера|кэширования на стороне браузера]] важно иметь механизм [[highload/Инвалидация кэша|инвалидации кэша]]. Иначе пользователи могут продолжить видеть неактуальные JS-скрипты и CSS-стили, что приведет к проблемам.
|
||||
|
||||
Fingerprint — это метод, при котором при каждом изменении файла его название изменяется. Обычно это делается путем добавления префикса или суффикса, сгенерированного на основе хэша файла. Например, для файла стилей `style.css` можно вычислить его [[../cryptography/MD5|MD5]]-хэш и добавить его к имени файла. В итоге получится файл с именем `style.e626dd36e0085927f334adbe3eb38e7a.css`.
|
||||
|
||||
Каждый раз, когда файл изменяется, хэш пересчитывается, и файл получает новое имя. Это заставляет браузер скачать актуальную версию файла, игнорируя старую кэшированную копию.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[highload/Инвалидация кэша|Инвалидация кэша]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-10]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
356
dev/architecture/Fluent API.md
Normal file
356
dev/architecture/Fluent API.md
Normal file
@ -0,0 +1,356 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-04
|
||||
zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
**Fluent API** — это стиль проектирования API, в котором ==методы возвращают объект, к которому они принадлежат==, позволяя вызывать методы цепочкой (chaining).
|
||||
|
||||
**Основные концепции**
|
||||
- **Method Chaining**. Fluent API позволяет вызывать методы один за другим, что уменьшает количество промежуточных переменных и улучшает читаемость.
|
||||
- **Самоописывающийся код**. Использование цепочки методов делает код более понятным и логичным, приближая его к естественному языку.
|
||||
|
||||
**Где встречается?**
|
||||
- Фреймворки с реактивным подходом.
|
||||
- Java Stream
|
||||
- **Библиотеки для работы с базами данных**. Такие фреймворки, как JPA или Hibernate, используют Fluent API для создания запросов. Например, запросы могут выглядеть так
|
||||
|
||||
```java
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Car> query = builder.createQuery(Car.class);
|
||||
query.select(query.from(Car.class))
|
||||
.where(builder.equal(root.get("color"), "Red"));
|
||||
```
|
||||
|
||||
- **Настройка объектов**. Fluent API часто используется в [[../../../../garden/ru/dev/architecture/Builder Pattern|Builder Pattern]], где объект строится поэтапно через цепочку методов.
|
||||
- Конфигурация. Например Spring Security, Kafka Streams
|
||||
- **Фреймворки для тестирования**. Например, в JUnit или AssertJ можно строить цепочки утверждений:
|
||||
|
||||
Fluent API часто используется для построения специфических языков (DSL), которые имитируют человеческий язык и делают код максимально самоописательным.
|
||||
|
||||
Пример императивного кода
|
||||
```java
|
||||
Instant start = Instant.now();
|
||||
Duration timeout = Duration.ofSeconds(10);
|
||||
do {
|
||||
Thread.sleep(200);
|
||||
var entity = repo.get("id");
|
||||
if ("EXPECTED".equals(entity.status)) {
|
||||
return;
|
||||
}
|
||||
} while (Instant.now().isBefore(start.plus(timeout)));
|
||||
throw new AssertionError("Status was not updated to EXPECTED");
|
||||
```
|
||||
|
||||
И аналогичный в стиле Fluent API
|
||||
```java
|
||||
Awaitility.await("Entity status should be updated to EXPECTED")
|
||||
.atMost(Duration.ofSeconds(10))
|
||||
.pollDelay(Duration.ofMillis(200))
|
||||
.until(() -> "EXPECTED".equals(repo.get("id").status));
|
||||
```
|
||||
## Приемы и подходы
|
||||
### Method chaining
|
||||
**Method chaining** — это техника, при которой методы возвращают текущий объект (обычно через `this`), позволяя вызывать несколько методов последовательно в одной строке.
|
||||
|
||||
```java {7, 12}
|
||||
public class Car {
|
||||
private String engine;
|
||||
private int doors;
|
||||
|
||||
public Car setEngine(String engine) {
|
||||
this.engine = engine;
|
||||
return this; // Возвращаем текущий объект
|
||||
}
|
||||
|
||||
public Car setDoors(int doors) {
|
||||
this.doors = doors;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
```
|
||||
### Смена контекста
|
||||
#### С помощью method chaining
|
||||
Представим, что мы настраиваем серверное приложение с несколькими аспектами: базовая настройка, настройка безопасности, логирования и т.д. Здесь каждый вызов метода переключает нас на новый “контекст”, где мы продолжаем настраивать приложение, но в рамках другой области (например, с безопасности переключаемся на логирование).
|
||||
|
||||
```java
|
||||
public class ServerConfig {
|
||||
|
||||
public ServerConfig http() {
|
||||
System.out.println("HTTP basic configuration");
|
||||
return this; // Возвращаем тот же объект для продолжения цепочки
|
||||
}
|
||||
|
||||
public ServerConfig security() {
|
||||
System.out.println("Security configuration");
|
||||
return this; // Переключение на контекст безопасности
|
||||
}
|
||||
|
||||
public ServerConfig authorizeRequests() {
|
||||
System.out.println("Authorization configuration");
|
||||
return this; // Переключение на настройку авторизации запросов
|
||||
}
|
||||
|
||||
public ServerConfig requestMatchers(String pattern) {
|
||||
System.out.println("Configuring request matchers for: " + pattern);
|
||||
return this; // Продолжение работы в контексте авторизации
|
||||
}
|
||||
|
||||
public ServerConfig csrf() {
|
||||
System.out.println("CSRF protection disabled");
|
||||
return this; // Переключение на настройку защиты CSRF
|
||||
}
|
||||
|
||||
public ServerConfig exceptionHandling() {
|
||||
System.out.println("Exception handling configuration");
|
||||
return this; // Переключение на обработку исключений
|
||||
}
|
||||
|
||||
public Server build() {
|
||||
System.out.println("Server is configured and built");
|
||||
return new Server();
|
||||
}
|
||||
}
|
||||
|
||||
class Server {
|
||||
// Имитация запущенного сервера
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
Server server = new ServerConfig()
|
||||
.http() // Контекст базовой настройки HTTP
|
||||
.security() // Переключение на контекст безопасности
|
||||
.authorizeRequests() // Настройка авторизации запросов
|
||||
.requestMatchers("/") // Настройка доступа для главной страницы
|
||||
.requestMatchers("/api") // Настройка доступа к API
|
||||
.csrf() // Отключение CSRF
|
||||
.exceptionHandling() // Настройка обработки исключений
|
||||
.build(); // Завершаем конфигурацию и запускаем сервер
|
||||
```
|
||||
#### С помощью лямбда-выражений
|
||||
```java
|
||||
public class ServerConfig {
|
||||
|
||||
public ServerConfig http(Consumer<HttpConfig> httpConfig) {
|
||||
System.out.println("Entering HTTP configuration context");
|
||||
httpConfig.accept(new HttpConfig());
|
||||
return this; // Возвращаем тот же объект для дальнейшей конфигурации
|
||||
}
|
||||
|
||||
public ServerConfig security(Consumer<SecurityConfig> securityConfig) {
|
||||
System.out.println("Entering Security configuration context");
|
||||
securityConfig.accept(new SecurityConfig());
|
||||
return this; // Переключение на контекст безопасности
|
||||
}
|
||||
|
||||
public ServerConfig logging(Consumer<LoggingConfig> loggingConfig) {
|
||||
System.out.println("Entering Logging configuration context");
|
||||
loggingConfig.accept(new LoggingConfig());
|
||||
return this; // Переключение на контекст логирования
|
||||
}
|
||||
|
||||
public Server build() {
|
||||
System.out.println("Server is configured and built");
|
||||
return new Server(); // Финальный этап — запуск сервера
|
||||
}
|
||||
|
||||
// Вложенные классы конфигураций для разных контекстов
|
||||
public static class HttpConfig {
|
||||
public HttpConfig enableHttp2() {
|
||||
System.out.println("HTTP/2 enabled");
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpConfig port(int port) {
|
||||
System.out.println("Server will listen on port: " + port);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SecurityConfig {
|
||||
public SecurityConfig enableTLS() {
|
||||
System.out.println("TLS enabled");
|
||||
return this;
|
||||
}
|
||||
|
||||
public SecurityConfig authorizeRequests(Consumer<RequestAuthorization> authorizationConfig) {
|
||||
System.out.println("Authorizing requests...");
|
||||
authorizationConfig.accept(new RequestAuthorization());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoggingConfig {
|
||||
public LoggingConfig level(String level) {
|
||||
System.out.println("Logging level set to: " + level);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RequestAuthorization {
|
||||
public RequestAuthorization permitAll() {
|
||||
System.out.println("All requests are permitted");
|
||||
return this;
|
||||
}
|
||||
|
||||
public RequestAuthorization authenticated() {
|
||||
System.out.println("Authenticated requests only");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
Server server = new ServerConfig()
|
||||
.http(http -> http.enableHttp2().port(8080)) // Настройка HTTP с использованием лямбда-выражения
|
||||
.security(security -> security
|
||||
.enableTLS() // Настройка безопасности
|
||||
.authorizeRequests(auth -> auth.authenticated())) // Смена контекста внутри лямбды
|
||||
.logging(log -> log.level("INFO")) // Настройка логирования с помощью лямбда
|
||||
.build(); // Финальная сборка сервера
|
||||
```
|
||||
|
||||
### Step building
|
||||
Позволяет организовать процесс создания объектов или выполнения операций через строго упорядоченные шаги. Хотя этот подход часто используется в [[../../../../garden/ru/dev/architecture/Builder Pattern|Builder Pattern]], он применим и в других контекстах, например, при вызове API, конфигурации сложных процессов, построении запросов и даже в рабочих процессах (workflow).
|
||||
|
||||
**Основные концепции**
|
||||
- **Упорядоченные шаги**. Процесс выполнения операции или создания объекта разделен на несколько этапов (шагов), которые должны выполняться в определённой последовательности. Каждый шаг может представлять собой настройку, изменение состояния или выполнение отдельной операции.
|
||||
- **Контроль обязательных шагов**. Пошаговая сборка гарантирует, что определенные важные шаги не будут пропущены. Это особенно полезно для процессов, где важно соблюдение последовательности действий или конфигурации обязательных параметров.
|
||||
|
||||
**Примеры применения пошаговой сборки**
|
||||
|
||||
**Построение SQL-запросов**
|
||||
|
||||
```java
|
||||
public interface SelectStep {
|
||||
FromStep select(String... columns);
|
||||
}
|
||||
|
||||
public interface FromStep {
|
||||
WhereStep from(String table);
|
||||
}
|
||||
|
||||
public interface WhereStep {
|
||||
OrderByStep where(String condition);
|
||||
}
|
||||
|
||||
public interface OrderByStep {
|
||||
BuildStep orderBy(String column);
|
||||
}
|
||||
|
||||
public interface BuildStep {
|
||||
String build();
|
||||
}
|
||||
|
||||
public class SqlQueryBuilder implements SelectStep, FromStep, WhereStep, OrderByStep, BuildStep {
|
||||
private String query;
|
||||
|
||||
@Override
|
||||
public FromStep select(String... columns) {
|
||||
query = "SELECT " + String.join(", ", columns);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WhereStep from(String table) {
|
||||
query += " FROM " + table;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderByStep where(String condition) {
|
||||
query += " WHERE " + condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildStep orderBy(String column) {
|
||||
query += " ORDER BY " + column;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String build() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public static SelectStep start() {
|
||||
return new SqlQueryBuilder();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Самообобщение
|
||||
Когда мы используем наследование для создания подклассов, возникает проблема, что методы Fluent API могут возвращать не подкласс, а базовый класс, разрывая цепочку вызовов. **Самообобщение** решает эту проблему, позволяя методам возвращать правильный тип подкласса.
|
||||
|
||||
**Пример проблемы без самообобщения**. Допустим, у нас есть базовый класс с цепочкой методов, и мы хотим унаследовать этот класс.
|
||||
|
||||
```java
|
||||
class BaseBuilder {
|
||||
public BaseBuilder setName(String name) {
|
||||
System.out.println("Name set to: " + name);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class AdvancedBuilder extends BaseBuilder {
|
||||
public AdvancedBuilder setFeature(String feature) {
|
||||
System.out.println("Feature set to: " + feature);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
AdvancedBuilder builder = new AdvancedBuilder();
|
||||
builder.setName("MyObject")
|
||||
.setFeature("AdvancedFeature"); // Ошибка: возвращается BaseBuilder
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
В этом примере `setName()` возвращает тип `BaseBuilder`, поэтому попытка вызвать `setFeature()` на результат этого вызова приведет к ошибке. Метод `setFeature()` будет недоступен.
|
||||
|
||||
**Решение с использованием самообобщения (Self-type Generics)**. Мы можем решить эту проблему, используя самообобщение с помощью обобщений (generics). Это позволит методам возвращать **самый специфичный тип**.
|
||||
|
||||
```java
|
||||
class BaseBuilder<T extends BaseBuilder<T>> {
|
||||
public T setName(String name) {
|
||||
System.out.println("Name set to: " + name);
|
||||
return (T) this; // Возвращаем текущий объект с типом T
|
||||
}
|
||||
}
|
||||
|
||||
class AdvancedBuilder extends BaseBuilder<AdvancedBuilder> {
|
||||
public AdvancedBuilder setFeature(String feature) {
|
||||
System.out.println("Feature set to: " + feature);
|
||||
return this; // Возвращаем текущий объект с типом AdvancedBuilder
|
||||
}
|
||||
}
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
AdvancedBuilder builder = new AdvancedBuilder();
|
||||
builder.setName("MyObject")
|
||||
.setFeature("AdvancedFeature"); // Теперь работает правильно
|
||||
}
|
||||
}
|
||||
```
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../../garden/ru/meta/zero/00 Java разработка|00 Java разработка]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-10-04]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
39
dev/architecture/Infrastructure as Code.md
Normal file
39
dev/architecture/Infrastructure as Code.md
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
aliases:
|
||||
- IaC
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-21
|
||||
---
|
||||
Infrastructure as Code (IaC) — это практика управления, конфигурирования и автоматизации вычислительных ресурсов (серверов, сетей, баз данных и т.д.) с использованием программного кода. Она позволяет инфраструктуре быть определённой в виде описания, которое можно сохранить в системе контроля версий, автоматически применять и изменять.
|
||||
|
||||
Пример: создание сервера не вручную через облачный интерфейс, а с использованием скрипта, который можно запустить и повторить в любой момент.
|
||||
|
||||
**Принципы**
|
||||
- **Декларативность или императивность.** Инфраструктура описывается либо в виде желаемого состояния (декларативный подход), либо через последовательность команд (императивный подход).
|
||||
- **Контроль версий.** Код инфраструктуры хранится в системах контроля версий (например, Git), что позволяет отслеживать изменения и возвращаться к предыдущим состояниям.
|
||||
- [[Идемпотентность]]. Повторное выполнение кода приводит к одному и тому же результату, что важно для стабильности.
|
||||
|
||||
**Преимущества**
|
||||
- **Стандартизация.** Все ресурсы управляются одинаково, снижается риск ошибок.
|
||||
- **Ускорение разработки.** Быстрое развёртывание и настройка инфраструктуры.
|
||||
- [[Масштабирование информационной системы|Масштабируемость]]. Удобное управление инфраструктурой даже в крупных системах.
|
||||
- Упрощение [[highload/Disaster recovery|восстановления]]. Код инфраструктуры позволяет восстановить её после сбоев.
|
||||
|
||||
**Недостатки**
|
||||
- **Кривая обучения.** Требуется время на изучение инструментов и практик IaC.
|
||||
- **Сложность внедрения.** Для небольших команд или простых систем реализация IaC может быть излишней.
|
||||
- **Необходимость дисциплины.** Некорректное управление кодом может привести к нестабильности.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[Архитектурная концепция]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-21]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
93
dev/architecture/Interface Segregation Principle.md
Normal file
93
dev/architecture/Interface Segregation Principle.md
Normal file
@ -0,0 +1,93 @@
|
||||
---
|
||||
aliases:
|
||||
- ISP
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
---
|
||||
Принцип разделения интерфейсов (Interface Segregation Principle, ISP) гласит: ==лучше создать несколько специализированных интерфейсов, чем один универсальный,== который заставляет классы реализовывать методы, не относящиеся к их функциональности. Каждый интерфейс должен описывать только те действия, которые действительно нужны конкретному клиенту. Этот принцип помогает избежать ненужной связанности и упрощает поддержку кода.
|
||||
|
||||
**Для реализации ISP следует:**
|
||||
- Создавать узкоспециализированные интерфейсы, соответствующие конкретным задачам.
|
||||
- Избегать универсальных интерфейсов с множеством методов, которые могут быть неактуальны для некоторых реализаций.
|
||||
- Делить интерфейсы на логически связанные группы методов.
|
||||
|
||||
**Преимущества соблюдения ISP**
|
||||
1. **Снижение связанности:** Реализации зависят только от методов, которые они используют.
|
||||
2. **Повышенная гибкость:** Интерфейсы можно изменять или добавлять новые без влияния на классы, которым эти изменения не нужны.
|
||||
3. **Упрощение тестирования:** Тестировать реализацию узких интерфейсов проще, так как они охватывают только необходимый функционал.
|
||||
4. **Улучшенная читаемость:** Логически разделенные интерфейсы делают код более понятным и структурированным.
|
||||
## Пример нарушения ISP
|
||||
Рассмотрим интерфейс `Worker`, который описывает как работу, так и прием пищи:
|
||||
|
||||
```java
|
||||
public interface Worker {
|
||||
void work();
|
||||
void eat();
|
||||
}
|
||||
|
||||
public class RobotWorker implements Worker {
|
||||
@Override
|
||||
public void work() {
|
||||
// Робот работает
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eat() {
|
||||
// Робот не ест — нарушение ISP
|
||||
throw new UnsupportedOperationException("Robots do not eat");
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Класс `RobotWorker` вынужден реализовывать метод `eat`, который ему не нужен. Это нарушение ISP, так как интерфейс содержит лишние методы, не применимые ко всем клиентам.
|
||||
|
||||
Разделим интерфейс на два более специализированных:
|
||||
|
||||
```java
|
||||
public interface Worker {
|
||||
void work();
|
||||
}
|
||||
|
||||
public interface Eater {
|
||||
void eat();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Теперь каждый класс реализует только те интерфейсы, которые ему нужны:
|
||||
|
||||
```java
|
||||
public class HumanWorker implements Worker, Eater {
|
||||
@Override
|
||||
public void work() {
|
||||
// Человек работает
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eat() {
|
||||
// Человек ест
|
||||
}
|
||||
}
|
||||
|
||||
public class RobotWorker implements Worker {
|
||||
@Override
|
||||
public void work() {
|
||||
// Робот работает
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[SOLID]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
99
dev/architecture/Inversion of Control.md
Normal file
99
dev/architecture/Inversion of Control.md
Normal file
@ -0,0 +1,99 @@
|
||||
---
|
||||
aliases:
|
||||
- IoC
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2023-10-26
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
- "[[Архитектурная концепция]]"
|
||||
linked:
|
||||
---
|
||||
Inversion of Control (IoC) — это [[архитектурная концепция]], которая заключается в передаче управления зависимостями программы от самого кода к внешней системе. Обычно, если один объект зависит от другого, он сам создаёт или запрашивает его. В IoC этот процесс контролируется извне, что позволяет программам быть более гибкими и легко расширяемыми.
|
||||
|
||||
Простой пример: допустим, у вас есть класс, который зависит от другого класса для выполнения своей работы. В обычном подходе класс сам создаёт объект-зависимость.
|
||||
|
||||
```java
|
||||
class Engine {
|
||||
public void start() {
|
||||
System.out.println("Engine started");
|
||||
}
|
||||
}
|
||||
|
||||
class Car {
|
||||
private Engine engine;
|
||||
|
||||
public Car() {
|
||||
// Класс Car сам создает зависимость
|
||||
this.engine = new Engine();
|
||||
}
|
||||
|
||||
public void drive() {
|
||||
engine.start();
|
||||
System.out.println("Car is moving");
|
||||
}
|
||||
}
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Car car = new Car();
|
||||
car.drive();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
С использованием **IoC**, создание объекта Engine передаётся внешнему компоненту. Теперь Car не отвечает за создание своей зависимости:
|
||||
|
||||
```java
|
||||
class Engine {
|
||||
public void start() {
|
||||
System.out.println("Engine started");
|
||||
}
|
||||
}
|
||||
|
||||
class Car {
|
||||
private Engine engine;
|
||||
|
||||
// Зависимость передается через конструктор (IoC)
|
||||
public Car(Engine engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
public void drive() {
|
||||
engine.start();
|
||||
System.out.println("Car is moving");
|
||||
}
|
||||
}
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// Создание зависимостей осуществляется снаружи
|
||||
Engine engine = new Engine();
|
||||
Car car = new Car(engine);
|
||||
car.drive();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
IoC помогает реализовать принципы [[../../../../garden/ru/dev/architecture/SOLID|SOLID]], особенно [[../../../../garden/ru/dev/architecture/Dependency Inversion Principle|Принцип инверсии зависимостей]] (Dependency Inversion Principle, DIP), согласно которому высокоуровневые модули не должны зависеть от низкоуровневых модулей напрямую. Оба типа модулей должны зависеть от абстракций. В контексте IoC это означает, что классы не должны напрямую создавать свои зависимости, а получать их через интерфейсы или внешние механизмы. Такой подход упрощает замену реализаций, тестирование и расширение приложения.
|
||||
|
||||
**Преимущества IoC**
|
||||
- **Ослабление связности кода**. Поскольку классы не создают свои зависимости напрямую, их связь с конкретными реализациями уменьшается. Это облегчает изменение или замену зависимостей без изменения самого класса.
|
||||
- **Упрощение тестирования**. IoC позволяет легко заменять реальные зависимости на тестовые (например, mock-объекты), что упрощает процесс модульного тестирования. Вы можете изолировать классы и тестировать их независимо от реальных зависимостей.
|
||||
- **Лучшая расширяемость**. Система, построенная на принципах IoC, легче адаптируется к изменениям и новым требованиям. Новые зависимости могут быть добавлены или изменены без значительного изменения существующего кода.
|
||||
- **Разделение ответственности**. С IoC создаётся чёткое разделение между бизнес-логикой и управлением зависимостями. Это помогает сосредоточить внимание на основной функциональности класса, не отвлекаясь на вопросы создания объектов.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[Архитектурная концепция]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2023-10-26]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Dependency Injection]]
|
||||
<!-- SerializedQuery END -->
|
41
dev/architecture/Latency.md
Normal file
41
dev/architecture/Latency.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
aliases:
|
||||
- задержка
|
||||
- время отклика
|
||||
- задержки
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-12
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Latency - это время, необходимое для выполнения какой-либо операции или передачи данных от одной точки к другой. В более широком смысле, это период времени между началом действия и моментом, когда его результаты становятся заметны.
|
||||
|
||||
**Что влияет?**
|
||||
- **Расстояние**: Физическое расстояние между отправителем и получателем данных напрямую влияет на время передачи сигнала, особенно при больших расстояниях.
|
||||
- **Скорость передачи данных среды**: Скорость, с которой данные передаются через физическую среду (например, медные кабели, оптоволокно, беспроводные каналы), также влияет на задержку.
|
||||
- **Пропускная способность сети**: Высокая загруженность сети и ограниченная пропускная способность могут приводить к задержкам из-за ожидания доступа к сетевым ресурсам.
|
||||
- **Обработка данных**: Время, необходимое для обработки данных устройствами, такими как маршрутизаторы, коммутаторы и серверы, также вносит свой вклад в общую задержку.
|
||||
- **Количество прыжков (хопов) в сети**: Количество устройств (например, маршрутизаторов и коммутаторов), через которые данные должны пройти от источника к пункту назначения, увеличивает общее время задержки.
|
||||
- **Эффективность используемых протоколов**. Например, дополнительные шаги рукопожатия создают задержку
|
||||
|
||||
**Что поможет уменьшить значение:**
|
||||
- **Оптимизация производительности сервера**: Улучшение аппаратных характеристик сервера, таких как процессор, оперативная память и системы хранения, может сократить время обработки запросов.
|
||||
- **Использование кэширования**: [[Кэширование]] часто запрашиваемых данных на сервере или ближе к клиенту может существенно сократить время доступа к этим данным, поскольку избавляет от необходимости каждый раз обращаться к основному источнику данных.
|
||||
- **Оптимизация базы данных**: Индексация, оптимизация запросов и структур данных, а также выбор подходящего типа базы данных могут снизить время доступа к данным
|
||||
- **Минимизация расстояния**: Размещение серверов ближе к конечным пользователям или использование сети доставки контента ([CDN](highload/Content%20Delivery%20Network.md)) может снизить физическую задержку, связанную с расстоянием, которое должны преодолеть данные.
|
||||
- **Сокращение объема передаваемых данных**: Минимизация размера данных, передаваемых между клиентом и сервером (например, [[../fundamental/Сжатие данных|сжатие данных]] и изображений), может уменьшить время их передачи.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-12]]
|
||||
### Дополнительные материалы
|
||||
- [[Throughput]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
81
dev/architecture/Liskov Substitution Principle.md
Normal file
81
dev/architecture/Liskov Substitution Principle.md
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
aliases:
|
||||
- LSP
|
||||
- Принцип подстановки Барбары Лисков
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
---
|
||||
Принцип подстановки Лисков (Liskov Substitution Principle, LSP) утверждает, что ==объекты подклассов должны быть взаимозаменяемы с объектами базового класса без изменения поведения программы==. Это означает, что ==подклассы не должны нарушать контракт базового класса или изменять его логику==. LSP является третьим принципом в набор[[SOLID|е SOL]]ID и играет ключевую роль в создании устойчивой и понятной иерархии классов.
|
||||
|
||||
**Чтобы соответствовать LSP:**
|
||||
- Подклассы должны расширять функциональность базового класса, не изменяя его поведение.
|
||||
- [[Контракт взаимодействия|Контракты]], задаваемые базовыми классами, должны строго соблюдаться.
|
||||
- Следует избегать переопределения методов, если это изменяет их ожидаемое поведение.
|
||||
|
||||
**Преимущества соблюдения LSP:**
|
||||
1. **Предсказуемость:** Код, использующий базовый класс, будет работать одинаково независимо от того, какие подклассы используются.
|
||||
2. **Упрощение тестирования:** Система становится менее подверженной ошибкам, так как базовый контракт всегда соблюдается.
|
||||
3. **Гибкость и масштабируемость:** Добавление новых подклассов не требует модификации существующего кода, если соблюден принцип LSP.
|
||||
4. **Улучшенная читаемость:** Четкое разделение обязанностей между базовыми и дочерними классами упрощает понимание системы.
|
||||
## Пример нарушения LSP
|
||||
Рассмотрим иерархию классов для птиц:
|
||||
|
||||
```java
|
||||
public class Bird {
|
||||
public void fly() {
|
||||
// Логика полета
|
||||
System.out.println("I can fly!");
|
||||
}
|
||||
}
|
||||
|
||||
public class Penguin extends Bird {
|
||||
@Override
|
||||
public void fly() {
|
||||
// Пингвин не может летать — нарушение LSP
|
||||
throw new UnsupportedOperationException("Penguins cannot fly");
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
В данном случае класс `Penguin` нарушает контракт базового класса `Bird`. Код, который ожидает, что любой объект типа `Bird` может летать, перестанет работать корректно при использовании `Penguin`. Это ведет к непредсказуемому поведению программы и увеличивает сложность сопровождения.
|
||||
|
||||
Для устранения нарушения следует пересмотреть иерархию классов, чтобы явно выделить летающих и нелетающих птиц:
|
||||
|
||||
```java
|
||||
public abstract class Bird {
|
||||
// Общие свойства и методы для всех птиц
|
||||
}
|
||||
|
||||
public interface Flyable {
|
||||
void fly();
|
||||
}
|
||||
|
||||
public class FlyingBird extends Bird implements Flyable {
|
||||
@Override
|
||||
public void fly() {
|
||||
// Реализация полета
|
||||
System.out.println("I can fly!");
|
||||
}
|
||||
}
|
||||
|
||||
public class Penguin extends Bird {
|
||||
// Пингвин остается нелетающей птицей
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Теперь поведение каждой птицы становится очевидным, и программа корректно работает с летающими и нелетающими птицами, не нарушая LSP.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[SOLID]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
29
dev/architecture/Long polling.md
Normal file
29
dev/architecture/Long polling.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
**Long polling** — это метод опроса сервера, при котором клиент отправляет запрос и остается подключенным к серверу, ожидая ответа до тех пор, пока не появятся новые данные. Если серверу нечего отправить, он удерживает запрос открытым, пока не произойдет обновление, или пока не истечет тайм-аут. После получения ответа клиент сразу отправляет новый запрос для продолжения ожидания.
|
||||
|
||||
**Преимущества:**
|
||||
- Меньше нагрузка на сервер по сравнению с [[Short polling]], так как запросы отправляются реже, только когда есть новые данные.
|
||||
- Обеспечивает более оперативное получение обновлений, чем при обычном коротком опросе.
|
||||
|
||||
**Недостатки:**
|
||||
- Задержка может быть непредсказуемой, особенно если данные появляются нерегулярно.
|
||||
- Удержание открытого соединения может быть менее эффективным для серверов с ограниченными ресурсами, особенно при большом количестве клиентов.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Short polling]]
|
||||
- [[Webhook]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
106
dev/architecture/Open Closed Principle.md
Normal file
106
dev/architecture/Open Closed Principle.md
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
aliases:
|
||||
- Open/Closed Principle
|
||||
- OCP
|
||||
- Принцип открытости/закрытости
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
---
|
||||
Классы и модули должны быть **открыты для расширения, но закрыты для модификации**. Это означает, что функциональность можно добавлять без изменения существующего кода. Такой подход позволяет минимизировать риск возникновения ошибок в уже работающей системе при внедрении новых функций. **Принцип открытости/закрытости (Open-Closed Principle, OCP)** является вторым из пяти [[SOLID]]-принципов и способствует созданию гибкой и поддерживаемой архитектуры.
|
||||
|
||||
Обычно для реализации принципа используются:
|
||||
- **Интерфейсы** или **абстрактные классы**, которые задают общую структуру поведения.
|
||||
- [[Полиморфизм]], позволяющий создавать новые реализации без изменения базового кода.
|
||||
|
||||
Следование OCP снижает [[связанность]] модулей, делает код проще в тестировании и облегчает внедрение новых функций.
|
||||
|
||||
**Преимущества соблюдения OCP:**
|
||||
1. **Гибкость кода:** Добавление нового функционала не требует изменений существующего кода, что снижает риск ошибок.
|
||||
2. **Улучшенная тестируемость:** Изолированные реализации проще тестировать независимо друг от друга.
|
||||
3. **Снижение связанности:** Код становится более модульным, и изменения в одной части системы не затрагивают другие.
|
||||
4. **Поддерживаемость:** Разработчики могут легко добавлять новые возможности без угрозы сломать существующий функционал.
|
||||
|
||||
## Пример нарушения OCP
|
||||
Рассмотрим класс, который обрабатывает оплату, поддерживая только один способ оплаты через кредитную карту:
|
||||
|
||||
```java
|
||||
public class PaymentProcessor {
|
||||
public void processPayment(String type, double amount) {
|
||||
if (type.equals("credit_card")) {
|
||||
// Логика оплаты через кредитную карту
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Если требуется добавить поддержку нового способа оплаты, например, PayPal, придется модифицировать метод `processPayment`:
|
||||
|
||||
```java
|
||||
public class PaymentProcessor {
|
||||
public void processPayment(String type, double amount) {
|
||||
if (type.equals("credit_card")) {
|
||||
// Логика оплаты через кредитную карту
|
||||
} else if (type.equals("paypal")) {
|
||||
// Логика оплаты через PayPal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Такой подход нарушает OCP, так как для добавления нового функционала приходится изменять уже существующий код. Это увеличивает риск ошибок и затрудняет сопровождение.
|
||||
|
||||
Используем интерфейсы для реализации разных способов оплаты:
|
||||
|
||||
```java
|
||||
public interface PaymentMethod {
|
||||
void pay(double amount);
|
||||
}
|
||||
|
||||
public class CreditCardPayment implements PaymentMethod {
|
||||
@Override
|
||||
public void pay(double amount) {
|
||||
// Оплата через кредитную карту
|
||||
}
|
||||
}
|
||||
|
||||
public class PayPalPayment implements PaymentMethod {
|
||||
@Override
|
||||
public void pay(double amount) {
|
||||
// Оплата через PayPal
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Теперь процессор оплаты будет работать с интерфейсом `PaymentMethod`, не завися от конкретных реализаций:
|
||||
|
||||
```java
|
||||
public class PaymentProcessor {
|
||||
private PaymentMethod paymentMethod;
|
||||
|
||||
public PaymentProcessor(PaymentMethod paymentMethod) {
|
||||
this.paymentMethod = paymentMethod;
|
||||
}
|
||||
|
||||
public void processPayment(double amount) {
|
||||
paymentMethod.pay(amount);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Для добавления нового способа оплаты достаточно создать новую реализацию `PaymentMethod`, не изменяя код процессора.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[SOLID|SOLID]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
27
dev/architecture/Remote Procedure Call.md
Normal file
27
dev/architecture/Remote Procedure Call.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
aliases:
|
||||
- RPC
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
RPC (удалённый вызов процедур) — это **общая концепция и протокол**, позволяющая программе вызывать функции или методы, которые выполняются на удалённом сервере, так, как будто они выполняются локально. В RPC клиент запрашивает сервер, чтобы тот выполнил определённую функцию и вернул результат. Концепция RPC используется для создания распределённых систем, и её можно реализовать разными способами и технологиями.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103005803.png]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[gRPC]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
32
dev/architecture/Representation State Transfer.md
Normal file
32
dev/architecture/Representation State Transfer.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
- REST
|
||||
- REST API
|
||||
- RESTful
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
Representation State Transfer (REST) - способ взаимодействия компонентов распределенного приложения в сети.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103004607.png]]
|
||||
|
||||
- Использует стандартные HTTP-методы, такие как GET, POST, PUT, DELETE, для операций CRUD.
|
||||
- Хорошо работает, когда вам нужны простые, единообразные интерфейсы между отдельными сервисами / приложениями.
|
||||
- Стратегии кэширования просты в реализации.
|
||||
- Недостатком является то, что для сбора связанных данных из отдельных конечных точек может потребоваться несколько обходов.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103020635.png]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[../architecture/Протоколы коммуникаций|Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
30
dev/architecture/Rеverse proxy.md
Normal file
30
dev/architecture/Rеverse proxy.md
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-04-13
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]"
|
||||
parents:
|
||||
- "[[../garden/ru/dev/architecture/Фронтенд|Фронтенд]]"
|
||||
linked:
|
||||
---
|
||||
Rеverse proxy позволяет снять часть задач с [[Бэкенд|бэкенда]].
|
||||
|
||||
Rеverse proxy решает следующие проблемы:
|
||||
- **Организация https шифрования.** Клиенты подключаются к Reverse proxy по https, а прокси подключается к бэкенду по http.
|
||||
- Буферизация запросов и ответов.
|
||||
- Валидация http
|
||||
- Борьба с медленными клиентами. Клиенты с плохим интернет соединением могут долго удерживать канал. Reverse proxy с бэкендом быстро обмениваются данными, Reverse Proxy буферизирует ответ с бэкенда и может довольно долго удерживать соединение с клиентом скармливая ему ответ.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[Фронтенд]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
37
dev/architecture/SOLID.md
Normal file
37
dev/architecture/SOLID.md
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
aliases:
|
||||
- S.O.L.I.D.
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
---
|
||||
**SOLID** — это набор из пяти принципов объектно-ориентированного проектирования, предложенных Робертом Мартином (Robert C. Martin), которые помогают создавать более понятные, гибкие и поддерживаемые системы. Эти принципы направлены на улучшение структуры кода и снижение его сложности, что упрощает расширение и поддержку проекта.
|
||||
|
||||
- [[Single Responsibility Principle]]
|
||||
- [[Open Closed Principle|Open/Closed Principle]]
|
||||
- [[Liskov Substitution Principle]]
|
||||
- [[Interface Segregation Principle]]
|
||||
- [[Dependency Inversion Principle]]
|
||||
|
||||
> [!WARNING] Недостижимый идеал
|
||||
> Важно не применять принципы слепо, а учитывать контекст проекта и потребности системы. SOLID это идеал, к которому стоит стремиться, но который не достижим в реальной жизни.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Dependency Inversion Principle]]
|
||||
- [[Interface Segregation Principle]]
|
||||
- [[Liskov Substitution Principle]]
|
||||
- [[Open Closed Principle]]
|
||||
- [[Single Responsibility Principle]]
|
||||
<!-- SerializedQuery END -->
|
53
dev/architecture/Serverless.md
Normal file
53
dev/architecture/Serverless.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-08
|
||||
---
|
||||
**Serverless-архитектура** — это модель разработки приложений, при которой серверы все еще существуют, но управление ими полностью скрыто от разработчиков. Вместо этого, разработчики пишут небольшие, автономные функции, которые исполняются в облачной среде. Инфраструктурой управляет провайдер (например, AWS, Azure, Google Cloud).
|
||||
|
||||
Несмотря на название, серверы в Serverless есть, но разработчики:
|
||||
- Не управляют серверами напрямую.
|
||||
- Не занимаются их настройкой, мониторингом или масштабированием.
|
||||
- Платят только за фактическое время выполнения кода (pay-as-you-go).
|
||||
|
||||
**Основные принципы**
|
||||
- **Вызов на основе событий**. Код (функция) запускается в ответ на событие: HTTP-запрос, запись в базу данных, загрузка файла и т. д. Пример: загрузка изображения в облако запускает функцию для изменения его размера.
|
||||
- **Автоматическое масштабирование**. Серверная инфраструктура автоматически увеличивает или уменьшает количество ресурсов в зависимости от нагрузки. Пример: при росте числа запросов добавляются новые инстансы функции.
|
||||
- **Оплата за использование**. Вы платите только за фактическое время выполнения кода, а не за простаивающие серверы. Пример: если функция исполняется 200 мс, вы платите только за эти миллисекунды.
|
||||
- **Фокус на коде**. Разработчики сосредотачиваются на написании бизнес-логики, а не на настройке инфраструктуры.
|
||||
|
||||
**Преимущества Serverless**
|
||||
- **Снижение затрат**. Отсутствие расходов на простаивающие ресурсы. Вы платите только за выполнение кода.
|
||||
- **Автоматическое масштабирование**. Приложение автоматически адаптируется к изменяющимся нагрузкам.
|
||||
- **Быстрота разработки**. Упрощённое управление инфраструктурой позволяет сосредоточиться на бизнес-логике.
|
||||
- **Упрощённое развертывание**. Разработчики могут быстро выкатывать изменения, так как управление серверами осуществляется провайдером.
|
||||
|
||||
**Недостатки**
|
||||
- **Задержки холодного старта**. При запуске функции, которая долгое время не использовалась, может возникнуть задержка из-за необходимости инициализации контейнера.
|
||||
- **Ограниченная гибкость**. Провайдеры накладывают ограничения на использование определённых языков, библиотек и объёма ресурсов.
|
||||
- **Трудности отладки**. Локальное тестирование может быть сложным из-за особенностей облачных платформ.
|
||||
- **Зависимость от провайдера**. Использование специфичных для платформы инструментов может усложнить переносимость приложения.
|
||||
- **Высокая стоимость при больших нагрузках**. Для очень нагруженных систем Serverless может оказаться дороже традиционной модели.
|
||||
|
||||
Serverless подходит, если:
|
||||
- Вы разрабатываете приложения с переменной нагрузкой.
|
||||
- Вам нужна быстрая обработка событий (ETL, IoT, уведомления).
|
||||
- Вы хотите минимизировать управление инфраструктурой.
|
||||
|
||||
Serverless может быть не лучшим выбором, если:
|
||||
- Требуется минимальная задержка (например, в высоконагруженных системах реального времени).
|
||||
- Вы работаете с задачами, требующими долгого выполнения или сложных вычислений.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[Архитектурный паттерн]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-08]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
36
dev/architecture/Shared Database.md
Normal file
36
dev/architecture/Shared Database.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
aliases:
|
||||
- общей базы данных
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-24
|
||||
---
|
||||
Подход "Shared Database" предполагает, что все микросервисы используют одну общую базу данных для хранения данных. Сервисы взаимодействуют напрямую с таблицами, которые принадлежат другим сервисам, что создает зависимости на уровне данных и разрушает [[Инкапсуляция|инкапсуляцию]] между микросервисами.
|
||||
|
||||
Наличие одной базы данных для всех сервисов увеличивает [[Связность|связность]] системы и создаёт [[Bottlneck|узкое место]].
|
||||
|
||||
В [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]] подход, при котором все сервисы общаются с одной общей базой данных, считается скорее анти-паттерном. Несмотря на то, что в некоторых случаях это может показаться более простым решением, такой подход ведет к серьёзным ограничениям и проблемам, особенно в масштабируемых системах. Использование общей базы данных приводит к проблемам с разделением ответственности и нарушает принципы слабой [[Связанность|связанности]] и высокой [[Связность|связности]], которые являются основными в микросервисной архитектуре.
|
||||
|
||||
**Проблемы подхода Shared Database**
|
||||
- Сильная [[связанность]] между сервисами. Общая база данных приводит к явным и неявным зависимостям между сервисами. Это может проявляться через использование триггеров или процедур, которые затрагивают данные разных сервисов. Например, один сервис может использовать процедуру, изменяющую данные, которые принадлежат другому сервису. Такие зависимости делают каждый сервис уязвимым к изменениям в других сервисах.
|
||||
- **Отсутствие независимости**. Микросервисы должны быть автономными, чтобы их можно было разрабатывать, тестировать и развёртывать независимо друг от друга. Использование общей базы данных приводит к необходимости координации изменений между разными сервисами, что нарушает эту независимость и замедляет процесс разработки.
|
||||
- **Проблемы с масштабируемостью**. Когда все сервисы используют одну базу данных, её сложно масштабировать. Один сервис может использовать значительное количество ресурсов, создавая нагрузку на базу данных и замедляя работу остальных сервисов. Это делает независимое масштабирование отдельных компонентов практически невозможным.
|
||||
- **Трудности с тестированием**. Тестирование сервисов в изолированном окружении становится гораздо сложнее, так как все они зависят от одной базы данных. Чтобы протестировать один сервис, нужно воссоздать всю структуру данных, что может потребовать значительных усилий.
|
||||
|
||||
**Лучшие практики для избежания Shared Database**
|
||||
- [[Database per Service]]. Каждый микросервис должен владеть своей собственной базой данных. Это позволяет сохранять автономность сервисов и исключает возможность прямого доступа к данным другого сервиса.
|
||||
- **Событийная синхронизация.** Если данные одного сервиса нужны другому, лучше использовать [[Событийно-ориентированная архитектура|событийную архитектуру]]. Сервис, владеющий данными, может отправлять события, на которые подписываются другие сервисы, что помогает синхронизировать информацию без необходимости прямого доступа к общей базе данных.
|
||||
- **Использование API для доступа к данным**. Вместо того чтобы обращаться к базе данных другого сервиса напрямую, следует использовать публичные API. Это позволяет соблюсти инкапсуляцию данных и уменьшить связанность между сервисами.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-24]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Database per service]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
33
dev/architecture/Short polling.md
Normal file
33
dev/architecture/Short polling.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
**Short polling** — это метод опроса сервера, при котором клиент периодически отправляет запросы для проверки обновлений или новых данных. В отличие от постоянного соединения, клиент инициирует запросы через заданные интервалы, например, каждую секунду или каждые несколько секунд.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103010806.png|600]]
|
||||
|
||||
**Преимущества:**
|
||||
- Простая реализация, подходит для приложений, где данные обновляются редко.
|
||||
|
||||
**Недостатки:**
|
||||
- Высокая нагрузка на сервер и сеть из-за частых запросов, даже если данные не изменились.
|
||||
- Может приводить к задержкам в получении данных, так как обновления видны только при очередном запросе.
|
||||
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**::
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[../architecture/Long polling]]
|
||||
- [[Webhook]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
79
dev/architecture/Single Responsibility Principle.md
Normal file
79
dev/architecture/Single Responsibility Principle.md
Normal file
@ -0,0 +1,79 @@
|
||||
---
|
||||
aliases:
|
||||
- SRP
|
||||
- принцип единственной ответственности
|
||||
- Single Responsibility
|
||||
- единственная ответственность
|
||||
- единственной ответственности
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
---
|
||||
Каждый класс или метод должен иметь **только одну причину для изменения**, то есть решать одну задачу. Этот принцип называется **Принципом единственной ответственности (SRP)** и входит в набор [[SOLID]]-принципов, которые помогают создавать качественный и поддерживаемый код.
|
||||
|
||||
> [!EXAMPLE] Причина для изменения
|
||||
> Под "причиной для изменения" подразумевается аспект функциональности, который может измениться из-за изменения бизнес-требований. Например, класс, управляющий пользователями, должен модифицироваться только при изменении требований к управлению пользователями, но не из-за обновлений в логике отправки уведомлений.
|
||||
|
||||
Классы или методы, выполняющие несколько задач, усложняют их поддержку. Любое изменение может неожиданно затронуть другие области, увеличивая вероятность ошибок и сложность тестирования.
|
||||
|
||||
Каждый класс или метод должен иметь **только одну** причину для изменения, то есть решать лишь одну задачу.
|
||||
|
||||
Преимущества:
|
||||
1. **Упрощенная поддержка:** Изменения в одной части системы не влияют на другие, снижая риск побочных эффектов.
|
||||
2. **Повышенная переиспользуемость:** Узкоспециализированные классы можно легко применять повторно. Например, класс `EmailService` можно использовать в разных модулях для отправки уведомлений без доработок.
|
||||
3. **Улучшенная читаемость:** Четко определенные обязанности классов упрощают понимание кода для текущих и будущих разработчиков.
|
||||
4. **Снижение риска ошибок:** Разделение ответственности на изолированные компоненты помогает уменьшить вероятность ошибок, так как изменения в одной области не затрагивают другую.
|
||||
5. **Упрощение тестирования:** Можно протестировать независимо каждый компонент.
|
||||
|
||||
## Пример нарушения SRP
|
||||
Рассмотрим класс, который одновременно управляет данными пользователя и отправляет сообщения по электронной почте:
|
||||
|
||||
```java
|
||||
public class UserManager {
|
||||
private String userData;
|
||||
|
||||
public void updateUser(String data) {
|
||||
// Логика управления пользователем
|
||||
this.userData = data;
|
||||
}
|
||||
|
||||
public void sendEmail(String email, String message) {
|
||||
// Логика отправки сообщений
|
||||
System.out.println("Sending email to: " + email);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Класс `UserManager` выполняет две разные задачи: управление данными пользователя и отправку уведомлений. ==Это нарушает принцип единственной ответственности, так как задачи имеют разные причины для изменения.== Такой подход увеличивает [[связанность]] кода, усложняет его поддержку и повышает риск ошибок.
|
||||
|
||||
Разделите обязанности на отдельные классы:
|
||||
|
||||
```java
|
||||
public class UserService {
|
||||
public void updateUser(String data) {
|
||||
// Логика управления пользователем
|
||||
}
|
||||
}
|
||||
|
||||
public class EmailService {
|
||||
public void sendEmail(String email, String message) {
|
||||
// Логика отправки сообщений
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Теперь каждое изменение будет затрагивать только соответствующий класс. Это улучшает читаемость, тестируемость и устойчивость к изменениям.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[SOLID]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Bounded Context|Ограниченный контекст]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
42
dev/architecture/Single point of failure.md
Normal file
42
dev/architecture/Single point of failure.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
aliases:
|
||||
- SPOF
|
||||
- точка отказа
|
||||
- единственная точка отказа
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-08
|
||||
---
|
||||
**Single Point of Failure (SPOF)** — это любой компонент [[../../../../_inbox/Информационная система|системы]], отказ которого приводит к её недоступности или снижению работоспособности. Такие компоненты являются критически важными для функционирования системы, и их выход из строя может иметь катастрофические последствия.
|
||||
|
||||
SPOF часто встречается в системах с центральным узлом, на который приходится вся нагрузка или от которого зависит доступность других компонентов.
|
||||
|
||||
**Примеры Single Point of Failure:**
|
||||
- **Единственный сервер**. Если сервер, обрабатывающий запросы, выходит из строя, система перестает отвечать.
|
||||
- База данных без [[highload/Репликация|репликации]]. При отказе центральной базы данных все операции, зависящие от неё, останавливаются.
|
||||
- **Сетевой маршрутизатор или коммутатор**. Если устройство выходит из строя, теряется связь между частями системы.
|
||||
- [[Централизованный сервис|Централизованный сервис]]. Например, единственная точка авторизации (Auth Service) может остановить работу всей системы при её отказе.
|
||||
- **Единый источник питания**. Если отсутствует резервное питание, система будет недоступна при отключении электричества.
|
||||
|
||||
**Методы устранения Single Point of Failure**
|
||||
- [[highload/Репликация|Репликация]]. Создание копий компонентов (например, баз данных, серверов) для обеспечения их доступности при отказе одного из них.
|
||||
- **Резервирование**. Установка резервного оборудования или программного обеспечения, которое автоматически включается в работу при отказе основного.
|
||||
- **Распределение нагрузки**. Использование балансировщиков нагрузки для равномерного распределения запросов между несколькими серверами или сервисами.
|
||||
- **Отказоустойчивые архитектуры**. Проектирование системы так, чтобы она могла продолжать работу, даже если один из компонентов выйдет из строя.
|
||||
- [[Масштабирование информационной системы|Масштабирование]].
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-08]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Централизованный сервис]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
46
dev/architecture/Throughput.md
Normal file
46
dev/architecture/Throughput.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
aliases:
|
||||
- пропускная способность
|
||||
- пропускной способности
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-12
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Throughput - пропускная способность системы, то есть количество работы, которое система или процесс может выполнить в единицу времени.
|
||||
|
||||
**В чем можно измерять:**
|
||||
- Для web-систем
|
||||
- Количество запросов в единицу времени
|
||||
- Requests per seconds (RPS)
|
||||
- Request per minute (RPM)
|
||||
- Количество данных в единицу времени
|
||||
- Packets per seconds (PPS)
|
||||
- Мегабит в секунду (MB/s)
|
||||
- Количество одновременно обслуживаемых соединений
|
||||
- Simultaneous connections
|
||||
- Cuncurrency
|
||||
- Для баз данных
|
||||
- транзакциях в секунду (т/с)
|
||||
- операциях в секунду (оп/с)
|
||||
|
||||
Что влияет на значение Throughput:
|
||||
- Аппаратные ресурсы
|
||||
- **Сетевая инфраструктура**: В сетевых системах скорость и пропускная способность сети, задержки, [потеря пакетов](Потеря%20пакетов.md), а также эффективность протоколов передачи данных играют ключевую роль в определении общей пропускной способности системы.
|
||||
- **Масштабирование**: Способность системы к [горизонтальному](highload/Горизонтальное%20масштабирование.md) и [вертикальному масштабированию](highload/Вертикальное%20масштабирование.md) также влияет на Throughput. Горизонтальное масштабирование путем добавления дополнительных узлов может увеличить пропускную способность, но также добавляет накладные расходы на синхронизацию и управление.
|
||||
- **Конфигурация системы**: Настройки и конфигурация системы, включая размеры пула соединений, размеры буферов и кэшей, могут влиять на производительность и пропускную способность.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-12]]
|
||||
### Дополнительные материалы
|
||||
- [[Latency]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
55
dev/architecture/Transactional Outbox.md
Normal file
55
dev/architecture/Transactional Outbox.md
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
aliases:
|
||||
- transactional outbox
|
||||
- транзакционный аутбокс
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-15
|
||||
---
|
||||
Transactional Outbox — это [[Паттерн проектирования|шаблон проектирования]], используемый в распределённых системах для обеспечения гарантированной отправки сообщений, особенно при интеграции с [[Брокер сообщений|брокерами сообщений]]. Этот шаблон помогает решить [[Отправка сообщений в Kafka из транзакции БД| проблему атомарности между изменениями в базе данных и отправкой событий]], гарантируя, что сообщение будет отправлено только после успешного выполнения транзакции в базе данных.
|
||||
|
||||
**Схема работы:**
|
||||
1. При выполнении бизнес-операции, например, при изменении данных в базе данных, создаётся запись в таблице `outbox`. Эта запись содержит сообщение, которое нужно отправить другим сервисам.
|
||||
2. Операция создания записи в таблице `outbox` происходит в одной транзакции с основной бизнес-операцией. Это гарантирует, что и изменение данных, и запись сообщения будут выполнены атомарно.
|
||||
3. После успешной фиксации транзакции фоновый процесс или отдельный компонент читает сообщения из таблицы `outbox` и отправляет их в [[брокер сообщений]].
|
||||
4. После успешной отправки сообщения запись в таблице outbox помечается как обработанная и спустя какое-то время удаляется.
|
||||
|
||||
**Преимущества:**
|
||||
- **Гарантированная доставка сообщений**: сообщения фиксируются вместе с бизнес-операциями, что предотвращает ситуацию, когда данные в базе данных обновлены, а сообщение не отправлено.
|
||||
- **Упрощение архитектуры**: использование таблицы `outbox` вместо распределённых транзакций (2PC) значительно упрощает архитектуру и позволяет избежать сложных механизмов блокировки.
|
||||
|
||||
**Недостатки:**
|
||||
- **Дополнительная задержка**: отправка сообщений через фоновый процесс может вызвать небольшую задержку в доставке сообщений, по сравнению с немедленной отправкой.
|
||||
- **Увеличение нагрузки на базу данных**: таблица `outbox` требует дополнительного хранения и управления, что увеличивает нагрузку на базу данных, особенно при большом объёме сообщений.
|
||||
|
||||
Сначала необходимо создать таблицу `outbox` в вашей базе данных для хранения сообщений, ожидающих отправки в Kafka.
|
||||
|
||||
Возможная структура `outbox` таблицы
|
||||
```sql
|
||||
CREATE TABLE outbox (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
topic VARCHAR(255) NOT NULL,
|
||||
payload TEXT NOT NULL,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
- `id`: Уникальный идентификатор записи.
|
||||
- `topic`: Название топика/очереди, в который должно быть отправлено событие.
|
||||
- `payload`: данные события.
|
||||
- `status`: Статус обработки (`PENDING`, `SENT`, `FAILED`).
|
||||
- `created_at` и `updated_at`: Временные метки для отслеживания создания и обновления записи.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[Паттерн проектирования]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-15]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[../../../../_inbox/Transactional Inbox|Transactional Inbox]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
31
dev/architecture/Webhook.md
Normal file
31
dev/architecture/Webhook.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-03
|
||||
---
|
||||
**Webhook** — это метод взаимодействия между системами, при котором один сервер автоматически отправляет HTTP-запрос на другой сервер, когда происходит определенное событие. В отличие от [[../architecture/Long polling|Long polling]] или [[../architecture/Short polling|Short polling]], клиенту не нужно регулярно проверять наличие обновлений; вместо этого он получает уведомление от сервера в режиме реального времени.
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103010806.png|600]]
|
||||
|
||||
**Преимущества:**
|
||||
- Мгновенная доставка данных при возникновении события.
|
||||
- Снижение нагрузки на сервер, так как нет необходимости в регулярных запросах.
|
||||
|
||||
**Недостатки:**
|
||||
- Требует настройки безопасности для предотвращения нежелательных вызовов (например, использование токенов или подписи).
|
||||
- Сложнее тестировать и отлаживать, так как вебхуки зависят от событий, происходящих на сервере.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[../architecture/Протоколы коммуникаций]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-03]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[../architecture/Short polling]]
|
||||
- [[../architecture/Long polling]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
34
dev/architecture/highload/CacheMissRate.md
Normal file
34
dev/architecture/highload/CacheMissRate.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-18
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
- "[[Оценка эффективности кэша|Оценка эффективности кэша]]"
|
||||
---
|
||||
CacheMissRate показывает, насколько часто кэш не справляется с задачей хранения нужных данных и приходится обращаться к базе данных. Обычно рассчитывается как отношение количества промахов мимо кэша к общему количеству запросов на чтение данных. Формула для CacheMissRate выглядит так:
|
||||
|
||||
```
|
||||
CacheMissRate= Количество промахов / Количество запросов.
|
||||
```
|
||||
|
||||
Где:
|
||||
• **Количество промахов** — это число случаев, когда данные не были найдены в кэше и потребовался доступ к базе данных.
|
||||
• **Общее количество запросов** — это общее количество запросов на чтение данных, которые могут быть обслужены кэшем.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-18]]
|
||||
### Дополнительные материалы
|
||||
- [[Оценка эффективности кэша]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
31
dev/architecture/highload/Content Delivery Network.md
Normal file
31
dev/architecture/highload/Content Delivery Network.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
aliases:
|
||||
- CDN
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-01-11
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
---
|
||||
Распределенная географическая сеть кэширующих серверов по всему миру, которая позволяет доставлять контент до пользователей быстрее за счет более близкого расположения сервера к клиенту.
|
||||
|
||||
Бывают push и pull реализации. В push CDN мы должны сами отправить данные, которые будут доступны из cdn. В pull модели CDN сама сходит на сервер за нужными данными.
|
||||
|
||||
**Плюсы:**
|
||||
- Географически распределенный кэш
|
||||
- Уменьшает количество запросов на сервера
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-01-11]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
40
dev/architecture/highload/Disaster recovery.md
Normal file
40
dev/architecture/highload/Disaster recovery.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
- DR
|
||||
- восстановления
|
||||
- восстановление
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-05
|
||||
---
|
||||
Disaster Recovery (восстановление после сбоев) — это совокупность мер, направленных на восстановление [[Информационная система|ИТ-систем]] и операций после серьёзных сбоев, включая аппаратные отказы, кибератаки, природные катастрофы и ошибки пользователей. DR-планы разрабатываются для снижения времени простоя, минимизации потерь данных и обеспечения непрерывности бизнеса.
|
||||
|
||||
Одна из ключевых проблем в DR — это потеря данных. В большинстве сценариев невозможно полностью избежать этой потери, особенно если системы не были спроектированы с высокой степенью [[Reliability|отказоустойчивости]]. Тем не менее, применение современных технологий может значительно сократить объём утраченных данных.
|
||||
|
||||
Для оценки эффективности DR используются следующие метрики:
|
||||
- **RTO (Recovery Time Objective).** Максимально допустимое время восстановления системы.
|
||||
- **RPO (Recovery Point Objective).** Максимально допустимый объём данных, который можно потерять без критического ущерба.
|
||||
|
||||
Разработка эффективного DR-плана включает:
|
||||
1. **Анализ рисков.** Выявление возможных угроз и их последствий.
|
||||
2. **Выбор стратегии.** Определение метрик RTO и RPO, а также подходящих технологий восстановления.
|
||||
3. **Создание документации.** Подробный план действий в случае сбоя.
|
||||
4. **Тестирование.** Регулярное проведение тестов на соответствие плана реальным угрозам.
|
||||
5. **Обновление.** Корректировка плана в зависимости от изменений в инфраструктуре или бизнес-процессах.
|
||||
|
||||
**Методы и инструменты DR**
|
||||
- Резервное копирование
|
||||
- [[Резервное копирование БД]]
|
||||
- [[Репликация|Репликация]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-04-05]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
53
dev/architecture/highload/Асинхронная репликация.md
Normal file
53
dev/architecture/highload/Асинхронная репликация.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-07
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
- "[[Синхронная репликация]]"
|
||||
- "[[Полу-синхронная репликация]]"
|
||||
---
|
||||
Изменения записываются на master и пересылаются на slaves с некоторой задержкой. Этот метод отличается от синхронной репликации тем, что подтверждение транзакции возвращается клиенту до того, как изменения применены на всех репликах, что позволяет улучшить производительность, но может привести к несогласованности данных.
|
||||
|
||||
Быстро, но не надежно. Возможно используется по умолчанию. Реализовано в [MySQL](../../../meta/zero/00%20MySQL.md), [PostgreSQL](../../../meta/zero/00%20PostgreSQL.md)
|
||||
|
||||
Схема выполнения на MySQL.
|
||||
![](../../../meta/files/images/Pasted%20image%2020240206195611.png)
|
||||
|
||||
**Как работает**
|
||||
- Подготовка транзакции в движке БД: Транзакция начинается на главном сервере, где собираются все изменения данных.
|
||||
- Запись транзакции в лог: Все изменения записываются в журнал транзакций (например, Write-Ahead Log в PostgreSQL).
|
||||
- Завершение транзакции в движке БД: Транзакция завершается на master.
|
||||
- Возврат результата клиенту: Клиент получает подтверждение о завершении транзакции
|
||||
- Пересылка лога репликам: Журнал транзакций отправляется на реплики для асинхронного применения изменений.
|
||||
- Воспроизведение транзакции на репликах: Реплики получают журнал и применяют изменения к своим копиям данных, но это может произойти с задержкой.
|
||||
|
||||
**Преимущества**
|
||||
- Высокая производительность: Поскольку подтверждение транзакции возвращается клиенту до её применения на репликах, время отклика уменьшается, что улучшает производительность системы.
|
||||
- Уменьшенная нагрузка на сеть: Пересылка изменений на реплики происходит асинхронно, что снижает нагрузку на сеть и позволяет более эффективно использовать сетевые ресурсы.
|
||||
- Гибкость в использовании: Асинхронная репликация позволяет использовать реплики для различных задач, таких как отчеты или резервное копирование, без влияния на производительность главного сервера.
|
||||
|
||||
**Минусы**
|
||||
- Потеря данных при сбое: Если master выходит из строя до пересылки изменений на реплики, данные могут быть потеряны. Это может привести к несогласованности данных и необходимости восстановления системы.
|
||||
- [Отставание реплики БД](Отставание%20реплики%20БД.md): Задержка в применении изменений на репликах может привести к отставанию реплик от master, что может затруднить выполнение некоторых операций, требующих актуальных данных.
|
||||
- Проблемы с консистентностью данных: Каждая реплика может отставать по разному, из-за этого данные могут быть несогласованными между репликами. Например, пользователь может получить разные результаты для одного и того же запроса.
|
||||
|
||||
## Примеры использования
|
||||
Асинхронная репликация широко используется в системах, где высокая производительность и низкое время отклика имеют приоритет над полной консистентностью данных. Например, в системах аналитики и отчетности, где задержки в обновлении данных не критичны, асинхронная репликация позволяет эффективно распределять нагрузку и использовать реплики для выполнения сложных запросов, не влияя на производительность основного сервера.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-07]]
|
||||
### Дополнительные материалы
|
||||
- [[Синхронная репликация]]
|
||||
- [[Полу-синхронная репликация|Полу-синхронная репликация]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
34
dev/architecture/highload/Балансировка нагрузки.md
Normal file
34
dev/architecture/highload/Балансировка нагрузки.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
aliases:
|
||||
- балансировку нагрузки
|
||||
- Балансировщик нагрузки
|
||||
- балансировщики нагрузки
|
||||
- балансировщиком нагрузки
|
||||
- балансировщиком
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-06-13
|
||||
---
|
||||
![[../../../meta/files/images/Pasted image 20241103021050.png]]
|
||||
|
||||
**Статические алгоритмы**
|
||||
- **Round robin**. Запросы от клиентов отправляются поочередно разным экземплярам сервиса. Как правило, сервисы должны быть stateless (не сохранять состояние между запросами).
|
||||
- **Sticky round-robin** Улучшенная версия алгоритма round robin. Если первый запрос от Алисы попал на сервис A, то и все последующие её запросы будут отправляться на этот же сервис A.
|
||||
- **Weighted round-robin** Администратор может задать вес для каждого сервиса. Сервисы с большим весом будут обрабатывать больше запросов, чем другие.
|
||||
- **Hash (Хеширование)** Этот алгоритм применяет хеш-функцию к IP-адресу или URL запроса. Запросы направляются на соответствующие экземпляры сервиса в зависимости от результата [[../../cryptography/Хеш-функция|хеш-функции]].
|
||||
|
||||
**Динамические алгоритмы**
|
||||
- **Least connections**. Новый запрос отправляется экземпляру сервиса с наименьшим числом текущих соединений.
|
||||
- **Least response time.** Новый запрос отправляется на экземпляр сервиса с самым быстрым временем отклика.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-13]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
67
dev/architecture/highload/Безмастерная репликация.md
Normal file
67
dev/architecture/highload/Безмастерная репликация.md
Normal file
@ -0,0 +1,67 @@
|
||||
---
|
||||
aliases:
|
||||
- безмастерной репликацией
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-04
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 Реляционная база данных|00 Реляционная база данных]]"
|
||||
parents:
|
||||
- "[[Репликация БД|Репликация БД]]"
|
||||
linked:
|
||||
---
|
||||
Безмастерная репликация — это метод репликации в котором отсутствует главный master. Все узлы системы являются равноправными.
|
||||
|
||||
Клиентские приложения могут записывать данные на любой узел системы. Более того ==запросы отправляются сразу на все реплики, но применяются только на тех, которые доступны в данный момент.==
|
||||
|
||||
Для успешного завершения операции записи требуется подтверждение от определенного количества реплик (W). Если количество успешных записей превышает значение W, операция считается успешной. ==Если их меньше, но не 0, отката транзакции не будет.==
|
||||
|
||||
Клиентские приложения читают данные со всех доступных в данный момент реплик. Для успешного чтения требуется подтверждение от определенного количества реплик (R). Если количество ответивших реплик превышает значение R, операция считается успешной.
|
||||
|
||||
![800](../../../meta/files/images/Pasted%20image%2020240226135429.png)
|
||||
|
||||
Формула расчета кворума: W + R > number of replics
|
||||
- W - в каком количестве реплик должна примениться запись, чтобы мы считали ее успешной
|
||||
- R - со скольки реплик мы должны прочитать значение ключа, чтобы считать, что чтение прошло успешным
|
||||
|
||||
**Преимущества:**
|
||||
- **Высокая доступность:** Поскольку все узлы являются равноправными, система не имеет единой точки отказа. Даже если несколько узлов выйдут из строя, остальные узлы продолжают обслуживать запросы.
|
||||
- **Горизонтальное масштабирование:** Безмастерная репликация позволяет легко добавлять новые узлы для повышения производительности и масштабируемости системы.
|
||||
- **Гибкость конфигурации:** Система может быть настроена для достижения различных уровней консистентности и доступности, в зависимости от требований приложений.
|
||||
|
||||
**Проблемы:**
|
||||
- [Нестрогий кворум](Нестрогий%20кворум.md). Возможно чтение старых данных при W+R < N
|
||||
- Проблемы с откатом транзакций: В безмастерной репликации отсутствует механизм отката транзакций, что может усложнить управление ошибками и восстановление данных.
|
||||
- Как в таком случае работает обновление при чтении или противодействие энтропии, ведь эти данные становятся новыми.
|
||||
- Проблемы с консистентностью данных: Поскольку запись данных может происходить на нескольких узлах одновременно, возникает риск конфликтов и несогласованности данных. Для разрешения конфликтов используются различные методы, такие как Last Write Wins или версионирование данных.
|
||||
- Конфликт записей и [Потерянное обновление](Потерянное%20обновление.md).
|
||||
- Проблемы с линеаризуемостью.
|
||||
|
||||
**Поддержание консистентности:**
|
||||
- Анти-энтропия. Реплики могут периодически синхронизоваться друг с другом, чтобы обеспечить консистентность данных.
|
||||
- Противодействие энтропии. Внешний клиент опрашивает все ноды, находит устаревшие данные и обновляет их.
|
||||
- Обновление при чтении (Set on read). Берем последнюю версию после чтения и отправляем в реплики с устаревшими данными.
|
||||
- Last write wins. Кто последний записал, те данные и верные.
|
||||
- [Happens before](Happens%20before.md).
|
||||
- Векторы версий.
|
||||
- [Tombstone](../../Tombstone.md)
|
||||
|
||||
Такая репликация есть в:
|
||||
- DynamoDB
|
||||
- [[Cassandra]]
|
||||
- Scylla (Переписанная на C++ Cassandra)
|
||||
- Riak
|
||||
- Voldemort
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД|Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-04]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
35
dev/architecture/highload/Вертикальное масштабирование.md
Normal file
35
dev/architecture/highload/Вертикальное масштабирование.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
aliases:
|
||||
- вертикальном масштабировании
|
||||
- вертикальному масштабированию
|
||||
- scale-up
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-12
|
||||
---
|
||||
Вертикальное масштабирование представляет собой увеличение мощности существующей машины или сервера путем добавления более мощных процессоров, большего объема оперативной памяти, большей емкости хранения данных и так далее, без добавления дополнительных машин в систему. Это противоположность [горизонтального масштабирования](Горизонтальное%20масштабирование.md), при котором мощность системы увеличивается за счет добавления дополнительных узлов.
|
||||
|
||||
**Плюсы:**
|
||||
1. **Простота управления**: Управление одной машиной обычно проще, чем управление кластером машин, что упрощает администрирование и техническое обслуживание.
|
||||
2. **Совместимость с приложениями**: Вертикальное масштабирование часто не требует изменений в архитектуре или конфигурации приложений, что делает его более простым в реализации для некоторых систем.
|
||||
3. **Меньшая сложность**: Отсутствие необходимости в распределенной обработке данных упрощает архитектуру и может обеспечить более высокую производительность для определенных типов задач.
|
||||
4. **Немедленное улучшение производительности**: Добавление ресурсов к существующему серверу может обеспечить немедленное улучшение производительности без необходимости перераспределения данных или изменения архитектуры системы.
|
||||
- Самый простой способ масштабирования
|
||||
|
||||
**Проблемы:**
|
||||
1. **Ограничения аппаратного обеспечения**: Существует предел, до которого можно улучшить аппаратные характеристики одной машины, что ограничивает максимально достижимое масштабирование.
|
||||
2. **Высокие затраты**: Мощное аппаратное обеспечение может быть значительно дороже, особенно когда речь идет о высокопроизводительных компонентах. Каждое следующее обновление железа обходится дороже предыдущего.
|
||||
3. **Риск сбоев**: Увеличение зависимости от одного сервера повышает риск того, что сбой этого сервера приведет к полной недоступности системы.
|
||||
4. **Простои при апгрейде**: Улучшение аппаратных характеристик сервера часто требует временного отключения и простоя, что может негативно сказаться на доступности сервиса.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Масштабирование информационной системы|Масштабирование информационной системы]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-12]]
|
||||
### Дополнительные материалы
|
||||
- [[Горизонтальное масштабирование]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
39
dev/architecture/highload/Горизонтальное масштабирование.md
Normal file
39
dev/architecture/highload/Горизонтальное масштабирование.md
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
aliases:
|
||||
- горизонтального масштабирования
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-12
|
||||
---
|
||||
Горизонтальное масштабирование это процесс увеличения мощности системы за счет добавления дополнительных узлов в распределенную сеть, а не за счет увеличения мощности уже существующих узлов (как это происходит при [вертикальном масштабировании](Вертикальное%20масштабирование.md)).
|
||||
|
||||
**Плюсы:**
|
||||
- **Масштабируемость**: Горизонтальное масштабирование позволяет системе легко масштабироваться в соответствии с увеличением нагрузки, добавляя больше машин в кластер. Теоретически бесконечно, но физически есть пределы.
|
||||
- **Гибкость**: Можно добавлять дополнительные ресурсы по мере необходимости, что позволяет лучше адаптироваться к изменяющимся требованиям без простоев.
|
||||
- **Надежность и доступность**: Распределение нагрузки и данных между множеством узлов может улучшить общую надежность и доступность системы, так как отказ одного узла не приведет к сбою всей системы.
|
||||
- **Географическое распределение**: Узлы могут быть географически распределены, что помогает минимизировать задержки и улучшить производительность для пользователей в разных регионах.
|
||||
|
||||
**Проблемы:**
|
||||
1. **Сложность управления**: Управление множеством узлов и их координация может быть значительно сложнее, чем управление одним мощным сервером. Нужно делать балансировку вызовов.
|
||||
2. **Сложность разработки**: Разработка приложений, способных эффективно использовать ресурсы в распределенной среде, может быть более сложной, а значит программисты обходятся дороже.
|
||||
3. **Согласованность данных**: Обеспечение согласованности данных между множеством узлов может представлять собой вызов, особенно в системах, где требуется высокий уровень согласованности.
|
||||
4. **Затраты на сеть**: Горизонтальное масштабирование может повлечь за собой увеличенные затраты на сетевое оборудование и управление сетью, особенно если узлы географически распределены.
|
||||
|
||||
Частные проблемы:
|
||||
- [[../Проблема горизонтального масштабирования Websocket|Проблема горизонтального масштабирования Websocket]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Масштабирование информационной системы|Масштабирование информационной системы]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-12]]
|
||||
### Дополнительные материалы
|
||||
- [[Вертикальное масштабирование]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Репликация]]
|
||||
- [[Проблема горизонтального масштабирования Websocket]]
|
||||
<!-- SerializedQuery END -->
|
40
dev/architecture/highload/Групповая репликация.md
Normal file
40
dev/architecture/highload/Групповая репликация.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-05
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
---
|
||||
Работает как [Репликация master-master](Репликация%20master-master.md), но при количестве узлов больше 2
|
||||
|
||||
- Все транзакции чтения и записи фиксируются только после того, как они были одобрены группой.
|
||||
- Read-only транзакции не требуют координации внутри группы и фиксируются немедленно
|
||||
- Групповая репликация - eventual consistency система
|
||||
|
||||
![](../../../meta/files/images/Pasted%20image%2020240605091036.png)
|
||||
|
||||
## Консенсус
|
||||
- Когда транзакция read-write готова к фиксации на исходном сервере, сервер атомарно передает значения записи (строки, которые были изменены) и соответствующий набор записи (уникальные идентификаторы строк, которые были обновлены).
|
||||
- Транзакция отправляется через атомарную broadcast рассылку, транзакцию получают либо все серверы в группе, либо ни один.
|
||||
- Если они его получат, то все они получат его в том же порядке относительно других транзакций, которые были отправлены ранее.
|
||||
|
||||
Таким образом, все серверы получают один и тот же набор транзакций в одном и том же порядке, и для транзакций устанавливается глобальный общий порядок.
|
||||
|
||||
## Дополнительные материалы
|
||||
- [MySQL 20.1.1.2 Group Replication](https://dev.mysql.com/doc/refman/8.0/en/group-replication-summary.html)
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-05]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
@ -0,0 +1,33 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-12
|
||||
---
|
||||
При реализации [[../Идемпотентность|идемпотентности]] в системах, где требуется многократная обработка событий или вызовов, [[../../../meta/zero/00 Redis|Redis]] может быть использован как ключевой инструмент для предотвращения повторной обработки сообщений. Данное решение подходит для различных систем обмена сообщениями, таких как [[../../../../../_inbox/00 Kafka|Kafka]], [[../../gRPC|gRPC]], [[../../network/HyperText Transfer Protocol|HTTP]], и других видов асинхронных или синхронных вызовов.
|
||||
### Основной подход
|
||||
Каждое сообщение или запрос должен иметь уникальный идентификатор, обычно называемый **requestId**. Этот идентификатор присваивается при создании сообщения или вызова и передаётся вместе с ним в процессе обработки. Потребитель, получая сообщение, сначала проверяет наличие **requestId** в Redis. Этот подход позволяет контролировать, было ли сообщение уже обработано и в каком оно состоянии.
|
||||
|
||||
Алгоритм выглядит следующим образом:
|
||||
1. **Получение сообщения**: Потребитель получает сообщение, извлекает **requestId** и проверяет его наличие в Redis.
|
||||
1. Если **requestId** уже существует в Redis и статус обработки указывает на **COMPLETED**, потребитель ничего не делает и отправляет **ack** (подтверждение) в Kafka (или другой источник).
|
||||
2. **Обработка сообщения**: Если **requestId** отсутствует в Redis или статус обработки указывает на **FAILED**, потребитель, то потребитель обрабатывает сообщение. Перед обработкой статус в Redis обновляется на **IN_PROGRESS** с TTL, например, 40 секунд.
|
||||
3. **Запись результата**:
|
||||
- После успешной обработки статус в Redis обновляется на **COMPLETED**, и устанавливается длительный TTL, например, на 3-24 часа, чтобы сигнализировать, что это сообщение уже было успешно обработано и повторная обработка не требуется.
|
||||
- Если при обработке возникает ошибка, статус обновляется на **FAILED** и потребитель отправляет **nack** в Kafka (или другой источник).
|
||||
### Рекомендации по реализации
|
||||
- **Уникальность requestId**: Генерируйте **requestId** таким образом, чтобы обеспечить его уникальность в пределах всей системы, например, используя UUID или другие подходящие алгоритмы.
|
||||
- **Оптимальный TTL**: Выберите TTL в зависимости от требований к ретеншену данных. Слишком короткий TTL может привести к потере информации об обработке, а слишком длинный — к переполнению Redis.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Идемпотентность|Идемпотентность]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-12]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
65
dev/architecture/highload/Инвалидация кэша.md
Normal file
65
dev/architecture/highload/Инвалидация кэша.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
aliases:
|
||||
- инвалидации кэша
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-18
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
---
|
||||
Инвалидация кэша это процесс удаления данных из кэша при изменении состояния источника. Причем очень желательно, чтобы кэш сбрасывался сразу же за изменением. Например, мы закэшировали выборку из БД, рано или поздно исходные данные таблицы изменятся, и кэш перестает быть валидным.
|
||||
|
||||
**Способы инвалидации:**
|
||||
- По истечению срока действия - TTL.
|
||||
- Самая простая реализация.
|
||||
- При малом TTL будет высокий [CacheMissRate](CacheMissRate.md)
|
||||
- При большом TTL данные могут быть не консистентны
|
||||
- По событию
|
||||
- Опасно из-за риска мгновенной инвалидации и сопутствующей [[Перестройка кэша|перестройки кэша]]
|
||||
- Использование [[../../algorithm/Алгоритм вытеснения кэша|алгоритмов вытеснения]]
|
||||
|
||||
Дополнительно для работы со статическими файлами можно отменить [[../Fingerprint|Fingerprint]].
|
||||
|
||||
## Инвалидация по TTL
|
||||
Один из подходов это инвалидация по времени. Для кэшированных данных устанавливается TTL, и по прошествию времени кэш удаляется. Такое вариант подходит для редко изменяемых данных, устаревание которых не приводит к серьезным проблемам в бизнес-логике, например словари.
|
||||
|
||||
При таком варианте важно подобрать оптимальное время жизни кэша, слишком маленькое время жизни будет давать плохую производительность, слишком большое ухудшит опыт пользователей. В оценке эффективности кэша поможет метрика [[CacheMissRate]].
|
||||
## Инвалидация по событию
|
||||
В этом случае мы удаляем данные кэша по какому-то событию. Например, при вызове метода обновления данных можно удалить кэш, который связан с этими данными. В некоторых случаях можно не удалять, а сразу класть новые данные в кэш, если понимаете, что они скоро потребуются.
|
||||
|
||||
Инвалидацию по событию можно комбинировать с TTL. В таком случае при запросе данных из кэша можно проверять оставшееся время жизни, и если оно меньше, чем некоторое заданное значение, то установить TTL заново. Таким образом данные остаются в кэше, если ими активно пользуются.
|
||||
|
||||
Пример реализации механизма обновления TTL на Lua:
|
||||
```lua
|
||||
local key = KEYS[1];
|
||||
local threshold = tonumber(ARGV[1]);
|
||||
local new_ttl = tonumber(ARGV[2]);
|
||||
local value = redis.call('get', key);
|
||||
if value then
|
||||
local ttl = redis.call('pttl', key);
|
||||
if ttl >= 0 and ttl <= threshold then
|
||||
redis.call('pexpire', key, new_ttl);
|
||||
end;
|
||||
end;
|
||||
return value;
|
||||
```
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-18]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Алгоритм вытеснения кэша]]
|
||||
- [[Fingerprint]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
63
dev/architecture/highload/Ключ кэширования.md
Normal file
63
dev/architecture/highload/Ключ кэширования.md
Normal file
@ -0,0 +1,63 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-13
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Кэширование]]"
|
||||
linked:
|
||||
---
|
||||
Представим, что нам нужно кэшировать результат работы следующего метода:
|
||||
|
||||
```java
|
||||
public List<User> getUsersByType(String userType, Set<Long> userIds)
|
||||
```
|
||||
|
||||
Метод принимает 2 аргумента: строку и коллекцию. Ключ кэширования должен учитывать значения этих входящих аргументов и должен обладать следующими свойствами:
|
||||
- При изменении параметров, ключ кэширования также должен изменяться. В данном случае, если изменятся значения аргументов `userType` и `userIds`, мы должны получить новое значение ключа.
|
||||
- По параметрам ключ должен определяться однозначно, то есть для одних и тех же значений аргументов ключ кэширования должен принимать только одно значение. Иначе мы рискуем понизить эффективность процесса кэширования, создавая несколько кэшей для одной и той же выборки.
|
||||
|
||||
Сформируем ключ кэширования для нашего метода. В качестве хранилища будем использовать [[../../../meta/zero/00 Redis]].
|
||||
|
||||
В начале ключа я обычно обязательно указываю какой-то уникальный префикс сервиса, чтобы не получить коллизию между разными сервисами. Пускай в данном случае префикс будет `USER_SERVICE`. Также добавляю уникальный префикс метода, в данном случае будет `USERS`.
|
||||
|
||||
В качестве разделителей рекомендую использовать `:`, в [[../../../meta/zero/00 Redis|00 Redis]] это позволяет визуально сгруппировать ключи. Это позволяет визуально группировать ключи при использовании UI клиента. Таким образом начало нашего ключа выглядит следующим образом: `USER_SERVICE:USERS:`.
|
||||
|
||||
Значения аргументов метода также должны попасть в ключ. Возьмем наш первый аргумент `String userType`. Для аргумента также можно использовать префиксы, но это не обязательно. В данном случае пусть будет `USER_TYPE`. А вот для самого значения параметра есть несколько вариантов:
|
||||
- Оставить строкой и просто выполнить конкатенацию.
|
||||
- Использовать [[../../cryptography/Хеш-функция|хеш-функцию]] с фиксированной длиной выхода, например [[../../cryptography/MD5|MD5]]. Фиксированная длина выхода нужна, чтобы иметь предсказуемую и ограниченную длину ключа.
|
||||
|
||||
Оставим просто строкой, так как тип пользователя вряд ли может быть длинным. В итоге пока наш ключ выглядит как-то так: `USER_SERVICE:USERS:USER_TYPE:VIP:`.
|
||||
|
||||
Переходим ко второму аргументу `Set<Long> userIds`. С коллекцией все будет сложнее. Мы точно должны использовать какую-нибудь [[../../cryptography/Хеш-функция|хеш-функцию]], но как?
|
||||
|
||||
> [!WARNING] Disclamer
|
||||
> Этот способ я придумал сам, возможно он не самый удачный, но он работает. Если вы придумаете лучше, напишите в комментариях ниже 👇
|
||||
|
||||
Во-первых, коллекцию необходимо предварительно отсортировать. Иначе на одинаковые параметры коллекций мы будем получать разные результаты [[../../cryptography/Хеш-функция|хеш-функции]].
|
||||
|
||||
Во-вторых, нужно представить коллекцию как что-то понятное для [[../../cryptography/Хеш-функция|хеш-функции]]. Для этого я преобразую коллекцию в JSON. JSON используется, потому что ваша коллекция может быть из сложных объектов.
|
||||
|
||||
Теперь используем [[../../cryptography/SHA-256|SHA-256]], чтобы из нашей строки получить какой-то хеш. И уже этот хеш мы добавляем к нашему ключу, получается примерно такое:
|
||||
|
||||
```
|
||||
USER_SERVICE:USERS:USER_TYPE:VIP:USER_ID:315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
|
||||
```
|
||||
|
||||
> [!QUESTION] Почему SHA-256, а не MD5?
|
||||
> [[../../cryptography/MD5|MD5]] подвержен коллизиям, [[../../cryptography/SHA-256|SHA-256]] считается более устойчивым к коллизиям.
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-13]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[../../snippet/Реализация SHA-256 на Java|Реализация SHA-256 на Java]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
48
dev/architecture/highload/Кэширование на стороне браузера.md
Normal file
48
dev/architecture/highload/Кэширование на стороне браузера.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
aliases: []
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
---
|
||||
Статический контент — это элементы веб-сайта, которые остаются неизменными на протяжении долгого времени на всех страницах. К такому контенту относятся файлы изображений, CSS и JavaScript. Поскольку эти файлы редко изменяются, их можно сохранять в кэше браузера пользователя. Это позволяет браузеру загружать локальные копии файлов, а не запрашивать их каждый раз с сервера, что ускоряет работу сайта.
|
||||
|
||||
Обычно кэшируются только GET запросы, так как они должны быть [[../Идемпотентность|идемпотентны]].
|
||||
|
||||
Управление кэшированием часто осуществляется с помощью http-заголовков. Заголовки для кэширования:
|
||||
- ETAG. Тег, который позволяет указать версию файла. Можно использовать [[../../cryptography/MD5|MD5]].
|
||||
- [[../../network/Условный GET запрос|If-Modified-Since]]. Дата изменения файла.
|
||||
- Cache-Control. Передает инструкции по выполнению кэширования.
|
||||
- public - Сохранять может не только браузер, но и промежуточные узлы
|
||||
- private - Сохранять может только браузер клиента
|
||||
- no-store - не кэшируем. ==не уверен что правильно записал==
|
||||
- no-cache - Сохранять только в браузере, не сохранять на промежуточных серверах. ==не уверен что правильно записал==
|
||||
- max-age - Сколько нужно хранить файл в памяти
|
||||
- LocalStorage. Можно через JS складывать данные.
|
||||
|
||||
|
||||
![](../../../meta/files/images/Pasted%20image%2020240619083856.png)
|
||||
|
||||
Инвалидация:
|
||||
- Самый простой вариант указывать версию в GET параметрах.
|
||||
- Для статики можно использовать [[../Fingerprint|Fingerprint]]
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-17]]
|
||||
### Дополнительные материалы
|
||||
- [[../../devops/nginx/Кэширование статики в Nginx]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Кэширование статики в Nginx]]
|
||||
<!-- SerializedQuery END -->
|
26
dev/architecture/highload/Монотонное чтение.md
Normal file
26
dev/architecture/highload/Монотонное чтение.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-07
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
---
|
||||
Монотонное чтение — это проблема, возникающая при репликации данных, когда пользователи могут получить несогласованные результаты при выполнении последовательных запросов. Это происходит, когда изменения на мастере не успевают синхронизироваться с репликами, и разные запросы пользователя могут попадать на реплики с различными состояниями данных.
|
||||
## Пример проблемы монотонного чтения
|
||||
Рассмотрим ситуацию, когда пользователь запрашивает список комментариев к статье. Если новый комментарий был добавлен и записан на мастер, но ещё не успел синхронизироваться со всеми репликами, пользователь может столкнуться с несогласованными результатами:
|
||||
|
||||
1. Пользователь делает первый запрос и получает список комментариев без нового комментария.
|
||||
2. Пользователь делает второй запрос и получает список комментариев, включающий новый комментарий.
|
||||
3. При следующем запросе пользователь снова может не увидеть новый комментарий, если его запрос попадает на другую реплику.
|
||||
|
||||
![](../../../meta/files/images/Pasted%20image%2020240607211612.png)
|
||||
|
||||
## Методы решения проблемы монотонного чтения
|
||||
- Привязка пользователя к конкретной реплике (stickiness): Один из способов решения проблемы монотонного чтения — это привязка пользователя к конкретной реплике для всех последовательных запросов. Это можно реализовать с помощью сессий или токенов, обеспечивая пользователю доступ к одной и той же реплике, пока она доступна.
|
||||
- Настройка задержек при чтении: Можно настроить задержки при чтении данных с реплик, чтобы обеспечить их синхронизацию с мастером. Например, задержка может быть настроена таким образом, чтобы реплики всегда отставали от мастера на фиксированное время, достаточное для синхронизации данных.
|
||||
- Использование кворумных чтений: В системах с [[Безмастерная репликация|безмастерной репликацией]] можно использовать кворумные чтения, когда запросы выполняются на нескольких репликах одновременно, и результат считается успешным только если он подтвержден большинством реплик. Это повышает вероятность получения актуальных данных.
|
37
dev/architecture/highload/Отставание реплики БД.md
Normal file
37
dev/architecture/highload/Отставание реплики БД.md
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
aliases:
|
||||
- лаг репликации
|
||||
- задержки репликации
|
||||
- задержка репликации
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-04
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
---
|
||||
Отставание реплики (или лаг репликации) — это проблема, возникающая, когда изменения, выполненные на мастере, не успевают применяться на репликах вовремя. Это может привести к несогласованности данных между мастером и репликами и затруднить выполнение операций, требующих актуальных данных.
|
||||
|
||||
В нормальной ситуации отставание может достигать 1 секунды.
|
||||
|
||||
![](../../../meta/files/images/Pasted%20image%2020240219184314.png)
|
||||
|
||||
Так как в [[../../../meta/zero/00 PostgreSQL|PostgreSQL]] мы передаем не сам запрос, а блоки данных, то отставание по идее должно быть меньше, чем в [[../../../meta/zero/00 MySQL|MySQL]].
|
||||
|
||||
Что может приводить к лагу:
|
||||
- Медленные и сложные запросы: Если реплики выполняют сложные или ресурсоемкие запросы, это может замедлить процесс применения изменений.
|
||||
- Сетевые проблемы: Задержки в сети могут замедлить передачу журнала транзакций (WAL) от мастера к репликам.
|
||||
- Размер журнала транзакций: Большие объемы изменений могут создать нагрузку на систему репликации, увеличивая время обработки.
|
||||
- Проблемы с дисковой подсистемой: Медленные дисковые операции на репликах могут замедлить процесс применения изменений.
|
||||
|
||||
Рекомендации:
|
||||
- Оптимизация запросов: Оптимизация сложных запросов может снизить нагрузку на реплики и ускорить процесс применения изменений. Это включает в себя индексацию, переработку запросов и использование эффективных алгоритмов.
|
||||
- Убивайте медленные запросы. Если запрос висит уже 10 секунд, то лучше его прибить.
|
||||
- Использование выделенных реплик: Для выполнения сложных запросов или резервного копирования можно использовать выделенные реплики, что позволит снизить нагрузку на основные реплики, обеспечивающие актуальность данных.
|
||||
- Подумайте о кросс-СУБД репликации Репликация из реляционной бд в NoSQL
|
||||
- Избегайте [[../../database/Write-read pattern|Write-read pattern]]
|
||||
- Выделить отдельный жесткий диск под [Журнал БД](../../database/Журнал%20БД.md), чтобы обеспечить эксклюзивный доступ к ресурсам диска, тем самым улучшая производительность. Менее актуально для SSD.
|
||||
- Настройка параметров репликации: Оптимизация параметров репликации, таких как размер WAL и частота его отправки, может помочь уменьшить лаг репликации. В PostgreSQL, например, можно настроить параметры wal_level и max_wal_senders для оптимизации процесса репликации.
|
40
dev/architecture/highload/Оценка эффективности кэша.md
Normal file
40
dev/architecture/highload/Оценка эффективности кэша.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-11
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
- "[[CacheMissRate|CacheMissRate]]"
|
||||
---
|
||||
По формуле можно рассчитать среднее время доступа к данным.
|
||||
|
||||
```
|
||||
AverageTime = CacheAccessTime + DbAccessTime * CacheMissRate
|
||||
```
|
||||
|
||||
Где:
|
||||
- AverageTime - среднее время жизни кэша
|
||||
- CacheAccessTime - время доступа к кэшу
|
||||
- DbAccessTime - время доступа к БД
|
||||
- [[CacheMissRate|CacheMissRate]] - количество промахов мимо кэша. От 0 до 1.
|
||||
|
||||
Например, пусть
|
||||
- DbAccessTime = 100ms
|
||||
- CacheAccessTime = 20ms
|
||||
- Тогда при [[CacheMissRate|CacheMissRate]] > 0.8 - кэш вреден.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-11]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[CacheMissRate|CacheMissRate]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
35
dev/architecture/highload/Перестройка кэша.md
Normal file
35
dev/architecture/highload/Перестройка кэша.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
aliases:
|
||||
- thundering herd
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-18
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
---
|
||||
Представим, что у нас 3 реплики сервиса, которые выполняют какие-то вычисления раз в 30 секунд, а в вычислениях используется кэшированные значения. При [[Инвалидация кэша|инвалидации кэша]] может сложиться ситуация при которой все 3 реплики начнут наперегонки обновлять значение в кэше. Это приводит как минимум к лишней нагрузке на базу данных, а как максимум к отказу в обслуживании.
|
||||
|
||||
Решить эту проблему можно с использованием [[../../fundamental/Блокировка|блокировок]]:
|
||||
- Получаем доступ к кэшу, его срок жизни истёк. Пытаемся заблокироваться по ключу.
|
||||
- Не удалось получить блокировку
|
||||
- Ждём снятия [[../../fundamental/Блокировка|блокировки]].
|
||||
- Если не дождались, возвращаем старые данные кэша
|
||||
- Если дождались, значит кто-то построил кэш за нас, выбираем значения ключа заново, возвращаем новые данные.
|
||||
- Удалось получить блокировку
|
||||
- Строим кэш самостоятельно
|
||||
- Снимаем блокировку
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
53
dev/architecture/highload/Полу-синхронная репликация.md
Normal file
53
dev/architecture/highload/Полу-синхронная репликация.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
aliases:
|
||||
- semi-sync
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-07
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
- "[[Асинхронная репликация]]"
|
||||
- "[[Синхронная репликация]]"
|
||||
---
|
||||
Полу-синхронная репликация — это компромиссный метод между [[Синхронная репликация|синхронной]] и [[Асинхронная репликация|асинхронной]] репликацией. Он обеспечивает более высокую надежность данных по сравнению с асинхронной репликацией, но при этом снижает время отклика по сравнению с синхронной.
|
||||
|
||||
Комит прошел на одной реплике, но данные по транзакции были скопированы во все остальные реплики, но еще не были применены.
|
||||
|
||||
Реализовано в [MySQL](../../../meta/zero/00%20MySQL.md)
|
||||
|
||||
Схема выполнения на MySQL ![](../../../meta/files/images/Pasted%20image%2020240206195639.png)
|
||||
|
||||
**Как работает**
|
||||
- Подготовка транзакции в движке БД: Транзакция начинается на master, где собираются все изменения данных.
|
||||
- Запись транзакции в лог: Все изменения записываются в журнал транзакций.
|
||||
- Пересылка лога репликам: Журнал транзакций отправляется на реплики. Master ждет подтверждения от как минимум одной реплики о получении журнала, но не обязательно его применении.
|
||||
- Завершение транзакции в движке БД: После получения подтверждения от одной или нескольких реплик транзакция завершается на master, и клиент получает подтверждение.
|
||||
- Воспроизведение транзакции на репликах: Реплики применяют полученные изменения к своим копиям данных, но это может произойти с задержкой.
|
||||
|
||||
**Преимущества**
|
||||
- Баланс между надежностью и производительностью: Полу-синхронная репликация обеспечивает более высокую надежность данных по сравнению с асинхронной репликацией, так как master ждет подтверждения от реплик перед завершением транзакции. Это снижает риск потери данных при сбое.
|
||||
- Сниженное время отклика: В отличие от синхронной репликации, master не ждет подтверждения от всех реплик, что снижает время отклика и повышает производительность системы.
|
||||
- Меньшая вероятность отставания данных: Благодаря ожиданию подтверждения от реплик перед завершением транзакции, вероятность отставания данных на репликах уменьшается.
|
||||
|
||||
**Минусы**
|
||||
- Проблемы с консистентностью данных: Хотя master ждет подтверждения от одной или нескольких реплик, данные на других репликах могут оставаться несогласованными до применения изменений, что может привести к проблемам с консистентностью. [Фантомное чтение](Фантомное%20чтение.md).
|
||||
- Сложность управления: Полу-синхронная репликация требует более сложной настройки и управления по сравнению с асинхронной репликацией, так как необходимо следить за подтверждениями от реплик и управлять задержками.
|
||||
- Увеличенное время отклика по сравнению с асинхронной репликацией: Несмотря на снижение времени отклика по сравнению с синхронной репликацией, полу-синхронная репликация все же медленнее асинхронной, так как требует ожидания подтверждений от реплик.
|
||||
## Примеры использования
|
||||
Полу-синхронная репликация часто используется в системах, где требуется баланс между надежностью данных и производительностью. Например, в финансовых системах, где важна высокая доступность и консистентность данных, но при этом необходимо обеспечить приемлемое время отклика для клиентов. Полу-синхронная репликация позволяет снизить риск потери данных при сбоях и поддерживать консистентность данных на более высоком уровне, чем асинхронная репликация.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-07]]
|
||||
### Дополнительные материалы
|
||||
- [[Асинхронная репликация]]
|
||||
- [[Синхронная репликация]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
55
dev/architecture/highload/Репликация master-master.md
Normal file
55
dev/architecture/highload/Репликация master-master.md
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-10
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
- "[[Репликация master-slave]]"
|
||||
---
|
||||
Все реплики являются ведущими (master). Во все реплики можно писать изменения, а они каким-то образом синхронизируются между собой. Ведущие реплики могут также иметь дополнительные реплики в режиме [[Репликация master-slave|репликации master-slave]].
|
||||
|
||||
![](Pasted%20image%2020240206194251.png)
|
||||
|
||||
**Плюсы**:
|
||||
- Нет единой точки отказа
|
||||
- Дает максимальный [Availability](../../../../../_inbox/Availability.md).
|
||||
- Легкий failover
|
||||
|
||||
**Минусы:**
|
||||
- Нет консистентности. Могут возникать конфликты при одновременной работе с одним и тем же набором данных на разных репликах.
|
||||
- Усложнение логики. Встречается редко.
|
||||
- Все равно не масштабирует запись. Для масштабирования нужно использовать [шардирование](Шардирование%20БД.md).
|
||||
|
||||
**Варианты применения:**
|
||||
- Географическая распределенность. Репликация между ЦОД-ами в разных странах. Улучшается производительность, так как пользователь из страны работает с ближайшим ЦОД. Вы устойчивы к потере ЦОД и к сетевым проблемам, так как данные есть в других ЦОД-ах.
|
||||
- Hot-standby реплика (VIP). Второй мастер всегда на готове, на случай если упадет основной. Во время штатной работы второй мастер не используется.
|
||||
- Offline клиенты. При плохом или вовсе временно отсутвующем интерент соединении для ассинхронного объединения данных. CouchDB является примером такой БД.
|
||||
|
||||
Варианты реализаций:
|
||||
- Amazon Aurora
|
||||
- Google Spanner
|
||||
## Решение конфликтов
|
||||
- Избегайте конфликтов. Организуйте взаимодействие так, чтобы конфликты не возникали.
|
||||
- Last write wins. Выигрывает последняя запись. Но обычно сложно определить кто был первым.
|
||||
- Ранг реплик. Выигрывает запись от старейшей реплки.
|
||||
- Слияние. Автоматическое объединение конфликтных данных.
|
||||
- Решение конфликтов на клиенте.
|
||||
- Conflict-free replicated data types (CRDT).
|
||||
- Mergeable persistent data structures.
|
||||
- В этом режиме работает [00 Git](../../../meta/zero/00%20Git.md)
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-10]]
|
||||
### Дополнительные материалы
|
||||
- [[Репликация master-slave]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
38
dev/architecture/highload/Репликация master-slave.md
Normal file
38
dev/architecture/highload/Репликация master-slave.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
aliases:
|
||||
- репликации master-slave
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-10
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД|Репликация БД]]"
|
||||
linked:
|
||||
- "[[Репликация master-master]]"
|
||||
---
|
||||
В такой схеме у нас есть одна ведущая реплика (master) в которую пишутся изменения и несколько ведомых реплик (slave), на которые эти изменения копируются, из них можно только читать. Это наиболее распространенный подход репликации, так как он относительно прост и понятен.
|
||||
|
||||
![](Pasted%20image%2020240206194227.png)
|
||||
|
||||
**Проблемы и недостатки:**
|
||||
- Мастер обязательно когда-нибудь упадет. И нужно будет как-то выбрать из slaves нового master.
|
||||
- Как и другие способы репликации не ускоряет операции вставки данных.
|
||||
- Этот способ никогда не даст 99,9999 [Availability](../../../../../_inbox/Availability.md).
|
||||
|
||||
Управление master-slave:
|
||||
- MHA (MySQL Master HA)
|
||||
- MySQL Failover (Oracle)
|
||||
- Orchestrator
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД|Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-10]]
|
||||
### Дополнительные материалы
|
||||
- [[Репликация master-master|Репликация master-master]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
100
dev/architecture/highload/Репликация БД.md
Normal file
100
dev/architecture/highload/Репликация БД.md
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
aliases:
|
||||
- репликация базы данных
|
||||
- репликацию бд
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-03-10
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
- "[[../../../meta/zero/00 DevOps|00 DevOps]]"
|
||||
- "[[../../../meta/zero/00 Реляционная база данных|00 Реляционная база данных]]"
|
||||
parents:
|
||||
- "[[Репликация|Репликация]]"
|
||||
linked:
|
||||
---
|
||||
## Тезисы
|
||||
- Репликация это копирование измененных данных с одного сервера БД на другой.
|
||||
- Не отменяет первоначального копирования БД. Сначала нужно первый раз скопировать данные, а потом уже запустить репликацию.
|
||||
- Репликация не является [резервной копией БД](../../../../../_inbox/Резервное%20копирование%20БД.md).
|
||||
- Обычно реализуются на базе [[../../database/Журнал БД|журнала БД]].
|
||||
- Плюсы:
|
||||
- Помогает улучшить [Availability](../../../../../_inbox/Availability.md). Помогает при падении.
|
||||
- Ускоряет чтение данных
|
||||
- Проблемы:
|
||||
- Не ускоряет запись в БД
|
||||
- [Отставание реплики БД](Отставание%20реплики%20БД.md)
|
||||
- [[Монотонное чтение|Монотонное чтение]]
|
||||
- Репликация это ресурсозатратно.
|
||||
- Репликации БД:
|
||||
- [Репликация в MySQL](../../database/mysql/Репликация%20в%20MySQL.md)
|
||||
- [Репликация в PostgreSQL](../../database/postgresql/Репликация%20в%20PostgreSQL.md)
|
||||
***
|
||||
Репликация позволяет сделать N копий одной БД. Обычно есть одна ведущая копия, которую называют master, и есть N ведомых реплик, которые называют slaves.
|
||||
|
||||
Репликация не отменяет первоначального копирования БД. Сначала нужно первый раз скопировать данные, а потом уже запустить репликацию.
|
||||
|
||||
**Для чего делают репликацию?**
|
||||
- [[../../../../../_inbox/Availability|Availability]]. Если один сервер выходит из строя, другие реплики продолжают обслуживать запросы, обеспечивая непрерывный доступ к данным.
|
||||
- **Масштабирование чтения**. Нагрузка на чтение может быть распределена между несколькими репликами, что улучшает производительность системы.
|
||||
- **Распределение нагрузки**. Сложные аналитические запросы для построения отчетов и асинхронное [резервное копирование БД](../../../../../_inbox/Резервное%20копирование%20БД.md) могут выполняться на отдельных репликах, не нагружая основной сервер.
|
||||
- **Географическое распределение**. Реплики могут быть размещены ближе к пользователям в разных регионах, уменьшая задержки доступа к данным.
|
||||
|
||||
**Недостатки репликации:**
|
||||
- Не позволяет получить увеличение производительности запросов на вставку данных. Для этого нужно использовать [[../../../../../_inbox/Шардирование БД|шардирование]].
|
||||
- **Сложность управления**. Управление несколькими репликами требует дополнительных ресурсов и сложной конфигурации. Это включает настройку синхронизации данных, мониторинг состояния реплик и управление конфликтами.
|
||||
- **Ресурсозатратность**. Поддержание нескольких копий данных требует дополнительных ресурсов, что может значительно увеличить расходы на инфраструктуру.
|
||||
- **Проблемы консистентности:** В асинхронной репликации данные на разных репликах могут быть несогласованными, что может привести к проблемам с консистентностью. Например, пользователь может получить разные результаты для одного и того же запроса, если реплики не успели синхронизироваться.
|
||||
## Роль журнала БД в репликации
|
||||
Прямой способ сделать репликацию - это скопировать [[../../database/Журнал БД|журнал БД]] с master на slave и применить его. PostgreSQL работает именно так используя журнал [WAL](../../database/postgresql/Write-Ahead%20Log.md). Однако, не все так просто. Формат и возможности журнала напрямую зависят от СУБД.
|
||||
|
||||
![](Pasted%20image%2020240531083508.png)
|
||||
## Классификация репликаций
|
||||
- **По синхронизации.** Гарантия наличия и доступности.
|
||||
- [Синхронная репликация](Синхронная%20репликация.md)
|
||||
- [Асинхронная репликация](Асинхронная%20репликация.md)
|
||||
- [Полу-синхронная репликация](Полу-синхронная%20репликация.md)
|
||||
- **По уровню работы**
|
||||
- Физическая репликация. Работа на уровне хранилища, мы работаем напрямую со страницами памяти
|
||||
- [Write-Ahead Log](../../database/postgresql/Write-Ahead%20Log.md) в PostgreSQL
|
||||
- [InnoDB Undo/Redo Log](../../database/mysql/Журналы%20в%20MySQL.md#InnoDB%20Undo/Redo%20Log) в MySQL
|
||||
- Логическая репликация. Работает с кортежами. Мы храним набор кортежей до и после.
|
||||
- [Row-based Binary Log](../../database/mysql/Журналы%20в%20MySQL.md#Row-based%20Binary%20Log) в MySQL
|
||||
- [Statement-based Binary Log](../../database/mysql/Журналы%20в%20MySQL.md#Statement-based%20Binary%20Log) недоразумение, которое работает на уровне запросов. Для такой репликации нужно выполнять запрос на слейве, и если запрос выполнялся 30 минут, то и на слейве он будет выполняться 30 минут. Также присутсвует зависимость в функциях, например функция времени вернет одно значение на мастере и совершенно другое на слейве.
|
||||
- **По расспространению изменений**
|
||||
- push. мастер сует, слейву пофиг. Реализуется редко. (Postgres)
|
||||
- pull. слейв качает, мастеру пофиг. (MySQL)
|
||||
- **По количеству точек записи**
|
||||
- [Репликация master-slave](Репликация%20master-slave.md)
|
||||
- [Репликация master-master](Репликация%20master-master.md)
|
||||
- [Безмастерная репликация](Безмастерная%20репликация.md)
|
||||
- [Групповая репликация](Групповая%20репликация.md). Реализовано в MySQL.
|
||||
## Проблемы
|
||||
- [Отставание реплики БД](Отставание%20реплики%20БД.md)
|
||||
- [Монотонное чтение](Монотонное%20чтение.md)
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]], [[../../../meta/zero/00 DevOps|00 DevOps]], [[../../../meta/zero/00 Реляционная база данных|00 Реляционная база данных]]
|
||||
**Родитель**:: [[../../../../../source/курсы/otus/Архитектор высоких нагрузок 2019/Лекция. Репликация|Лекция. Репликация]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-03-10]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Асинхронная репликация]]
|
||||
- [[Безмастерная репликация]]
|
||||
- [[Групповая репликация]]
|
||||
- [[Монотонное чтение]]
|
||||
- [[Отставание реплики БД]]
|
||||
- [[Полу-синхронная репликация]]
|
||||
- [[Репликация master-master]]
|
||||
- [[Репликация master-slave]]
|
||||
- [[Синхронная репликация]]
|
||||
- [[Согласованное префиксное чтение]]
|
||||
- [[Репликация в MySQL]]
|
||||
- [[Репликация в PostgreSQL]]
|
||||
<!-- SerializedQuery END -->
|
38
dev/architecture/highload/Репликация.md
Normal file
38
dev/architecture/highload/Репликация.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
aliases:
|
||||
- зеркалирование
|
||||
- репликацию
|
||||
- репликации
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-05
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
linked:
|
||||
---
|
||||
Один из видов [горизонтального масштабирования](Горизонтальное%20масштабирование.md), который позволяет создать несколько копий одного узла системы.
|
||||
|
||||
**Плюсы:**
|
||||
- Помогает при падениях
|
||||
- Можно размазать нагрузку по узлам
|
||||
|
||||
**Минусы:**
|
||||
- Всегда ресурсозатратно.
|
||||
|
||||
**Виды репликации:**
|
||||
- [Репликация БД](Репликация%20БД.md)
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Горизонтальное масштабирование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-05]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Репликация БД]]
|
||||
<!-- SerializedQuery END -->
|
45
dev/architecture/highload/Синхронная репликация.md
Normal file
45
dev/architecture/highload/Синхронная репликация.md
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-07
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 Реляционная база данных|00 Реляционная база данных]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
- "[[Асинхронная репликация]]"
|
||||
- "[[Полу-синхронная репликация]]"
|
||||
---
|
||||
При получении запроса от клиента master ожидает, пока все реплики получат новые данные и подтвердят их применение у себя, и только после этого сообщает клиенту, что запрос успешно выполнен. Работает надежно, но медленно.
|
||||
|
||||
Реализовано в [PostgreSQL](../../../meta/zero/00%20PostgreSQL.md).
|
||||
|
||||
**Механизм работы**:
|
||||
- Подготовка транзакции в движке БД: Транзакция начинается на главном сервере (мастере), где собираются все изменения данных.
|
||||
- Запись транзакции в лог: Все изменения записываются в журнал транзакций, что обеспечивает возможность восстановления данных в случае сбоя.
|
||||
- Пересылка лога репликам: Журнал транзакций отправляется на все реплики для синхронного применения изменений.
|
||||
- Выполнение транзакций на репликах: Реплики применяют полученные изменения к своим копиям данных.
|
||||
- Завершение транзакции в движке БД: После успешного применения изменений на всех репликах транзакция завершается.
|
||||
- Возврат результата клиенту: Клиент получает подтверждение о завершении транзакции только после того, как изменения применены на всех репликах.
|
||||
|
||||
**Плюсы:**
|
||||
- Высокая надежность данных: Данные не теряются даже в случае сбоя одного из серверов, так как изменения применяются на всех репликах одновременно.
|
||||
- Консистентность данных: Обеспечивается консистентность данных на всех репликах, что исключает возможность получения различных результатов для одного и того же запроса.
|
||||
|
||||
**Минусы:**
|
||||
- Увеличенное время отклика: Поскольку подтверждение транзакции возвращается клиенту только после её завершения на всех репликах, время отклика увеличивается. Это может негативно сказаться на производительности системы, особенно при большом количестве реплик.
|
||||
- Высокая вероятность сбоев: С увеличением числа реплик общая вероятность сбоя возрастает, так как транзакция завершается только при успешном выполнении на всех репликах. Если хотя бы одна реплика не отвечает, транзакция не может быть завершена.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-07]]
|
||||
### Дополнительные материалы
|
||||
- [[Асинхронная репликация|Асинхронная репликация]]
|
||||
- [[Полу-синхронная репликация|Полу-синхронная репликация]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
32
dev/architecture/highload/Согласованное префиксное чтение.md
Normal file
32
dev/architecture/highload/Согласованное префиксное чтение.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-07
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Репликация БД]]"
|
||||
linked:
|
||||
---
|
||||
Ситуация, которая возникает при наличии нескольких master-ов ([[Репликация master-master]] или [[Групповая репликация]]) или при [Шардирование БД](Шардирование%20БД.md).
|
||||
|
||||
У нас есть 2 участника чата и один сторонний наблюдатель. Сначала один пользователь пишет в чат, а следом другой пользователь пишет в чат. Далее наблюдатель читает сообщения из реплики, в которую сначала пришло второе сообщение, а потом только первое.
|
||||
|
||||
![](../../../meta/files/images/Pasted%20image%2020240607212223.png)
|
||||
|
||||
**Возможные решения:**
|
||||
- Сортировка по какому-то монотонному полю.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Репликация БД]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-07]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
29
dev/architecture/highload/Старт с холодным кэшем.md
Normal file
29
dev/architecture/highload/Старт с холодным кэшем.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-18
|
||||
zero-link:
|
||||
- "[[../../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[../Кэширование|Кэширование]]"
|
||||
linked:
|
||||
---
|
||||
После аварии кэш, скорее всего будет [[Инвалидация кэша|инвалидирован]]. А в случае не персистентных хранилищ кэша не будет точно после отключения питания. Для некоторых систем подняться с не прогретым кэшом сложная задача.
|
||||
|
||||
Что может помочь:
|
||||
- Заранее напишите скрипт прогрева кэшей
|
||||
- Возвращайте нагрузку плавно
|
||||
- Помните о том, что нагрузку стоит уметь держать без кэш
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[../Кэширование|Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-18]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
40
dev/architecture/Архитектура as Code.md
Normal file
40
dev/architecture/Архитектура as Code.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
- AaC
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-21
|
||||
---
|
||||
Архитектура as Code (AaC) — это методология, при которой архитектурные решения и схемы описываются с использованием программного кода. Подход вдохновлен концепцией [[Infrastructure as Code]] (IaC), но применяется к более высокоуровневым аспектам системы, таким как взаимодействие сервисов, модули, [[Контракт взаимодействия|контракты]] и зависимости.
|
||||
|
||||
Пример: вместо создания диаграммы вручную, архитектура описывается в YAML или JSON-файле, который затем может быть интерпретирован для создания визуализации или проверки соответствия системе.
|
||||
|
||||
**Основные принципы**
|
||||
- **Декларативность.** Архитектура описывается в виде декларативного файла, который служит источником правды для всей команды.
|
||||
- **Автоматизация.** Использование кода для автоматической проверки архитектурных решений и их применения.
|
||||
- **Интеграция.** Возможность связки с CI/CD пайплайнами для проверки соответствия архитектурным стандартам.
|
||||
- **Версионность.** Все изменения архитектуры фиксируются в системе контроля версий, что позволяет отслеживать её эволюцию.
|
||||
|
||||
**Ограничения**
|
||||
- **Сложность внедрения.** Требуются опыт и компетенции команды для реализации подхода.
|
||||
- **Обучение.** Необходимо обучать специалистов работать с инструментами AaC.
|
||||
- **Необходимость дисциплины.** Без четкого подхода может возникнуть хаос в коде архитектуры.
|
||||
|
||||
**Инструменты**
|
||||
- [Structurizr](https://structurizr.com) — для описания архитектуры на основе C4-модели.
|
||||
- OpenAPI/AsyncAPI — для описания API.
|
||||
- Terraform, Pulumi — для связи архитектурного описания с инфраструктурой.
|
||||
- DSL (Domain-Specific Languages) — собственные языки для описания архитектуры.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-21]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
48
dev/architecture/Архитектурная карта.md
Normal file
48
dev/architecture/Архитектурная карта.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-26
|
||||
---
|
||||
Архитектурные карты — это **визуальное представление** системы, ее структуры, связей и компонентов. Они служат инструментом для анализа, проектирования и коммуникации, упрощая понимание системы всеми заинтересованными сторонами: разработчиками, аналитиками, архитекторами и бизнес-заказчиками.
|
||||
|
||||
Архитектурная карта может включать в себя несколько [[Архитектурная схема|архитектурных схем]].
|
||||
|
||||
**Зачем нужны архитектурные карты?**
|
||||
- **Упрощение коммуникации**. Карты выступают общим языком между командами. Например, разработчики и бизнес могут быстрее обсуждать проблемы и принимать решения, опираясь на общее визуальное представление системы.
|
||||
- **Целостное видение системы**. Архитектурные карты помогают увидеть всю систему как единое целое, включая связи между компонентами и взаимодействие с внешними системами.
|
||||
- **Выявление “слепых зон”**. Визуализация выявляет незадокументированные связи, зависимости и потенциальные уязвимости.
|
||||
- **Анализ и планирование изменений**. Карты позволяют моделировать изменения, предсказывать их влияние и оценивать риски.
|
||||
|
||||
**Виды архитектурных карт**
|
||||
- **Концептуальные карты**. Они описывают общую идею системы и ее назначение.
|
||||
- Упор на крупные блоки системы (например, модули или бизнес-процессы).
|
||||
- Подходят для общения с бизнес-заказчиками.
|
||||
- **Логические карты**. Подробное описание структуры системы: модули, компоненты и их взаимодействие.
|
||||
- Включают элементы архитектуры ПО, не зависящие от конкретной реализации.
|
||||
- Используются для проектирования и анализа решений на уровне разработки.
|
||||
- **Физические карты**. Описывают конкретную реализацию системы: сервера, базы данных, сети и прочее.
|
||||
- Применяются при развертывании и поддержке системы.
|
||||
- Подходят для DevOps, инфраструктурных инженеров и архитекторов.
|
||||
|
||||
**Как создавать и поддерживать карты?**
|
||||
- **Определите цель карты**. Например, если задача — объяснить бизнесу назначение системы, стоит сделать концептуальную карту.
|
||||
- **Используйте подходящие инструменты**. Для создания архитектурных карт популярны инструменты вроде Lucidchart, Draw.io, PlantUML и [[ArchiMate]].
|
||||
- **Обеспечьте актуальность**. Регулярно обновляйте карты при изменении системы, чтобы они оставались полезными и точными.
|
||||
- **Уточняйте уровень детализации**. Для разных целей нужны разные уровни абстракции. Например, высокоуровневый обзор для презентаций и более детальная схема для команды разработки.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-26]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Архитектурная схема]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
43
dev/architecture/Архитектурная концепция.md
Normal file
43
dev/architecture/Архитектурная концепция.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
aliases:
|
||||
- архитектурных принципов
|
||||
- архитектурный принцип
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-01
|
||||
---
|
||||
Архитектурная концепция это общая идея или принцип построения архитектуры системы или отдельного компонента системы.
|
||||
|
||||
**Цель**:
|
||||
- Определить базовые принципы, которые будут направлять разработку всей системы.
|
||||
- Решать проблемы на уровне системы, а не отдельных компонентов.
|
||||
## Классификация
|
||||
- [[Архитектурный паттерн]]
|
||||
- [[Паттерн проектирования]]
|
||||
|
||||
Прочие концепции:
|
||||
- [[Inversion of Control]]
|
||||
- [[Infrastructure as Code]]
|
||||
- [[Один клиент — один поток]]
|
||||
- [[Много клиентов — один поток]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-10-01]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Inversion of Control]]
|
||||
- [[Архитектурный паттерн]]
|
||||
- [[Большой комок грязи]]
|
||||
- [[Много клиентов — один поток]]
|
||||
- [[Один клиент — один поток]]
|
||||
- [[Паттерн проектирования]]
|
||||
- [[Infrastructure as Code]]
|
||||
<!-- SerializedQuery END -->
|
54
dev/architecture/Архитектурная схема.md
Normal file
54
dev/architecture/Архитектурная схема.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
aliases:
|
||||
- архитектурные схемы
|
||||
- архитектурных схем
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-26
|
||||
---
|
||||
Архитектурная схема — это детализированное визуальное представление структуры и функционирования системы. Она помогает понять, как устроена система, какие компоненты входят в её состав и как они взаимодействуют друг с другом.
|
||||
|
||||
Архитектурная схема позволяет уменьшить [[../../psychology/Семантический разрыв|семантический разрыв]] при технических обсуждениях.
|
||||
|
||||
**Основная цель архитектурной схемы**
|
||||
- **Технической документации** — фиксации текущего состояния системы.
|
||||
- **Разработки и тестирования** — схемы позволяют командам лучше понимать структуру системы и её компоненты.
|
||||
- **Оптимизации и масштабирования** — упрощают анализ узких мест и прогнозирование последствий изменений.
|
||||
- **Устранения ошибок** — помогают найти и исправить проблемы благодаря наглядности взаимодействий.
|
||||
|
||||
**Виды архитектурных схем**
|
||||
- **Модульная схема**. Отображает модули системы и их взаимодействия.
|
||||
- Применяется для анализа высокоуровневой структуры ПО.
|
||||
- Удобна на этапе проектирования или реструктуризации системы.
|
||||
- **Компонентная схема**. Фокусируется на более детальном описании архитектуры компонентов и их связей.
|
||||
- Используется для анализа взаимозависимостей и проектирования новых компонентов.
|
||||
- **Схема потоков данных (Data Flow Diagram)**. Показывает, как данные перемещаются между модулями и компонентами. Полезна для проектирования интеграции и анализа производительности.
|
||||
- **Инфраструктурная схема** Описывает физическую реализацию системы: сервера, сети, базы данных и т.д. Используется для DevOps и управления инфраструктурой.
|
||||
|
||||
**Основные элементы архитектурной схемы**
|
||||
- **Компоненты** — отдельные части системы, такие как модули, сервисы или базы данных.
|
||||
- **Интерфейсы** — точки взаимодействия между компонентами (например, API).
|
||||
- **Связи** — связи или зависимости между компонентами, указывающие на передачу данных или управление.
|
||||
- **Процессы и потоки данных** — движения информации внутри системы.
|
||||
|
||||
**Как создать архитектурную схему?**
|
||||
- **Определите цель**. Зачем создается схема? Для документации, обсуждения с командой или анализа системы? От цели зависит уровень детализации.
|
||||
- **Соберите информацию**. Перечислите все компоненты системы, их взаимодействия и внешние зависимости.
|
||||
- **Выберите инструмент**. Для создания схем можно использовать инструменты, такие как Draw.io, PlantUML, Lucidchart или Visio.
|
||||
- **Обеспечьте ясность**. Убедитесь, что схема легко читается, избегайте избыточной детализации. Используйте условные обозначения и комментарии.
|
||||
- **Актуализируйте схему**. При изменении системы своевременно вносите изменения в схему, чтобы она оставалась полезной.
|
||||
|
||||
Лучше всего использовать подход [[Архитектура as Code]], чтобы иметь возможность видеть эволюцию схемы.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[Архитектурная карта]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-26]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
35
dev/architecture/Архитектурный паттерн.md
Normal file
35
dev/architecture/Архитектурный паттерн.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
aliases:
|
||||
- архитектурный шаблон
|
||||
- Architectural Pattern
|
||||
- архитектурный подход
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-12-02
|
||||
---
|
||||
Архитектуры:
|
||||
- [[../../../../wiki/zero/00 Микросервисная архитектура|Микросервисная архитектура]]
|
||||
- [[Монолитная архитектура]]
|
||||
- [[Serverless|Serverless]]
|
||||
- [[Событийно-ориентированная архитектура]]
|
||||
|
||||
- [[Event Sourcing]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**:: [[Архитектурная концепция]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-12-02]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Event Sourcing]]
|
||||
- [[Serverless]]
|
||||
- [[Монолитная архитектура]]
|
||||
- [[00 Микросервисная архитектура]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
48
dev/architecture/Архитектурный слой.md
Normal file
48
dev/architecture/Архитектурный слой.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
aliases:
|
||||
- архитектурного слоя
|
||||
- слой
|
||||
- слоями
|
||||
- слоями приложения
|
||||
- архитектурными слоями
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Архитектурный слой — это уровень абстракции, который разделяет систему на части (слои), обеспечивая логическую организацию компонентов. Каждый слой отвечает за выполнение конкретных задач и взаимодействует с другими слоями через четко определённые интерфейсы.
|
||||
|
||||
Пример классической многослойной архитектуры — это разделение на уровни представления (интерфейс пользователя), бизнес-логики (основные процессы) и данных (хранение и управление информацией). Это облегчает разработку, поддержку и масштабирование системы.
|
||||
|
||||
Основные идеи использования слоёв в архитектуре:
|
||||
- **Чёткое разделение ответственности (Separation of Concerns)**: Каждый слой должен быть сосредоточен на выполнении одной задачи (например, UI, бизнес-логика, доступ к данным). Например, слой бизнес-логики не должен заниматься задачами, связанными с пользовательским интерфейсом, и наоборот. Это упрощает изменения, поддержку и тестирование.
|
||||
- **Минимизация связности между слоями**: Взаимодействие между слоями должно происходить через хорошо определённые интерфейсы или API. Это снижает зависимость слоёв друг от друга и облегчает замену или обновление слоёв.
|
||||
- **Инверсия зависимостей**: Верхние слои не должны зависеть от реализации нижних слоёв. Использование абстракций (интерфейсов) помогает избежать жестких зависимостей и улучшает тестируемость.
|
||||
- **Логика не должна просачиваться между слоями**: Каждая бизнес-логика или специфическая реализация должны быть строго в том слое, к которому они относятся, чтобы избежать смешивания задач.
|
||||
- **Использование принципов** [[SOLID|SOLID]]: Следование принципам объектно-ориентированного проектирования, таким как единая ответственность ([[Single Responsibility Principle|Single Responsibility]]) и открытость/закрытость ([[Open Closed Principle|Open/Closed Principle]]), помогает создать гибкие и легко расширяемые архитектуры.
|
||||
|
||||
Преимущества:
|
||||
- **Модульность**: Легче модифицировать или заменять части системы без влияния на весь код.
|
||||
- **Повторное использование**: Логика, размещённая в одном слое, может быть использована различными частями системы.
|
||||
- **Упрощение тестирования**: Благодаря разделению задач, тестирование может быть сосредоточено на отдельных слоях.
|
||||
|
||||
Частые ошибки:
|
||||
- **Слои как простая формальность**: Иногда разработчики создают слои, но не используют их как абстракции. Это приводит к тому, что слои теряют свой смысл и становятся перегруженными логикой, не относящейся к их роли.
|
||||
- **Слишком много слоёв**: Перегруженная многослойная архитектура может стать трудной для понимания и сопровождения. Использование слишком большого количества слоёв увеличивает сложность без явных преимуществ.
|
||||
- [[Необоснованное использование ORM в слое бизнес-логики]]: Когда объекты из слоя данных (например, сущности ORM) напрямую используются в бизнес-слое, это нарушает принцип [[Инкапсуляция|инкапсуляции]] и ведёт к избыточным зависимостям.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
22
dev/architecture/Асинхронное программирование.md
Normal file
22
dev/architecture/Асинхронное программирование.md
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-08
|
||||
---
|
||||
Асинхронность позволяет задачам выполняться в фоновом режиме, не блокируя основной поток программы, тем самым реализуя [[Concurrency]]. В синхронных операциях задача должна завершиться, прежде чем начнётся следующая, тогда как асинхронные задачи могут выполняться независимо, что особенно полезно для [[../architecture/Блокирующий вызов|блокирующих операций]].
|
||||
|
||||
Асинхронное программирование делает программы более отзывчивыми, позволяя основному потоку продолжать выполнение других задач, пока асинхронная операция выполняется. После завершения такой операции программа может вернуться к её результатам. В Java для этого используется класс `CompletableFuture`.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[../Парадигма разработки|Парадигма разработки]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-10-08]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
32
dev/architecture/Бизнес-логика.md
Normal file
32
dev/architecture/Бизнес-логика.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
- бизнес-логике
|
||||
- бизнес-логику
|
||||
- бизнес-логики
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-10-16
|
||||
---
|
||||
Бизнес-логика — это совокупность правил, процессов и операций, которые определяют, как бизнес-приложение или [[Информационная система|система]] обрабатывает данные и выполняет свои функции в соответствии с требованиями бизнеса. Она описывает последовательность действий, условия и правила, которые управляют поведением системы при выполнении бизнес-задач.
|
||||
|
||||
Основные аспекты бизнес-логики:
|
||||
|
||||
- **Правила и ограничения**: Определяют, что можно и нельзя делать в системе.
|
||||
- **Процессы и операции**: Описывают последовательность шагов для достижения определенного результата.
|
||||
- **Валидация данных**: Проверяет корректность и целостность вводимых или обрабатываемых данных.
|
||||
- **Взаимодействие с данными**: Определяет, как данные создаются, читаются, обновляются и удаляются.
|
||||
|
||||
Бизнес-логика отделена от пользовательского интерфейса и технической инфраструктуры, что позволяет легко вносить изменения в систему при изменении бизнес-требований без необходимости переписывать всю программу.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-10-16]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
43
dev/architecture/Блокирующий вызов.md
Normal file
43
dev/architecture/Блокирующий вызов.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
aliases:
|
||||
- блокирующие операции
|
||||
- блокирующая операция
|
||||
- блокирующий вызов
|
||||
- блокирующий ввод-вывод
|
||||
- блокирующего
|
||||
- блокирующей операции
|
||||
- блокирующих операций
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-01-28
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
linked:
|
||||
- "[[Блокирующий вызов]]"
|
||||
---
|
||||
Блокирующий вызов блокирует [поток](../fundamental/Поток%20процесса%20ОС.md) до того момента, как будут-получены данные. Во время блокировки [процесс](../fundamental/Процесс%20ОС.md) не потребляет процессорное время, но потребляет память. Например, для выполнения запроса к БД из пула потоков берётся поток, далее он ожидает, пока БД выполнит запрос и вернёт результат.
|
||||
|
||||
Это одна из основных проблем императивного программирования. ==Если вычисление результата займёт 5 минут, то поток всё это время будет недоступен для других операций.== Это может привести к снижению производительности сервиса, особенно если многие потоки будут блокироваться в ожидании завершения долго выполняющихся запросов к базе данных. В какой-то момент у вас просто могут закончиться потоки в пуле, и обработка новых запросов просто остановится.
|
||||
|
||||
![](../../meta/files/images/Pasted%20image%2020240319200211.png)
|
||||
|
||||
## Почему простаивание потока — это проблема?
|
||||
Каждый поток нуждается в памяти для хранения своего стека вызовов и других связанных с ним структур данных. ==Когда поток простаивает, он продолжает потреблять ресурсы для поддержания своего состояния.==
|
||||
|
||||
Кроме того, процессорное время, которое выделяется неработающим потокам, могло бы быть использовано для других задач. Если большое количество потоков простаивает, это может привести к увеличению загрузки процессора и снижению производительности, так как операционная система будет тратить больше времени на [[../fundamental/Переключение контекста|переключение между потоками]].
|
||||
|
||||
![](../../meta/files/images/Pasted%20image%2020240413205842.png)
|
||||
|
||||
Если посмотреть на соотношение скорости [[../fundamental/Центральный процессор|процессора]] и возможности сетевых соединений, то отличия – на пару порядков. Например, на этом слайде сжатие 1 Кб данных занимает 3 мкс, в то время как round trip в одну сторону даже внутри одного дата-центра – это уже 0,5 мс. Любое сетевое взаимодействие, которое нужно бэкенду (например, отправка запроса в БД), потребует, как минимум 2х round trip-ов и по сравнению с тем процессорным временем, которое он тратит на обработку данных, – это совершенно незначительно. Большую часть времени обработки запроса [бэкенд](Бэкенд.md) ничего не делает, просто ждет.
|
||||
## Заметки
|
||||
- Чтение с диска в linux может быть только блокирующим.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-01-28]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
40
dev/architecture/Большой комок грязи.md
Normal file
40
dev/architecture/Большой комок грязи.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
aliases:
|
||||
- Big ball of mud
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-04-04
|
||||
---
|
||||
**Большой комок грязи** (Big Ball of Mud) — это термин, описывающий программную систему с нераспознаваемой архитектурой. Такие системы не имеют чёткой структуры, их сложно поддерживать и развивать.
|
||||
|
||||
Ключевым последствием появления большой системы с неясной архитектурой является значительное замедление разработки. Это связано с тем, что:
|
||||
- **Сложность понимания кода**: Новые разработчики вынуждены тратить много времени на разбор устаревших и запутанных участков.
|
||||
- **Повышенная вероятность ошибок**: Внесение изменений в одну часть системы часто непредсказуемо влияет на другие.
|
||||
- **Снижение гибкости**: Система становится менее адаптируемой к новым требованиям бизнеса.
|
||||
|
||||
В результате работа над новыми функциями или изменениями превращается в долгий и трудозатратный процесс.
|
||||
|
||||
Одним из ярких примеров большого комка грязи является [[Распределенный монолит|распределённый монолит]]. Это система, которая внешне представлена как набор микросервисов, но на практике они сильно связаны между собой. Такая архитектура унаследовала все проблемы монолитных систем, добавив к ним сложности, связанные с распределёнными взаимодействиями.
|
||||
|
||||
**Почему возникают большие комки грязи?**
|
||||
- **Давление сроков**: Когда бизнес требует быстрых результатов, разработчики часто жертвуют качеством архитектуры ради скорости.
|
||||
- **Отсутствие единого видения**: Если в команде нет согласованного подхода к архитектурным решениям, код становится хаотичным.
|
||||
- **Текучка кадров**: Новые разработчики могут не понимать оригинального замысла системы и добавлять решения, противоречащие существующей структуре.
|
||||
- **Рост системы**: По мере увеличения объёма кода его поддержка становится всё сложнее, особенно если архитектура изначально была слабой.
|
||||
|
||||
**Как избежать появления большого комка грязи?**
|
||||
- **Создавать архитектурные стандарты**: Документировать основные принципы построения системы и регулярно их пересматривать.
|
||||
- [[../efficiency/Рефакторинг кода|Рефакторинг]] на ранних этапах: Регулярно пересматривать код и устранять хаотичные или устаревшие участки.
|
||||
- **Обучение команды**: Убедиться, что все разработчики понимают выбранный подход к проектированию.
|
||||
- **Разумное планирование сроков**: Учитывать время, необходимое для создания качественной архитектуры, вместо того чтобы ориентироваться только на скорость.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[Архитектурная концепция]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-04-04]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
55
dev/architecture/Брокер сообщений.md
Normal file
55
dev/architecture/Брокер сообщений.md
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
aliases:
|
||||
- брокерами сообщений
|
||||
- очереди сообщений
|
||||
- брокеры сообщений
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-07-02
|
||||
---
|
||||
Брокеры способны обрабатывать 10000+ сообщений в секунду
|
||||
|
||||
Для чего используются:
|
||||
- Межсервисное общение
|
||||
- Асинхронная запись логов приложения
|
||||
- Тяжелые ассинхронные задачи
|
||||
|
||||
Требования к брокерам:
|
||||
- гарантия доставки сообщений
|
||||
- at least once delivery. Гарантируется, что наше сообщение получит хотя бы один клиент.
|
||||
- at most once delivery. Не гарантирует доставку.
|
||||
- exactly once delivery. Гарантируется, что только один получатель получит сообщение.
|
||||
- порядок передачи сообщений
|
||||
- управление размером очереди
|
||||
- зеркалирование
|
||||
- масштабирование
|
||||
|
||||
**Терминология:**
|
||||
- Брокер - это приложение, которое реализует модель [AMQP](Advanced%20Message%20Queuing%20Protocol.md). Которое принимает соединения клиентов для маршрутизации сообщений и т.п.
|
||||
- Сообщение (message) - это единица передаваемых данных. Включая мета-информацию.
|
||||
- Потребитель (consumer) - приложение, которое читает сообщения из очереди.
|
||||
- Производитель (producer) - приложение, которое отправляет сообщения в брокер.
|
||||
|
||||
Примеры реализаций брокеров сообщений:
|
||||
- [00 RabbitMQ](00%20RabbitMQ.md)
|
||||
- [00 Kafka](00%20Kafka.md)
|
||||
- [[../../../../_inbox/NATS|NATS]]
|
||||
- [00 Redis](../../meta/zero/00%20Redis.md) (pub/sub, stream)
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103222905.png]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-07-02]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[00 RabbitMQ]]
|
||||
- [[Advanced Message Queuing Protocol]]
|
||||
- [[NATS]]
|
||||
<!-- SerializedQuery END -->
|
32
dev/architecture/Бэкенд.md
Normal file
32
dev/architecture/Бэкенд.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
- бэкенде
|
||||
- backend
|
||||
- бэкенда
|
||||
- бэкенду
|
||||
- Приложение
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-04-13
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Бэкенд – один из самых больших бездельников в веб-архитектуре. У него есть всего 2 задачи:
|
||||
- Сетевой ввод-вывод. Обычно сводится к общению с [Rеverse proxy](Rеverse%20proxy.md) – прием http-запроса и ответ на него, и со всевозможными сервисами, которые хранят данные – это могут быть БД, очереди, memcaсhed и т.п.
|
||||
- Склеивание строк – сериализовать данные в JSON, сформировать шаблон на основе html, посчитать sh1 или md5? выполнить сжатие данных.
|
||||
|
||||
А что такое [[бизнес-логика]] в бэкенде? Это проверки наподобие "если значение переменных больше 3-х, делай это", "если пользователь авторизован, покажи одно, если не авторизован – покажи другое". Бывают, конечно, отдельные задачи, например, по изменению размера картинки, преобразования видео, но чаще всего такие задачи решаются вне бэкенда с использованием очередей, воркеров и т.д.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-04-13]]
|
||||
### Дополнительные материалы
|
||||
- [[Блокирующий вызов|Блокирующий вызов]]
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
32
dev/architecture/Высокоуровневые модули.md
Normal file
32
dev/architecture/Высокоуровневые модули.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
- Высокоуровневые компоненты
|
||||
- высокоуровневых модулей
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-23
|
||||
---
|
||||
**Высокоуровневые модули** — это компоненты [[Информационная система|системы]], которые реализуют [[Бизнес-логика|бизнес-логику]] или основные функции приложения. Они определяют, что делает система, и взаимодействуют с абстрактными концепциями. Такие модули управляют процессами, принимают решения, организуют взаимодействие между компонентами.
|
||||
|
||||
**Примеры:**
|
||||
- Контроллеры в архитектуре [[MVC]], управляющие потоком данных и действиями пользователя.
|
||||
- Модуль, обрабатывающий заказы в интернет-магазине
|
||||
- Система отчетности, объединяющая данные из разных источников.
|
||||
|
||||
**Особенности:**
|
||||
|
||||
- Высокоуровневые модули зависят от абстракций, а не от деталей реализации.
|
||||
- Их изменения определяются требованиями бизнеса, а не техническими деталями [[Низкоуровневые модули|низкоуровневых модулей]].
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-23]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
- [[Низкоуровневые модули]]
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
53
dev/architecture/Декомпозиция на микросервисы.md
Normal file
53
dev/architecture/Декомпозиция на микросервисы.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
aliases:
|
||||
- размер микросервиса
|
||||
- гранулярность микросервисов
|
||||
- декомпозиции на микросервисы
|
||||
- декомпозиции системы
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-24
|
||||
---
|
||||
Гранулярность микросервисов — это один из ключевых вопросов при проектировании распределённых систем. От неё зависит многое: гибкость архитектуры, масштабируемость, время разработки и стоимость поддержки. Однако определение оптимального размера каждого сервиса — задача не из лёгких.
|
||||
|
||||
Гранулярность в контексте микросервисной архитектуры — это уровень разделения логики системы на отдельные сервисы. Слишком крупные сервисы рискуют превратиться в [[Монолитная архитектура|монолиты]], теряя преимущества микросервисного подхода. Слишком мелкие, наоборот, создают сложности в управлении и коммуникации, что приводит к росту накладных расходов.
|
||||
|
||||
Основной вызов заключается в нахождении оптимального баланса. Микросервисы должны быть достаточно маленькими, чтобы можно было легко управлять их жизненным циклом и развивать независимо от других компонентов. В то же время они должны оставаться самодостаточными и функциональными.
|
||||
|
||||
**Принципы определения гранулярности**
|
||||
1. **Бизнес-ориентированность**. Микросервис должен отражать конкретный бизнес-процесс или функциональную область. Если сервис охватывает слишком много бизнес-логики, его стоит разделить на более специализированные компоненты. Например, в системе для интернет-магазина логика управления заказами и обработка платежей должны быть разделены на два сервиса.
|
||||
2. Правило [[Single Responsibility Principle|единственной ответственности]]. Каждый микросервис должен выполнять одну задачу и делать это хорошо. Если сервис отвечает за множество разнородных функций, вероятно, его стоит разделить. Например, сервис, отвечающий и за авторизацию, и за управление профилем пользователя, нарушает принцип единственной ответственности.
|
||||
3. Слабая [[связанность]] и высокая [[Связность|связность]]. Сервисы должны быть слабо связаны друг с другом, чтобы изменения в одном не требовали изменений в других. В то же время внутренняя логика сервиса должна быть максимально когерентной — все функции должны быть тесно связаны и иметь смысл как единое целое.
|
||||
4. **Коммуникационные накладные расходы**. При излишнем разделении микросервисов коммуникация между ними может стать значительной проблемой. Каждое взаимодействие требует сетевых запросов, которые увеличивают время отклика и усложняют тестирование. Избежать этого можно, объединяя сервисы, которые часто взаимодействуют друг с другом.
|
||||
5. **Масштабируемость и независимость деплоя**. Один из ключевых факторов в пользу микросервисов — возможность масштабировать и развертывать сервисы независимо друг от друга. При этом важно помнить, что слишком мелкие микросервисы могут превратиться в головную боль для команды DevOps из-за увеличения количества деплоя и инфраструктурных задач.
|
||||
|
||||
**Подходы к выбору гранулярности**
|
||||
- Разбиение по [[Доменная область|доменным областям]]. Этот подход предполагает разделение микросервисов по бизнес-доменам. Например, в системе для электронной коммерции могут существовать отдельные сервисы для управления каталогом товаров, работы с корзиной и обработкой платежей.
|
||||
- **Использование событий**. [[Событийно-ориентированная архитектура|Событийная архитектура]] позволяет разделять микросервисы на основе того, как данные движутся через систему. Это помогает уменьшить связанность, так как каждый сервис реагирует только на те события, которые ему необходимы.
|
||||
- **Практика "Strangler Fig"**. Этот метод подразумевает постепенное выделение функциональности из монолита в микросервисы. Это помогает определить оптимальную гранулярность, анализируя, какие части системы требуют частых изменений и могут быть разделены без излишних коммуникационных накладных расходов.
|
||||
|
||||
**Ошибки, которых следует избегать**
|
||||
1. **Слишком крупные сервисы (микромонолиты)**. Они теряют преимущество независимости и приводят к тому, что разработчики вновь оказываются в рамках монолита, но с более сложной архитектурой деплоя и управления.
|
||||
2. **Излишняя гранулярность**. Чрезмерное разделение приводит к лавине коммуникаций и делает систему неуправляемой. Это может также вызвать рост сложности в управлении транзакциями и согласованностью данных.
|
||||
3. **Игнорирование бизнес-логики**. Определение границ микросервисов только на основе технических аспектов, без учёта бизнес-логики, приводит к нарушению когезии и снижению эффективности разработки.
|
||||
|
||||
**Практические рекомендации**
|
||||
- **Начинайте с более крупных сервисов** и постепенно выделяйте их части, когда возникает потребность в независимом развитии и деплое. Это поможет избежать излишней сложности на начальных этапах.
|
||||
- **Анализируйте связи между сервисами**. Регулярный анализ зависимостей и коммуникационных потоков поможет понять, не стали ли отдельные сервисы слишком тесно связаны и не следует ли их объединить.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
|
||||
**Родитель**:: [[Микросервис]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-24]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Объединение данных из разных микросервисов]]
|
||||
<!-- SerializedQuery END -->
|
||||
|
34
dev/architecture/Доменная область.md
Normal file
34
dev/architecture/Доменная область.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
aliases:
|
||||
- домена
|
||||
- доменных областях
|
||||
- доменным областям
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
zero-link:
|
||||
- "[[../garden/ru/meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
**Домен** — это предметная область, в которой работает ваша [[../../../../_inbox/Информационная система|система]]. Это набор знаний, правил, процессов и объектов, которые описывают конкретную сферу деятельности. Домены могут быть разными в зависимости от сферы бизнеса, например: финансы, медицина, логистика, образование и т.д.
|
||||
|
||||
Другими словами, домен — это всё, что касается бизнес-логики, которой занимается [[../../../../_inbox/Информационная система|система]]. Разработчики, создающие приложения, должны глубоко понимать предметную область, чтобы адекватно моделировать её в коде.
|
||||
|
||||
> [!EXAMPLE] Пример домена
|
||||
> Для интернет-магазина домен будет включать такие элементы, как товары, заказы, корзина, покупатели, процесс оплаты и доставки. Все эти сущности и их взаимодействия составляют домен электронной коммерции.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Модель]]
|
||||
<!-- SerializedQuery END -->
|
56
dev/architecture/Зависимости микросервисов.md
Normal file
56
dev/architecture/Зависимости микросервисов.md
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
aliases:
|
||||
- связи микросервисов
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-26
|
||||
---
|
||||
В [[../../../../wiki/zero/00 Микросервисная архитектура|микросервисной архитектуре]] каждый [[Микросервис|сервис]] имеет зависимости, которые можно разделить на **входящие** и **исходящие**:
|
||||
- **Входящие зависимости** — это другие сервисы или клиенты, которые полагаются на данный сервис для выполнения своих задач.
|
||||
- **Исходящие зависимости** — это внешние системы или микросервисы, от которых данный сервис зависит для выполнения своих функций.
|
||||
## Входящие зависимости
|
||||
Сервисы с высокой входящей зависимостью обычно выполняют функции, на которых завязаны многие другие компоненты. Отказ такого сервиса может привести к масштабным сбоям, поэтому требуется масштабируемость, мониторинг и резервирование.
|
||||
|
||||
Чем больше входящих зависимостей, тем выше вероятность перегрузки сервиса, особенно в моменты пиковых запросов. Например, сервис авторизации, на который завязаны все остальные микросервисы.
|
||||
## Исходящие зависимости
|
||||
Сервисы с множеством исходящих зависимостей сильно зависят от доступности и стабильности внешних систем.
|
||||
|
||||
Чем больше исходящих зависимостей, тем сложнее проводить изолированные тесты сервиса. Для таких случаев требуются mock-объекты или тестовые среды.
|
||||
|
||||
Высокое число исходящих зависимостей может замедлять работу сервиса из-за сетевых задержек, ограничения пропускной способности или API-лимитов.
|
||||
## Типы микросервисов на основе зависимостей
|
||||
- **Центральные (Hub)**
|
||||
- Много входящих зависимостей, мало исходящих.
|
||||
- Выполняют ключевые функции, от которых зависят другие.
|
||||
- Пример: [[API Gateway]] или сервис аутентификации.
|
||||
- **Агрегаторы**
|
||||
- Много исходящих зависимостей, среднее число входящих.
|
||||
- Сбор и обработка данных из множества источников.
|
||||
- Пример: сервис аналитики или отчётности.
|
||||
- **Специализированные (Leaf)**
|
||||
- Мало входящих и исходящих зависимостей.
|
||||
- Выполняют автономные задачи, минимально влияя на другие части системы.
|
||||
- Пример: сервис генерации отчетов.
|
||||
- **Мосты (Bridge)**
|
||||
- Баланс между входящими и исходящими зависимостями.
|
||||
- Соединяют разные домены или внешние API с внутренними сервисами.
|
||||
- Пример: сервис интеграции с внешней платежной системой.
|
||||
## Рекомендации
|
||||
- **Минимизируйте исходящие зависимости**. Ограничьте количество внешних систем, от которых зависит сервис. Агрегируйте зависимости, чтобы уменьшить количество прямых связей.
|
||||
- **Делайте отказоустойчивые сервисы с высокой входящей зависимостью**. Используйте [[кэширование]], [[highload/Балансировка нагрузки|балансировщики нагрузки]] и [[highload/Горизонтальное масштабирование|горизонтальное масштабирование]], чтобы снизить риски.
|
||||
- **Используйте асинхронные коммуникации**. Асинхронные подходы (например, через [[Брокер сообщений|брокеры сообщений]]) помогают уменьшить плотность зависимостей и снизить нагрузку.
|
||||
- **Мониторьте зависимости**. Отслеживайте состояние входящих и исходящих зависимостей с помощью [[Архитектурная схема|архитектурных схем]], чтобы своевременно выявлять узкие места и проблемы.
|
||||
- **Сегментируйте систему** Разделение архитектуры на домены помогает уменьшить плотность зависимостей и сделать систему более управляемой.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../../../wiki/zero/00 Микросервисная архитектура|00 Микросервисная архитектура]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-26]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
|
35
dev/architecture/Идемпотентность.md
Normal file
35
dev/architecture/Идемпотентность.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
aliases:
|
||||
- идемпотентны
|
||||
- идемпотентной
|
||||
- идемпотентности
|
||||
- идемпотентную
|
||||
- идемпотентные
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-11
|
||||
---
|
||||
Идемпотентность — это свойство операции, при котором многократное выполнение этой операции с одинаковыми входными данными не изменяет результат после первого выполнения. Иными словами, независимо от того, сколько раз вы выполните операцию, итог будет одним и тем же.
|
||||
|
||||
Примером идемпотентной операции может быть запрос на установку значения, например, «установить цену товара в 100». Если отправить этот запрос несколько раз, цена останется 100, и результат не изменится. В противоположность этому, операция «увеличить цену на 10» не является идемпотентной, так как каждое выполнение увеличивает цену, и результат меняется.
|
||||
|
||||
Идемпотентность позволяет системе быть устойчивой к ошибкам и повторам — если запрос случайно повторится, это не приведет к нежелательным изменениям.
|
||||
|
||||
**Примеры реализации:**
|
||||
- [[highload/Идемпотентность на базе уникального идентификатора|Идемпотентность на базе уникального идентификатора]]
|
||||
- Логика приложения устроена таким образом, что выполнение запроса с одними и теми же параметрами всегда приводит к одному и тому же результату.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-11]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[Идемпотентность на базе уникального идентификатора]]
|
||||
<!-- SerializedQuery END -->
|
44
dev/architecture/Избыточность данных.md
Normal file
44
dev/architecture/Избыточность данных.md
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-11-24
|
||||
---
|
||||
В [[../../meta/zero/00 HighLoad|высоконагруженных системах]] часто возникает необходимость хранить одни и те же данные в разных формах, чтобы оптимизировать работу различных частей системы. Это один из архитектурных [[Паттерн проектирования|паттернов]], который позволяет справиться с разными требованиями к доступу и обработке данных. Избыточность данных может быть полезной для повышения производительности и удобства работы с различными типами запросов.
|
||||
|
||||
Представим ситуацию, когда система хранит переписку между пользователями. Допустим, эта переписка отображается только двум участникам, и в интерфейсе показывается сразу вся история общения. В этом случае данные можно хранить в одном месте — например, даже в виде файла, который легко доступен для обоих пользователей.
|
||||
|
||||
Но что если нам нужно вывести список всех переписок пользователя с отображением только последнего сообщения каждой из них? Хранение всей переписки в одном файле становится неудобным, так как для получения последнего сообщения нам нужно будет прочитать все файлы и выбрать необходимую информацию, что занимает много времени и ресурсов.
|
||||
|
||||
Правильное решение в такой ситуации — ввести избыточность. Это означает, что вместо попытки хранить все данные в одном месте, необходимо создавать дополнительные структуры данных, которые оптимизированы под разные сценарии использования.
|
||||
|
||||
В случае с перепиской можно хранить данные следующим образом:
|
||||
1. **Основное хранилище для переписок**. Вся история переписки между двумя пользователями хранится в одном месте, что позволяет удобно отображать её целиком, когда это необходимо.
|
||||
2. **Индекс с последними сообщениями**. Дополнительно создаётся индекс, в котором хранятся только идентификаторы переписок и последние сообщения из каждой из них. Это позволяет быстро получать список переписок с последними сообщениями для отображения на экране.
|
||||
|
||||
Преимущества избыточности данных
|
||||
1. **Оптимизация под разные схемы доступа**. Хранение данных в разных формах позволяет оптимизировать производительность системы под различные сценарии использования. Например, быстрый доступ к последним сообщениям, не читая всю историю переписки.
|
||||
2. **Увеличение скорости работы**. Избыточность помогает сократить количество операций чтения и уменьшить время выполнения запросов. В случае переписки пользователю не нужно ждать, пока система обработает весь массив данных для получения последних сообщений.
|
||||
3. **Повышение отказоустойчивости**. Хранение данных в нескольких местах и формах также помогает повысить устойчивость к сбоям. В случае потери одного источника данных, другой может частично компенсировать потерю информации.
|
||||
|
||||
Недостатки избыточности данных
|
||||
1. **Сложность синхронизации**. Поддержание согласованности между несколькими копиями данных — сложная задача. Необходимо следить за тем, чтобы все изменения, внесённые в одну копию, корректно синхронизировались с другими копиями.
|
||||
2. **Увеличение объёма хранилища**. Хранение данных в нескольких формах требует больше места в хранилище. Для высоконагруженных систем с большими объёмами данных это может стать значительным фактором.
|
||||
|
||||
Лучшие практики для работы с избыточностью данных
|
||||
1. **Продуманная архитектура синхронизации**. Используйте [[Событийно-ориентированная архитектура|событийную архитектуру]], чтобы поддерживать согласованность данных. Например, при добавлении нового сообщения можно отправить событие, которое обновит индекс последних сообщений.
|
||||
2. **Оценка необходимости избыточности**. Вводите избыточность только там, где это действительно необходимо для повышения производительности или удобства работы. Не стоит избыточно усложнять систему там, где этого можно избежать.
|
||||
3. **Мониторинг консистентности**. Внедряйте механизмы проверки и восстановления консистентности данных между копиями. Это поможет вовремя обнаружить и устранить расхождения.
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-11-24]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
62
dev/architecture/Инкапсуляция.md
Normal file
62
dev/architecture/Инкапсуляция.md
Normal file
@ -0,0 +1,62 @@
|
||||
---
|
||||
aliases:
|
||||
- инкапсуляцию
|
||||
- инкапсуляции
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
parents:
|
||||
- "[[../garden/ru/dev/architecture/ООП|ООП]]"
|
||||
linked:
|
||||
---
|
||||
Инкапсуляция — один из ключевых принципов [[ООП|объектно-ориентированного программирования]] (ООП), который обеспечивает контроль доступа к данным и методам объекта, скрывая внутреннюю реализацию и предоставляя только необходимые интерфейсы для взаимодействия с внешним миром.
|
||||
|
||||
Основные идеи инкапсуляции:
|
||||
- **Сокрытие данных**: Внутренние детали реализации объекта, такие как его состояние или внутренние методы, не должны быть доступны напрямую из внешнего кода. Это позволяет избежать прямого изменения данных объекта извне и защищает его от некорректного использования.
|
||||
- **Чёткие интерфейсы**: Объект предоставляет только те методы и свойства, которые необходимы для работы с ним, скрывая всю сложную внутреннюю логику. Это упрощает работу с объектом и делает его использование безопасным.
|
||||
- **Управляемое изменение состояния**: Изменение состояния объекта происходит через методы, которые контролируют корректность этих изменений и могут проводить валидацию, логику или вызовы других методов.
|
||||
|
||||
Частые ошибки:
|
||||
- **Избыточная доступность**: Если данные и методы не скрыты должным образом, это приводит к увеличению связности компонентов и нарушению принципа инкапсуляции.
|
||||
- **Смешивание ответственности**: Когда внутренние данные объекта предоставляются другим компонентам, появляется риск того, что ответственность за управление состоянием будет распределена между разными частями системы.
|
||||
|
||||
## Пример инкапсуляции
|
||||
Представьте, что у вас есть объект `BankAccount`, который хранит баланс пользователя. Чтобы обеспечить безопасность, прямой доступ к балансу невозможен. Вместо этого объект предоставляет методы `deposit()` и `withdraw()`, которые корректно изменяют баланс и проверяют возможность транзакции:
|
||||
|
||||
```java
|
||||
public class BankAccount {
|
||||
private double balance;
|
||||
|
||||
public void deposit(double amount) {
|
||||
if (amount > 0) {
|
||||
balance += amount;
|
||||
}
|
||||
}
|
||||
|
||||
public void withdraw(double amount) {
|
||||
if (amount > 0 && balance >= amount) {
|
||||
balance -= amount;
|
||||
}
|
||||
}
|
||||
|
||||
public double getBalance() {
|
||||
return balance;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Таким образом, инкапсуляция помогает управлять состоянием объекта, делая его использование безопасным и устойчивым к ошибкам.
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||||
**Родитель**:: [[ООП]]
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
46
dev/architecture/Контракт взаимодействия.md
Normal file
46
dev/architecture/Контракт взаимодействия.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
aliases:
|
||||
- Контракты
|
||||
- контракт
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date: 2024-09-27
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]"
|
||||
- "[[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]"
|
||||
---
|
||||
В контексте разработки программного обеспечения **контракт** — это соглашение или набор правил, определяющий, как различные части системы (например, компоненты, классы или модули) взаимодействуют друг с другом. Контракт описывает обязанности и ожидания каждой из сторон (поставщика и потребителя), гарантируя, что при соблюдении этих условий взаимодействие будет корректным и предсказуемым.
|
||||
|
||||
Основные элементы контракта:
|
||||
- **Предусловия**: Условия, которые должны быть выполнены перед вызовом метода или началом взаимодействия. Например, входные данные метода должны быть корректными, а ресурс должен быть доступен.
|
||||
- **Постусловия**: Результаты, которые гарантируются после выполнения метода или операции, если предусловия были выполнены. Это может включать возвращаемое значение метода или состояние объекта после вызова.
|
||||
- **Инварианты**: Условия, которые остаются неизменными в течение жизни объекта. Например, допустимые диапазоны значений переменных или непротиворечивость состояния системы.
|
||||
## Примеры контрактов
|
||||
**Контракт в объектно-ориентированном программировании**: В [[ООП|ООП]] контракт может выражаться через интерфейсы или абстрактные классы, которые определяют набор методов, обязательных для реализации. Это позволяет программным компонентам общаться на основе общих соглашений, не зная конкретную реализацию.
|
||||
|
||||
Пример интерфейса как контракта:
|
||||
```java
|
||||
public interface Shape {
|
||||
double calculateArea(); // контракт: любой класс, реализующий Shape, обязан иметь этот метод
|
||||
}
|
||||
```
|
||||
|
||||
**Контракт API**: В контексте API контрактом является описание того, как клиент может взаимодействовать с API. Это включает в себя форматы запросов и ответов, методы HTTP, параметры, типы данных, кодировки и обработку ошибок.
|
||||
|
||||
Пример контракта [[Representation State Transfer|REST]] API:
|
||||
- Метод: `POST /users`
|
||||
- Входные данные: JSON-объект с полями `name` и `email`
|
||||
- Ответ: код 201 (Created) и объект пользователя
|
||||
- Ошибки: код 400 (Bad Request) при некорректных данных
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]], [[../../meta/zero/00 Архитектура ИС|00 Архитектура ИС]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Создана**:: [[2024-09-27]]
|
||||
**Автор**::
|
||||
### Дополнительные материалы
|
||||
-
|
||||
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
33
dev/architecture/Кэширование в приложении.md
Normal file
33
dev/architecture/Кэширование в приложении.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
- "[[Кэширование]]"
|
||||
---
|
||||
Поход в базу данных может быть достаточно дорогим, в этом случае имеет смысл сохранять данные в кэш. Ускорить сложные запросы может кэширование: мы помещаем результат вычислений в некоторое хранилище, которое обладает отличными характеристиками по времени доступа к информации. Теперь вместо обращений к медленным, сложным и тяжелым backend’ам нам достаточно выполнить запрос к быстрому кэшу.
|
||||
|
||||
Самые распространенные варианты хранения:
|
||||
- Внутри сервиса. Хранение в ОЗУ
|
||||
- За сервисом
|
||||
- [Memcached](Memcached.md)
|
||||
- [[../../meta/zero/00 Redis|Redis]]
|
||||
|
||||
![](../../meta/files/images/Pasted%20image%2020240617184722.png)
|
||||
|
||||
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**:: [[Кэширование]]
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-06-17]]
|
||||
### Дополнительные материалы
|
||||
-
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
78
dev/architecture/Кэширование.md
Normal file
78
dev/architecture/Кэширование.md
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
aliases:
|
||||
- кэш
|
||||
- кэша
|
||||
- кеш
|
||||
tags:
|
||||
- maturity/🌱
|
||||
date:
|
||||
- - 2024-05-24
|
||||
zero-link:
|
||||
- "[[../../meta/zero/00 HighLoad|00 HighLoad]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Для каждого ресурса критичной для пользователя является такая характеристика, как [[Latency|время отклика]] сервера. Увеличение времени отклика сервера приводит к оттоку посетителей. Следовательно, необходимо минимизировать [[Latency|время отклика]]: для этого необходимо уменьшать время, требуемое на формирование ответа пользователю, при этом для формирования ответа пользователю необходимо получить данные из каких-то внешних ресурсов ([Бэкенд](Бэкенд.md)).
|
||||
|
||||
|
||||
> [!TIP] Работа без кэша
|
||||
> Хорошая система должна уметь выдерживать нагрузку и без кэша. Задача кэша ускорить ответ, а не держать нагрузку.
|
||||
|
||||
Сами данные можно разделить на несколько категорий:
|
||||
- **Можно потерять**. К этой категории относятся кэши выборок из базы данных. Потеря таких ключей не так страшна, потому что мы можем легко восстановить их значения, обратившись заново к backend’у. Однако частые потери кэшей приводят к излишним обращениям к БД.
|
||||
- **Не хотелось бы потерять**. Здесь можно упомянуть счетчики посетителей сайта, просмотров ресурсов и т.п. Хоть и восстановить эти значения иногда напрямую невозможно, но значения этих ключей имеют ограниченный по времени смысл: через несколько минут их значение уже неактуально, и будет рассчитано заново.
|
||||
- **Совсем не должны терять**. Кэш удобен для хранения сессий пользователей. Однако содержимое сессий не хотелось бы терять никогда – иначе пользователей на сайте будет «разлогинивать». Как попытаться избежать? Можно кластеризовать систему кэширования, так вероятность потери снижается.
|
||||
|
||||
==Системы используемые для кэширования обычно не являются надежными, так что не следует хранить только там какие-то важные данные.==
|
||||
## Уровни кэширования
|
||||
![](../../meta/files/images/Pasted%20image%2020240617195054.png)
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103033544.png]]
|
||||
|
||||
Уровни кэширования:
|
||||
- [Кэширование на стороне браузера](highload/Кэширование%20на%20стороне%20браузера.md). Ответы HTTP могут кэшироваться браузером. При первом запросе данных по HTTP они возвращаются с политикой истечения срока действия в заголовке HTTP. При повторном запросе данных клиентское приложение сначала пытается получить их из кэша браузера.
|
||||
- [Кэширование на стороне Nginx](../devops/nginx/Кэширование%20на%20стороне%20Nginx.md)
|
||||
- [Content Delivery Network](highload/Content%20Delivery%20Network.md). CDN кэширует статические веб-ресурсы. Клиенты могут получать данные с ближайшего узла CDN.
|
||||
- **Балансировщик нагрузки**: Балансировщик также может кэшировать ресурсы.
|
||||
- [Кэширование в приложении](Кэширование%20в%20приложении.md). В сервисах есть несколько уровней кэша. Если данные не находятся в кэше процессора, сервис пытается получить их из памяти. Иногда в сервисе есть вторичный уровень кэша для хранения данных на диске.
|
||||
- **Распределённый кэш**: Распределённые кэши, такие как Redis, хранят пары ключ-значение в памяти для множества сервисов. Это обеспечивает значительно лучшую производительность чтения и записи по сравнению с базой данных.
|
||||
- **База данных**: Даже в базе данных есть различные уровни кэша
|
||||
|
||||
**Виды кэширования:**
|
||||
- Сквозное. Все запросы проходят через кэш. [Схема](../../meta/files/images/Pasted%20image%2020240617194731.png).
|
||||
- Кэширование на стороне сервиса. [Схема](../../meta/files/images/Pasted%20image%2020240617194759.png).
|
||||
- Опережающее. Кладем данные в кэш заранее. [Схема](../../meta/files/images/Pasted%20image%2020240617194938.png).
|
||||
|
||||
Чаще всего кэш реализуется на основе [[../fundamental/structure/Хеш-таблица|хеш-таблиц]] и использует [принцип локальности](../fundamental/Принцип%20локальности.md). Для работы с хеш-таблицей вам необходим [[highload/Ключ кэширования|ключ кэширования]] и сами данные. По ключу данные кладутся и забираются из таблицы.
|
||||
|
||||
Для хранения результатов кэширования я обычно использую JSON. Использую для этого библиотеку [[../../../../knowledge/dev/java/other/Jackson|Jackson]], но есть один [[../snippet/Преобразование Json из коллекции в Java объект при помощи Jackson|нюанс при работе с коллекциям]], который стоит учитывать.
|
||||
|
||||
При желании результат кэширования можно сжать используя [[../algorithm/GZIP|GZIP]]. Однако, приходится использовать [[../other/Base64|Base64]], чтобы преобразовать байты полученные от gzip в строку, и уже в таком виде положить в Redis. Не смотря на то, что Base64 увеличивает размер строки на 33% все равно получается намного компактнее, чем просто JSON.
|
||||
|
||||
Рано или поздно исходные данные изменяются, и кэш перестает быть валидным. Часто важно, чтобы кэш сбрасывался сразу же за изменением. За это отвечает [[highload/Инвалидация кэша|Инвалидация кэша]].
|
||||
|
||||
![[../../meta/files/images/Pasted image 20241103035011.png]]
|
||||
***
|
||||
## Мета информация
|
||||
**Область**:: [[../../meta/zero/00 HighLoad|00 HighLoad]]
|
||||
**Родитель**::
|
||||
**Источник**::
|
||||
**Автор**::
|
||||
**Создана**:: [[2024-05-24]]
|
||||
### Дополнительные материалы
|
||||
- [[highload/Оценка эффективности кэша|Оценка эффективности кэша]]
|
||||
- [Старт с холодным кэшем](highload/Старт%20с%20холодным%20кэшем.md)
|
||||
### Дочерние заметки
|
||||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|
||||
- [[CacheMissRate]]
|
||||
- [[Content Delivery Network]]
|
||||
- [[Инвалидация кэша]]
|
||||
- [[Ключ кэширования]]
|
||||
- [[Кэширование на стороне браузера]]
|
||||
- [[Оценка эффективности кэша]]
|
||||
- [[Перестройка кэша]]
|
||||
- [[Старт с холодным кэшем]]
|
||||
- [[Кэширование в приложении]]
|
||||
- [[Кэширование на стороне Nginx]]
|
||||
<!-- SerializedQuery END -->
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user