D. High-volume Event Storage¶
Тип материала: учебный архитектурный сценарий. Не описывает систему конкретной компании.
Границы и предпосылки¶
Cassandra5.0 либо ScyllaDB2025.1; immutable event history с lookup по tenant/time. Common CQL subset не обещает идентичные defaults/операции. HYPOTHETICAL; retention, bucket width и shard count определяются workload, без универсальных чисел.
Архитектура¶
Все узлы и связи — HYPOTHETICAL.
flowchart TB
Kafka --> Router[Stable hash and layout version]
Router --> Bucket[Bounded tenant time shard partitions]
Bucket --> Replicas[Configured replica set and CL]
Replicas --> LSM[Commit log memtable SSTables]
LSM --> Compaction[TWCS and safe tombstone GC]
Query[Time range query] --> Fanout[Known buckets and shards]
Fanout --> Bucket
Последовательность операций¶
-
Контракт immutable event задаёт tenant, event_id, occurred_at, original expiry deadline и payload. Для одного ID время/payload не меняются; corrections — отдельные версии или иной model.
-
Router вычисляет event_day, layout_version и shard по явно заданному stable hash, например фиксированной реализации SHA-256 bytes modulo N. Встроенный process-randomized hash языка не использовать. N/algorithm версионируются.
-
Partition key=(tenant,day,layout_version,shard), clustering=(occurred_at,event_id). Отдельная таблица lookup by event_id нужна, если требуется запрос без time; её dual-write consistency надо проектировать отдельно.
-
Writer вычисляет remaining TTL по original deadline, пропуская уже истёкшее. Повтор не должен продлевать retention. Политика timestamp при retry должна быть согласована: обычный upsert/timestamp resolution не является проверкой payload equality.
-
Driver задаёт write/read CL в нужном DC и обрабатывает timeout как ambiguous outcome. Для RF3/local quorum пример кворума — 2, но это объяснение алгоритма, не sizing recommendation. В Scylla2025.1 LWT неприменим к tablets keyspace; event path LWT не требует.
-
Reader перечисляет известные buckets/layout versions/shards, делает bounded clustering-range queries с paging и merge sorted results. Не выполнять бесконтрольный global fan-out или ALLOW FILTERING по payload.
-
TWCS обслуживает временные runs; одинаковая expiration policy, редкие late writes, repair schedule и достаточный disk headroom позволяют безопасный lifecycle. Expired данные физически уйдут позже, после compaction/safety checks.
Failure modes и recovery¶
| Сбой | Поведение и восстановление |
|---|---|
| Write timeout | Повтор stable primary key и immutable payload; помнить timestamp/TTL semantics и неопределённый исход. |
| Hot tenant/partition | Увеличить будущий layout shards, хранить routing version; старые partitions не перераспределятся магически. |
| Node отсутствовал долго | Оценить repair/tombstone safety, выполнить documented replace/rebuild; не возвращать stale disk без анализа. |
| Repair/compaction backlog | Снизить ingest/дать ресурсы и место; не сокращать GC horizon без доказательства безопасности. |
| Replay старой истории | Original expiry deadline исключает продление retention; restore полноты требует сохранённого source archive. |
Trade-offs и эксплуатация¶
Больше shards даёт распределение writes ценой fan-out; меньший bucket ограничивает partition size ценой metadata/query overhead. Денормализованные query tables увеличивают write cost и recovery сложность. TTL и TWCS требуют аккуратности с mixed TTL/late updates; counters не используются для финансовых сумм.
Код и границы проверки¶
events.cql — schema/TWCS/query. Cassandra/ScyllaDB runtime отсутствует; CQL не прошёл server validation, replication DC name и options требуют проверки в реальном кластере. Нет обещаний native arbitrary point-in-time restore для обеих систем.
Типичные ошибки проектирования¶
Обещать exactly-once по одному компоненту; не хранить stable identity/version; путать ACK, visible state и восстановимость; не учитывать replay/retention horizon. Таблица отказов задаёт обязательные сценарии дальнейшего тестирования.
Вопросы на собеседовании¶
Где заканчивается транзакционная гарантия? На явно указанной local/engine boundary. Все последующие projections требуют собственного delivery/retry/version contract и контроля полноты.
Практические упражнения¶
Постройте worst-tenant partition size по своим rows/day/bytes. Затем сделайте drill потери node, late replay после TTL и migration N→новое N. Проверяйте не только count, но и event IDs, deadline и query fan-out.
Дополнительные источники¶
Общий отчёт проверок (архив рабочего проекта). Ни статическая проверка, ни model test не подтверждают production reliability.