РСУБД поверх Telegram.
pip install tgdb
docker pull n255/tgdb:0.1.0-slim
Caution
Не используйте этот проект с большим количеством ботов, так как он нарушает правила Telegram и создаёт паразитическую нагрузку на его инфраструктуру.
В противном случае ваши данные могут быть удалены, а аккаунты — заблокированы.
Для запуска сервера укажите путь к YAML-конфигу через переменную окружения CONFIG_PATH
.
Пример конфигурации:
conf:
uvicorn:
host: "0.0.0.0"
port: 8000
api:
id: 23598539
hash: "6d9d7305ffc6f148dab120d24541b127"
clients:
bots: "/etc/tgdb/clients/bots"
userbots: "/etc/tgdb/clients/userbots"
horizon:
max_len: 800
transaction:
max_age_seconds: 30
message_cache:
max_len: 100_000
heap:
chat: -1000000000000
page:
max_fullness: 0.8
relations:
chat: -1000000000000
buffer:
chat: -1000000000000
overflow:
len: 5000
timeout_seconds: 0.1
Important
С данной конфигурацией один сервер потребляет не более 200 МБ памяти (без учёта обработки входящих запросов).
tgdb
— это СУБД, хранящая данные в Telegram-чатах и предоставляющая доступ к ним через реляционную модель с поддержкой ACID-транзакций.
Взаимодействие с Telegram происходит через ботов/юзерботов, имеющих фиксированные лимиты на количество запросов в определённый промежуток времени. Фактически они представляют собой аренду небольшой части инфраструктуры Telegram, поэтому считаются ресурсами ввода-вывода (аналогично пропускной способности сети).
Из-за специфики лимитов операции с сообщениями имеют существенно разную стоимость по сравнению с операциями в памяти/на диске:
- Все операции выполняются за константное время (200–400 мс), но чтение значительно дороже записи, так как доступно только через юзерботов. Для регистрации юзербота требуется отдельный номер (по закону РФ физическое лицо может иметь не более 20 номеров), тогда как для обычных ботов достаточно регистрации у BotFather.
- Несмотря на сложность создания юзерботов, за один запрос можно прочитать множество сообщений. Запись новых сообщений требует отдельного запроса для каждого сообщения.
- Обновление сообщений требует предварительного поиска целевого сообщения.
- Удаление поддерживает пакетную обработку, но также требует поиска сообщений.
Текущая реализация позволяет создавать отношения без поддержки миграций. Ограничения включают только доменные ограничения на размер данных.
Физически кортежи не группируются по отношениям, а хранятся в едином чате (куче). Каждый кортеж размещается в отдельном сообщении (странице) размером до 4096 символов. Следовательно, невозможно создать отношение, кортежи которого не помещаются в одну страницу.
На данный момент можно читать кортежи только до записи, а сама запись возможна только через bulk-запрос в рамках коммита.
tgdb
не использует MVCC, поэтому невозможно сделать Repeatable Read в том виде, что бы он был легче Serializable. В этом случае может быть только три уровня изоляции:
n
— количество транзакций уровня изоляции.
Уровень изоляции | Особенности | Старт | Коммит | Откат | Память |
---|---|---|---|---|---|
Serializable | Требует повторения транзакций при ошибках сериализации | O(n) | O(n) | O(n) | O(n²) |
Read Committed | В разработке. Операции чтения могут выполняться в 3 раза дольше | O(1) | O(1) | O(1) | O(n) |
Read Uncommitted | O(1) | O(1) | O(1) | O(n) |
Important
При параллельном выполнении транзакций с разными уровнями изоляции вся группа получает гарантии минимального уровня из группы.
Чтение кортежей вне транзакций эквивалентно уровню Read Uncommitted, но создаёт меньшую нагрузку.
Коммиты буферизируются и хранятся в отдельном чате перед конкурентной записью в кучу. При достаточном количестве ботов задержка транзакции (10 чтений + 10 записей) составляет ~3 обращения к Telegram (~0.75 с).
Буфер хранится на сервере и сохраняется в чате только при переполнении. Это гарантирует восстановление консистентного состояния после сбоев и не ограничивает сервер пропускной способностью в одно обращение к Telegram.
Этапы выполнения транзакции:
- Старт транзакции — сетевая задержка до сервера
tgdb
- Чтение из кучи — сетевая задержка до
telegram
- Начало коммита — сетевая задержка до сервера
tgdb
- Ожидание переполнения буфера —
conf.buffer.overflow.timeout_seconds
(макс.) - Сохранение буфера в чате — сетевая задержка до
telegram
- Запись в кучу — сетевая задержка до
telegram
- Подтверждение коммита — сетевая задержка до сервера
tgdb
На данный момент все данные хранятся в одной куче, которая может вмещать только 1 млн сообщений (после 1 млн Telegram будет удалять сообщения до 500 тыс.), что даже в случае полного заполнения страниц ~16 ГБ (включая метаданные) и сам по себе сервер однопоточный.
В таком случае нужно секционировать данные между несколькими серверами практически всегда, даже в случае одной ноды, но сейчас нет встроенных механизмов для этого.