在分布式系统领域,Apache Kafka 几乎成为了消息队列的代名词,但其复杂的集群部署、资源消耗和运维成本让许多中小型项目望而却步。当你的团队只需要一个可靠的消息中间件来处理日常开发、测试环境,甚至是小规模生产流量时,是否存在一种更轻量的替代方案?Tansu 项目给出了一个出人意料的答案:使用 SQLite 作为存储引擎,在一台免费的 AWS t3.micro 实例上运行 Kafka 兼容的消息队列,整个 broker 的内存占用仅为约 19MB。
这种方案的核心在于 Tansu 对存储引擎的可插拔设计。与传统 Kafka 将消息存储在分布式日志文件中不同,Tansu 允许开发者选择不同的后端存储方式,包括内存模式、S3 对象存储、PostgreSQL 关系数据库,以及本文重点讨论的 SQLite 嵌入式数据库。SQLite 模式将所有元数据和消息数据保存在单个文件(默认命名为 tansu.db)中,这意味着备份和恢复变得极为简单 —— 只需复制该文件即可完成环境迁移。在零停机要求的场景下,Tansu 还支持切换到 S3 存储引擎,多个无状态 broker 可以通过乐观并发机制共享同一个 S3 桶,实现实例类型的灵活扩缩容。
然而,将 SQLite 应用于消息队列场景并非没有代价。SQLite 采用单写入模型,即使在启用 WAL(Write-Ahead Logging)模式的情况下,所有写入操作仍然是串行的,一次写入会短暂阻塞其他表的写入操作。这与 MySQL 或 PostgreSQL 等关系数据库的表级或行级锁机制有本质区别。对于追求高吞吐量的生产环境,这一限制可能成为性能瓶颈。因此,SQLite 存储引擎更适合以下场景:本地开发环境、测试数据生成、小规模内部系统,以及对吞吐量要求在每秒数千消息以内的中低负载应用。在评估是否采用此方案时,团队需要根据实际业务的消息产生速率、消费者数量以及可接受的端到端延迟来做出判断。
若决定在生产环境中使用 SQLite 存储引擎,必须正确配置多个 SQLite PRAGMA 参数以确保稳定性和性能。首先应启用 WAL 模式(PRAGMA journal_mode=WAL),这允许读写操作并发进行,写入操作写入日志文件而非立即同步到主数据库。其次将同步级别设置为 NORMAL(PRAGMA synchronous=NORMAL),在保证一定持久性的同时提升写入性能。此外,还应配置内存映射大小(PRAGMA mmap_size=134217728,即 128MB)以减少系统调用开销,并设置适当的缓存大小(PRAGMA cache_size=2000)来平衡内存使用与查询效率。这些配置项的具体数值应根据 t3.micro 实例的 1GB 内存限制进行调整,避免因缓存过大导致内存不足。
在 AWS t3.micro 实例上部署 Tansu 的操作步骤相对直接。首先启动一台配置 Amazon Linux 2023 的实例,然后安装 Docker Compose 并启用 containerd 服务。接着创建 docker-compose.yaml 文件,指定 Tansu 的官方镜像(ghcr.io/tansu-io/tansu),配置 ADVERTISED_LISTENER_URL 为实例的公共 DNS 名称,并将 STORAGE_ENGINE 环境变量设置为 "sqlite://data/tansu.db"。通过 docker compose up -d 启动服务后,可以使用 Tansu CLI 创建测试主题并验证消息的生产与消费功能。监控方面,建议定期检查 tansu.db 文件的大小增长趋势、磁盘 I/O 利用率以及 SQLite 的锁等待时间,一旦发现写入延迟显著增加或锁竞争频繁,就应考虑迁移到 S3 或 PostgreSQL 存储引擎以获得更好的横向扩展能力。
对于正在寻找 Kafka 替代方案的团队,Tansu 的 SQLite 模式提供了一条值得探索的路径。它保留了 Kafka 的 API 兼容性,使现有应用程序无需修改即可接入,同时大幅降低了基础设施成本和运维复杂度。但正如所有技术决策一样,关键是理解其适用边界 —— 当业务规模增长到一定程度时,及时规划向更高性能的存储引擎迁移才是负责任的做法。
参考资料
- Tansu 官方博客:Small Kafka: Tansu + SQLite on a free t3.micro(https://blog.tansu.io/articles/broker-aws-free-tier)
- Anže Pečar:Gotchas with SQLite in Production(https://blog.pecar.me/sqlite-prod)