Архитектура TiDB состоит из трех ключевых компонентов, развязанных по принципу shared-nothing:
- **TiDB Server** — безсостояниевые (stateless) узлы, отвечающие за прием SQL-запросов, их парсинг, оптимизацию и генерацию плана выполнения. Они не хранят данные, а лишь преобразуют SQL-запросы в вызовы к нижележащему ключ-значение хранилищу. Для highload критически важно горизонтальное масштабирование этого слоя: добавление новых TiDB-серверов за балансировщиком нагрузки (например, HAProxy или Kubernetes Service) позволяет распределить нагрузку от приложений.
- **TiKV Server** — распределенное, транзакционное ключ-значение хранилище, где фактически лежат данные. Это сердце системы, написанное на Rust. Данные автоматически шардируются по кластеру в виде регионов (Regions) — диапазонов ключей размером примерно 96 MiB по умолчанию. Каждый регион реплицируется (обычно в 3 копии) через алгоритм консенсуса Raft для обеспечения отказоустойчивости и согласованности. Производительность TiKV напрямую определяет производительность всего кластера.
- **Placement Driver (PD)** — "мозг" кластера, менеджер метаданных. PD управляет расположением регионов на узлах TiKV, делает балансировку нагрузки, распределяет Raft-лидеров и назначает уникальные идентификаторы. Для highload-кластера PD должен быть высокодоступным (минимум 3 узла) и иметь низкую задержку сети между собой и узлами TiKV.
Ключевые настройки TiKV для highload:
- `region-max-size` и `region-split-size`: Уменьшение размера региона (например, до 64 MiB) может улучшить балансировку и параллелизм обработки, но увеличит нагрузку на PD. Требует тестирования.
- `raftstore.store-pool-size` и `raftstore.apply-pool-size`: Эти пулы потоков обрабатывают Raft-логи и apply-логи соответственно. Их размер должен быть адекватен количеству CPU-ядер.
- `storage.block-cache.capacity`: Кэш блоков данных RocksDB. Обычно устанавливается в 30-50% от доступной оперативной памяти на узле TiKV.
- `coprocessor`: Настройки для обработки запросов, которые могут выполняться прямо на TiKV (например, агрегации). Увеличение `coprocessor.thread-pool-size` может помочь.
Паттерны проектирования схемы данных и запросов:
- **Горячие регионы (Hot Regions):** Если все запросы идут по одному ключу (например, счётчик глобальных заказов), возникает горячий регион, который становится узким местом. Решение — шардирование на уровне приложения: добавление суффикса к ключу (например, `order_counter_00`, `order_counter_01`) или использование композитных первичных ключей, которые равномерно распределяют данные.
- **Индексы:** TiDB поддерживает вторичные индексы, но они также хранятся в TiKV и создают дополнительную нагрузку на запись. Для highload-записей минимизируйте количество индексов. Используйте покрывающие индексы (covering indexes) для чтения, чтобы избежать лишних обращений к основной таблице.
- **Транзакции:** Длинные транзакции — враг производительности. Они блокируют версии данных в памяти (MVCC). Разбивайте большие транзакции на мелкие, используйте оптимистичные блокировки. Настройте `tidb_txn_mode` на 'optimistic' там, где это допустимо.
- **Типы данных:** Используйте наиболее эффективные типы. `INT` вместо `VARCHAR` для ключей, если возможно. Избегайте `TEXT/BLOB` в часто сканируемых полях.
Таким образом, успешное использование TiDB под highload — это не просто развертывание кластера, а тонкая настройка компонентов, продуманное проектирование схемы данных и постоянный мониторинг. При правильном подходе TiDB способна стать высокопроизводительным, масштабируемым и надежным фундаментом для самых требовательных сервисов.
Комментарии (13)