Нияз Хадимуллин | Ментор по GO – Telegram
Нияз Хадимуллин | Ментор по GO
1.21K subscribers
138 photos
1 video
35 links
Авторский канал ментора Нияза про Go, базы данных и разработку

Если хочешь записаться на моё менторство и начать получать офферы, не стесняйся писать мне https://mentor-niyaz.ru
Download Telegram
🔍 DNS: как работает резолвинг доменных имен

Что происходит при поиске в браузере?

DNS (Domain Name System) преобразует доменные имена в IP-адреса. Процесс включает несколько этапов.

💡 Процесс резолвинга:

1. Этапы поиска:
- Проверка браузерного кэша
- Проверка кэша ОС
- Запрос к локальному DNS-серверу
- Рекурсивный поиск через корневые серверы

2. Иерархия DNS:
   . (root)
├── .com
│ └── example.com
│ └── www.example.com
├── .org
└── .net

⚠️ Последовательность действий:

1. Ввод URL в браузер
2. Поиск IP в локальных кэшах
3. Запрос к DNS-серверу провайдера
4. Рекурсивный поиск через DNS-серверы
5. Получение IP-адреса
6. Установка HTTP-соединения

Особенности:

- DNS-записи кэшируются
- Существуют разные типы записей (A, AAAA, MX, CNAME)
- Возможны проблемы с пропагацией*

*Пропагация в DNS — это процесс распространения изменений в DNS-записях (например, обновление IP-адреса или добавление новой записи) на все DNS-серверы, которые кэшируют эту информацию. Это может занять от нескольких минут до 48 часов, так как зависит от настроек TTL (Time to Live) и работы DNS-серверов по всему миру.
👍6🔥63
День 🎱

Вторник… вторник никогда не меняется.

Поехали 🛫
🔥54👍2
🔍 Бинарный поиск: эффективный поиск в отсортированных данных

Что такое бинарный поиск?

Бинарный поиск — алгоритм поиска элемента в отсортированном массиве с временной сложностью O(log n), работающий путем деления области поиска пополам на каждом шаге.

💡 Ключевые реализации:

1. Классический бинарный поиск:
func binarySearch(arr []int, target int) int {
left, right := 0, len(arr)-1

for left <= right {
mid := left + (right-left)/2

if arr[mid] == target {
return mid
}
if arr[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return -1
}

2. Поиск левой границы:
func binarySearchLeftmost(arr []int, target int) int {
left, right := 0, len(arr)

for left < right {
mid := left + (right-left)/2
if arr[mid] < target {
left = mid + 1
} else {
right = mid
}
}

if left < len(arr) && arr[left] == target {
return left
}
return -1
}

⚠️ Важные особенности:

- Массив должен быть отсортирован
- Правильное вычисление середины предотвращает переполнение
- Различные варианты для поиска границ при дубликатах
- Работает с любыми сравнимыми типами данных

Распространенные ошибки:

- Неправильные граничные условия
- Некорректная обработка дубликатов
- Забытая проверка на пустой массив
- Неверное обновление указателей
🔥11👍93
👥 Два указателя: элегантные решения для массивов и списков

Что такое техника двух указателей?

Метод двух указателей — подход к решению задач, использующий два указателя, которые перемещаются по структуре данных согласно определенным правилам.

💡 Основные паттерны:

1. Встречное движение:
func twoSum(nums []int, target int) []int {
left, right := 0, len(nums)-1

for left < right {
sum := nums[left] + nums[right]
if sum == target {
return []int{left, right}
}
if sum < target {
left++
} else {
right--
}
}
return nil
}

2. Быстрый и медленный указатели:
func findCycle(head *ListNode) bool {
if head == nil {
return false
}

slow, fast := head, head
for fast.Next != nil && fast.Next.Next != nil {
slow = slow.Next
fast = fast.Next.Next
if slow == fast {
return true
}
}
return false
}

⚠️ Типичные задачи:

- Поиск пары с заданной суммой
- Обнаружение циклов в связном списке
- Удаление дубликатов
- Палиндромы
- Сортировка трех цветов (Dutch Flag Problem)

Особенности применения:

- Часто требует предварительной сортировки
- Важен порядок обновления указателей
- Различные стратегии движения
- Обработка граничных случаев
👍186🔥2
📦 Set в Golang: эффективная работа с уникальными элементами

Что такое Set?

Set — структура данных для хранения уникальных элементов. В Go реализуется через map с пустой структурой в качестве значения для оптимизации памяти.

💡 Полная реализация:
type Set struct {
items map[interface{}]struct{}
}

func NewSet() *Set {
return &Set{
items: make(map[interface{}]struct{}),
}
}

// Основные операции
func (s *Set) Add(item interface{}) {
s.items[item] = struct{}{}
}

func (s *Set) Remove(item interface{}) {
delete(s.items, item)
}

func (s *Set) Contains(item interface{}) bool {
_, exists := s.items[item]
return exists
}

// Операции над множествами
func (s *Set) Union(other *Set) *Set {
result := NewSet()
for item := range s.items {
result.Add(item)
}
for item := range other.items {
result.Add(item)
}
return result
}

func (s *Set) Intersection(other *Set) *Set {
result := NewSet()
for item := range s.items {
if other.Contains(item) {
result.Add(item)
}
}
return result
}

⚠️ Преимущества:

- O(1) для основных операций
- Эффективное использование памяти
- Удобные операции над множествами
- Отсутствие дубликатов

Ограничения:

- Неупорядоченная структура
- Ключи должны быть сравнимыми
- Нет встроенной реализации
- Потребность в type assertions при использовании interface{}
👍16🔥42
📊 Столбчатые БД: оптимизация для аналитики

Что такое столбчатые БД?

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

💡 Основные представители:

1. ClickHouse:
- Высокая производительность
- Сжатие данных
- Векторные вычисления
- Материализованные представления

2. Cassandra:
- Распределенная архитектура
- Высокая доступность
- Wide-column store
- Тьюнабл консистентность

3. Apache Parquet:
- Формат хранения
- Эффективное сжатие
- Интеграция с экосистемой Hadoop
- Предиктивное чтение

⚠️ Преимущества:

- Эффективное сжатие данных
- Быстрые агрегации
- Оптимизация I/O операций
- Параллельная обработка
- Эффективная работа с большими данными

Недостатки и ограничения:

- Медленная запись отдельных записей
- Сложность обновления данных
- Больше сложность разработки
- Специфичные оптимизации запросов
🔥128👍4
🏰 Паттерн Фасад: упрощение сложных систем

Что такое паттерн Фасад?

Фасад — структурный паттерн проектирования, предоставляющий простой интерфейс к сложной системе классов, библиотеке или фреймворку.

💡 Пример реализации:
// Сложные подсистемы
type VideoConverter struct{}
func (v *VideoConverter) Convert(filename string, format string) { /* ... */ }

type AudioMixer struct{}
func (a *AudioMixer) Mix(audioData []byte) { /* ... */ }

type Compressor struct{}
func (c *Compressor) Compress(data []byte) []byte { /* ... */ }

// Фасад
type MediaConverter struct {
videoConverter *VideoConverter
audioMixer *AudioMixer
compressor *Compressor
}

func NewMediaConverter() *MediaConverter {
return &MediaConverter{
videoConverter: &VideoConverter{},
audioMixer: &AudioMixer{},
compressor: &Compressor{},
}
}

// Простой интерфейс для клиента
func (mc *MediaConverter) ConvertVideo(filename, format string) string {
mc.videoConverter.Convert(filename, format)
// ... остальные операции
return "converted_" + filename
}

⚠️ Когда использовать:

- Сложная система с множеством компонентов
- Необходимость упрощения API
- Слоистая архитектура
- Работа с legacy-кодом
- Изоляция клиента от сложности системы
18👍9🔥3
📬 Kafka vs RabbitMQ: модели обмена сообщениями

Какие модели используют брокеры?

Kafka и RabbitMQ представляют разные подходы к обработке сообщений: лог-ориентированный и очередь-ориентированный.

💡 Модель Kafka:

1. Архитектура:
- Topics как упорядоченные логи
- Partitions для параллелизма
- Consumer Groups для масштабирования
- Сохранение сообщений на диске

2. Особенности:
- Pull-модель для потребителей
- Высокая пропускная способность
- Сохранение порядка в партиции

💡 Модель RabbitMQ:

1. Архитектура:
- Exchanges для маршрутизации
- Queues для хранения
- Bindings для связывания
- Virtual Hosts для изоляции

2. Особенности:
- Push-модель для потребителей
- Гибкая маршрутизация
- Транзакционность

⚠️ Сравнение моделей:
- Kafka: потоковая обработка
- RabbitMQ: точка-точка и pub/sub
- Kafka: долгое хранение
- RabbitMQ: быстрая доставка
👍11🔥1
🚀 NATS: сравнение с Kafka и RabbitMQ

Что такое NATS и чем отличается от остальных брокеров сообщений?

NATS - это облегчённый брокер сообщений, ориентированный на высокую производительность и простоту.

💡 Особенности NATS:

1. Архитектура:
- Простой pub/sub
- JetStream для персистентности
- Кластеризация
- Легковесность

2. Протокол:
- Текстовый протокол
- WebSocket поддержка
- Быстрая сериализация
- At-most-once доставка

⚠️ Сравнение:

NATS vs Kafka:
- Проще в настройке
- Меньше функций
- Выше скорость
- Меньше гарантий

NATS vs RabbitMQ:
- Меньше возможностей маршрутизации
- Лучше масштабируется
- Проще протокол
- Быстрее работает

❗️Когда выбирать NATS:
- Микросервисная архитектура
- Реал-тайм системы
- IoT приложения
- Простые очереди

💡Модель NATS (NATS Messaging System) больше похожа на модель RabbitMQ, использующую push-подход. В NATS сообщения отправляются от издателя (publisher) к подписчикам (subscribers) в реальном времени, что соответствует push-модели.

Kafka (pull-модель):
1. Подписчики сами запрашивают сообщения из топиков.
2. Сообщения хранятся в логах и могут быть прочитаны многократно.
3. Подходит для обработки больших объемов данных и обеспечивает высокую пропускную способность.

RabbitMQ (push-модель):
1. Сообщения отправляются от издателя к подписчикам в реальном времени.
2. Подписчики получают сообщения сразу после их отправки.
3. Подходит для сценариев, где требуется низкая задержка и реальное время обработки.

NATS (push-модель):
1. Сообщения отправляются от издателя к подписчикам в реальном времени.
2. Подписчики получают сообщения сразу после их отправки.
3. Подходит для сценариев, где требуется низкая задержка и высокая производительность.
🔥107👍4
День 9️⃣
👍15🔥131
⚡️ sync.Atomic: атомарные операции без мьютексов

Как работает sync.Atomic?

sync.Atomic в Go реализует атомарные операции на уровне процессора без использования мьютексов.

💡 Внутреннее устройство:

1. Процессорные инструкции:
- LOCK префикс
- Инструкции CAS (Compare-And-Swap)
- Аппаратная синхронизация шины памяти

2. Реализация операций:

   // Использует процессорную инструкцию XADD
atomic.AddInt64(&counter, 1)

// Использует инструкцию CMPXCHG
atomic.CompareAndSwapInt64(&value, old, new)


⚠️ Когда использовать?

- Простые счётчики
- Флаги состояния
- Одиночные числовые значения
- Указатели на структуры данных

❗️Особенности:
- Быстрее мьютексов
- Ограниченный набор операций
- Только примитивные типы
- Нет блокировок на уровне ОС
👍14🔥1
🏃 Race Condition: гонка за ресурсами

Что такое Race Condition?

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

💡 Типичные сценарии:

1. Чтение-Модификация-Запись:
   // Опасный код
counter++

// Безопасный код
mu.Lock()
counter++
mu.Unlock()


2. Проверка-Использование:
   // Опасно
if resource != nil {
resource.Use() // resource мог стать nil
}

// Безопасно
mu.Lock()
if resource != nil {
resource.Use()
}
mu.Unlock()


⚠️ Методы предотвращения:

- Мьютексы и семафоры
- Атомарные операции
- Каналы в Go
- Правильная синхронизация

❗️Диагностика:
- go run -race
- Статический анализ
- Логирование
- Стресс-тесты
👍154🔥1
📝 Event Sourcing и Event-Driven Architecture: двое из ларца, одинаковых с лица

В чём разница?

Event Sourcing и Event-Driven Architecture - это паттерны проектирования, использующие концепцию "события", но по-разному.

💡 Event Sourcing:

1. Принципы:
- События как источник правды
- Иммутабельность событий
- Восстановление состояния
- Аудит и отслеживание

💡 Event-Driven Architecture:

1. Принципы:
- Слабая связанность
- Асинхронность
- Масштабируемость
- Реактивность

⚠️ Подробности:

Event Sourcing - это как ваша банковская выписка:
- Хранит ВСЕ операции: "положил 100₽", "снял 50₽", "получил зарплату 1000₽"
- Текущий баланс всегда можно получить, просуммировав все операции
- Важен каждый шаг и их последовательность
- Фокус на ХРАНЕНИИ истории изменений

// Event Sourcing
type Account struct {
events []Event
}

func (a *Account) GetBalance() int {
balance := 0
for _, e := range events {
switch e.Type {
case "DEPOSIT": balance += e.Amount
case "WITHDRAW": balance -= e.Amount
}
}
return balance
}


Event-Driven Architecture - это как система оповещений:
- "Произошла оплата" → уведомляем склад, бухгалтерию, доставку
- События используются для КОММУНИКАЦИИ между частями системы
- Неважна история событий, важна реакция на них
- Фокус на ПЕРЕДАЧЕ информации между компонентами

// Event-Driven Architecture
type OrderService struct {}

func (s *OrderService) OnPaymentReceived(event PaymentEvent) {
// Уведомляем другие сервисы
warehouseService.StartPacking(event.OrderID)
notificationService.SendEmail(event.UserID)
analyticsService.LogPayment(event)
}


Ключевое различие:
- ES решает вопрос "как хранить данные и их историю"
- EDA решает вопрос "как компонентам системы общаться между собой"

Они часто используются вместе, но решают разные задачи: ES отвечает за сохранение истории изменений, а EDA - за коммуникацию между частями системы.
🔥19👍42
🔄 ООП в Go: особенности реализации

Как реализовано ООП в Go?

Go предлагает свой подход к объектно-ориентированному программированию, отличающийся от классического ООП.

💡 Ключевые концепции:

1. Структуры и методы:
   type User struct {
Name string
Age int
}

func (u *User) Birthday() {
u.Age++
}


2. Интерфейсы:
   type Stringer interface {
String() string
}

func (u User) String() string {
return fmt.Sprintf("%s (%d)", u.Name, u.Age)
}


⚠️ Особенности:

- Нет классов (используются структуры)
- Нет наследования (композиция)
- Неявная реализация интерфейсов
- Встраивание типов

❗️Важные моменты:
- Отсутствие перегрузки методов
- Простота и явность кода
- Акцент на композиции
2
📊 Оконные функции: продвинутая аналитика в SQL

Что такое оконные функции?

Оконные функции (Window Functions) - это SQL-функции, которые выполняют вычисления над набором строк, связанных с текущей строкой.

💡 Основные концепции:

1. Синтаксис:
function_name() OVER (
PARTITION BY column1
ORDER BY column2
ROWS/RANGE BETWEEN start AND end
)


2. Типы функций:
- Агрегатные (SUM, AVG, COUNT)
- Ранжирующие (ROW_NUMBER, RANK, DENSE_RANK)
- Аналитические (LAG, LEAD, FIRST_VALUE)
- Статистические (PERCENTILE_CONT, CUME_DIST)

⚠️ Когда использовать?

- Расчёт накопительных итогов
- Сравнение с предыдущими значениями
- Поиск аномалий в данных
- Ранжирование и группировка

❗️Особенности:
- Могут снижать производительность
- Требуют правильной индексации
- Нужно учитывать объём данных
2
🗄 Redis: быстрое хранилище в памяти

Что такое Redis?

Redis (Remote Dictionary Server) - это система управления базами данных типа "ключ-значение", работающая в оперативной памяти.

💡 Ключевые структуры данных:

1. Типы данных:
- Strings (строки)
- Lists (списки)
- Sets (множества)
- Hashes (хэши)
- Sorted Sets (сортированные множества)
- Streams (потоки)

2. Операции:
   SET key value
GET key
INCR counter
EXPIRE key seconds
ZADD sortedset score member


⚠️ Типичные применения:

- Кэширование
- Очереди сообщений
- Подсчёт уникальных посещений
- Управление сессиями
- Рейтинги и лидерборды

❗️Важные моменты:
- Данные в памяти (быстро, но дорого)
- Механизмы персистентности (RDB, AOF)
- Необходимость планирования объёма памяти

⚠️ В одном из следующих постов мы обязательного обсудим, как можно использовать Redis в качестве очереди!
2
🌐 Статические IP: почему они платные

Что такое статический IP?

Статический IP - это постоянный IP-адрес, который не меняется при переподключении к сети.

💡 Технические аспекты:

1. Особенности:
- Уникальный адрес в интернете
- Не меняется во времени
- Позволяет обратную DNS-запись
- Упрощает администрирование

2. Причины платности:
- Ограниченность IPv4-адресов
- Затраты на инфраструктуру
- Административные расходы
- Спрос со стороны бизнеса

⚠️ Когда необходим?

- Хостинг серверов
- VPN-сервисы
- Удалённый доступ
- Видеонаблюдение
- Email-серверы

❗️Альтернативы:
- Dynamic DNS (DDNS)
- IPv6 (больше адресов)
- Облачные решения
2
🎯 Kubelet: агент Kubernetes

Что такое Kubelet?

Kubelet - это основной агент, работающий на каждой ноде кластера Kubernetes, отвечающий за запуск и мониторинг контейнеров.

💡 Основные функции:

1. Управление подами:
- Запуск контейнеров
- Монтирование томов
- Проверка здоровья
- Отчётность о состоянии

2. Взаимодействие с компонентами:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2


⚠️ Ответственности:

- Регистрация ноды в кластере
- Выполнение проверок готовности
- Управление ресурсами
- Сбор метрик

❗️Особенности работы:
- Прямое взаимодействие с container runtime
- Локальное кэширование манифестов
- Автономная работа при потере связи с API
2
Что такое функциональная парадигма в Golang?

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

💡 Основные концепции:

1. Функции первого класса:
- Функции могут передаваться как аргументы, возвращаться из других функций и присваиваться переменным.
- Пример:
func apply(f func(int) int, x int) int {
return f(x)
}


2. Замыкания:
- Функции могут захватывать переменные из окружающего контекста.
- Пример:
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}


3. Чистые функции:
- Функции, которые не имеют побочных эффектов и возвращают одинаковый результат для одинаковых входных данных.
- Пример:
func add(a, b int) int {
return a + b
}


4. Рекурсия:
- Функции могут вызывать сами себя.
- Пример:
func factorial(n int) int {
if n == 0 {
return 1
}
return n * factorial(n-1)
}


⚠️ Важные моменты:
- Golang не поддерживает некоторые функциональные возможности, такие как монады или ленивые вычисления.
- Использование функциональных подходов может улучшить читаемость и модульность кода.

❗️Особенности:
- Функциональная парадигма может быть полезна для обработки данных и работы с коллекциями.
- В Golang часто используется комбинация императивного и функционального стилей.
2
Что такое ElasticSearch?

ElasticSearch — это распределенная поисковая и аналитическая система, основанная на Apache Lucene. Она позволяет быстро искать, анализировать и визуализировать большие объемы данных.

💡 Основные компоненты:

1. Индексы:
- Логические контейнеры для данных, аналогичные таблицам в базах данных.
- Пример: my_index

2. Документы:
- Основная единица данных в ElasticSearch, хранящаяся в формате JSON.
- Пример:
     {
"noscript": "ElasticSearch",
"content": "Distributed search engine"
}


3. Запросы:
- Поисковые запросы, которые можно выполнять с использованием DSL (Domain Specific Language).
- Пример:
     {
"query": {
"match": {
"noscript": "ElasticSearch"
}
}
}


4. Кластеры и узлы:
- ElasticSearch работает в распределенном режиме, где данные распределены между несколькими узлами в кластере.

⚠️ Важные моменты:
- ElasticSearch поддерживает горизонтальное масштабирование.
- Данные автоматически реплицируются для обеспечения отказоустойчивости.

❗️Особенности:
- ElasticSearch часто используется для полнотекстового поиска, лог-анализа и аналитики в реальном времени.
- Интеграция с Kibana позволяет визуализировать данные.
2
Что такое составные индексы в SQL?

Составные индексы — это индексы, которые создаются на несколько столбцов таблицы. Они используются для ускорения запросов, которые фильтруют или сортируют данные по нескольким столбцам.

💡 Основные концепции:

1. Создание составного индекса:
- Пример:
CREATE INDEX idx_name ON table_name (column1, column2);


2. Использование в запросах:
- Составные индексы эффективны для запросов, которые используют префикс индекса.
- Пример:
SELECT * FROM table_name WHERE column1 = 'value1' AND column2 = 'value2';


3. Порядок столбцов:
- Порядок столбцов в индексе важен. Индекс не будет использоваться, если запрос не включает префиксные столбцы.
- Пример:
SELECT * FROM table_name WHERE column2 = 'value2'; -- Индекс не используется


⚠️ Важные моменты:
- Составные индексы могут занимать больше места на диске.
- Не все СУБД поддерживают использование составных индексов для сортировки.

❗️Особенности:
- Составные индексы могут значительно ускорить выполнение сложных запросов.
- Важно правильно выбирать порядок столбцов в индексе для максимальной эффективности.
2