PmaControl logo PmaControl
  • 首页
  • PmaControl
    • AI智能代理 13个本地代理
    • 定价方案 Community、Cloud、On-Premise、Premium
    • 文档 指南、API、架构
    • 客户 28+企业
    • 常见问题 25个问题 / 7个类别
    数据库
    • MariaDB 30 篇文章
    • MySQL 10 篇文章
    • Galera Cluster 6 篇文章
    • MaxScale 3 篇文章
    • ProxySQL 2 篇文章
    • Amazon Aurora MySQL 0 篇文章
    • Azure Database 0 篇文章
    • ClickHouse 0 篇文章
    • GCP CloudSQL 0 篇文章
    • Percona Server 0 篇文章
    • SingleStore 0 篇文章
    • TiDB 0 篇文章
    • Vitess 0 篇文章
    解决方案
    • 全天候支持 MariaDB & MySQL紧急支持
    • Observabilité SQL 监控、告警、拓扑
    • Haute disponibilité 复制、故障转移、Galera
    • Disaster Recovery 备份、恢复、RPO/RTO
    • Sécurité & conformité 审计、GDPR、SOC2
    • Migration & upgrade 零停机、pt-osc、gh-ost
  • 定价方案
  • 资源
    • 文档 技术指南与API
    • 常见问题 25个常见问题
    • 客户评价 客户反馈与案例
    • 博客 文章与洞察
    • 路线图 即将推出的功能
    专业领域
    • Observabilité SQL 监控、告警、Dot3拓扑
    • Haute disponibilité 复制、故障转移、Galera
    • Sécurité & conformité 审计、GDPR、SOC2、ISO 27001
    • Disaster Recovery 备份、恢复、RPO/RTO
    • Performance & optimisation Digests、EXPLAIN、调优
    • Migration & upgrade 零停机、pt-osc
    快速链接
    • GitHub Wiki 26页 — 安装、引擎、插件
    • 源代码 GitHub官方仓库
    • 全天候支持 MariaDB & MySQL紧急支持
    • 预约演示 30分钟 — 真实架构
  • 全天候支持
  • 预约演示
预约演示
🇫🇷 FR Français 🇬🇧 EN English 🇵🇱 PL Polski 🇷🇺 RU Русский 🇨🇳 ZH 中文
← 返回博客

MMQ:将 MariaDB 用作消息队列

发布于 2024年11月5日 作者 Sylvain ARBAUDIE
mariadb message-queue blackhole replication
分享 X LinkedIn Facebook Email PDF
MMQ:将 MariaDB 用作消息队列

这个疯狂的想法

如果我们仅使用 MariaDB 来构建一个消息队列会怎样?不是 Kafka,不是 RabbitMQ,不是 Redis Streams。只是 MariaDB,它的存储引擎和 binlog 复制。

这是一个思想实验,一个概念验证。目标不是取代成熟的消息方案,而是展示 MariaDB / MySQL 架构的灵活性,并探索鲜为人知的模式。

MMQ 架构

MMQ(MariaDB Message Queue,MariaDB 消息队列)依赖三个原生组件:

  1. Blackhole 引擎:一个接受 INSERT 但不存储任何内容的存储引擎。数据"消失"了——但它会被记录在 binlog 中。
  2. Binlog 复制:MariaDB 的原生复制机制,将事件从一台服务器传播到另一台。
  3. InnoDB 表 + 触发器:用于消息消费和追踪。

生产者(Publisher)

生产者服务器有一个 Blackhole 表作为入口:

CREATE TABLE message_queue (
    msg_id BIGINT NOT NULL,
    topic VARCHAR(255) NOT NULL,
    payload JSON NOT NULL,
    created_at DATETIME(6) DEFAULT NOW(6)
) ENGINE=Blackhole;

当应用程序发布消息时:

INSERT INTO message_queue (msg_id, topic, payload)
VALUES (
    NEXT VALUE FOR msg_sequence,
    'order.created',
    '{"order_id": 12345, "customer": "acme", "total": 99.99}'
);

Blackhole 引擎不写入任何数据到磁盘。但 INSERT 会被记录在服务器的 binlog 中。这就是 Blackhole 的魔力:它参与 binlog 而不消耗存储。

用于标识符的序列

MariaDB 支持序列(自版本 10.3 起),提供无需 AUTO_INCREMENT 锁定成本的唯一标识符:

CREATE SEQUENCE msg_sequence
    START WITH 1
    INCREMENT BY 1
    CACHE 1000;

CACHE 1000 在内存中预分配 1,000 个值,减少磁盘访问和锁。

中间代理(Broker/Relay)

中间代理是一台配置为生产者从库的 MariaDB 服务器。它接收 binlog 事件并进行复制。这就是消息分发机制。

对于扇出(一条消息发送给多个消费者),你可以拥有同一主库的多个从库——每个从库独立接收所有消息的副本。

生产者 (Blackhole) → binlog → 代理 1 (从库)
                             → 代理 2 (从库)
                             → 代理 3 (从库)

消费者

每个消费者有一个 InnoDB 表存储接收到的消息以及消费追踪机制:

CREATE TABLE consumed_messages (
    msg_id BIGINT PRIMARY KEY,
    topic VARCHAR(255),
    payload JSON,
    created_at DATETIME(6),
    consumed_at DATETIME(6) DEFAULT NULL,
    consumer_id VARCHAR(100) DEFAULT NULL
) ENGINE=InnoDB;

一个触发器将复制的 INSERT 转换为可用的行:

CREATE TRIGGER trg_message_arrived
BEFORE INSERT ON message_queue
FOR EACH ROW
BEGIN
    INSERT INTO consumed_messages (msg_id, topic, payload, created_at)
    VALUES (NEW.msg_id, NEW.topic, NEW.payload, NEW.created_at);
END;

消费通过原子查询完成:

UPDATE consumed_messages
SET consumed_at = NOW(6),
    consumer_id = 'worker-01'
WHERE consumed_at IS NULL
  AND topic = 'order.created'
ORDER BY msg_id ASC
LIMIT 1;

LIMIT 1 与原子 UPDATE 结合,确保只有一个消费者处理每条消息(没有重复消费)。

JSON 消息

MariaDB 的原生 JSON 格式(自 10.2 起)允许用丰富的载荷来结构化消息:

INSERT INTO message_queue (msg_id, topic, payload) VALUES (
    NEXT VALUE FOR msg_sequence,
    'user.profile.updated',
    JSON_OBJECT(
        'user_id', 42,
        'changes', JSON_ARRAY(
            JSON_OBJECT('field', 'email', 'old', 'old@mail.com', 'new', 'new@mail.com'),
            JSON_OBJECT('field', 'name', 'old', 'John', 'new', 'Jonathan')
        ),
        'timestamp', NOW(6)
    )
);

局限性(而且有很多)

让我们明确:MMQ 是一个概念,不是生产就绪的解决方案。

没有可靠的投递保证。 如果复制中断,消息会丢失(或延迟)。没有原生重试机制。

没有分区。 所有消息流经单个 binlog。不像 Kafka 那样有按主题的分发。

没有重放。 一旦消费,消息无法轻松重放(除非你保留生产者上的 binlog)。

复制延迟。 复制延迟在发布和消息可用之间增加了延时。对异步场景可以接受,对实时场景则不行。

没有分布式确认。 生产者不知道消费者是否处理了消息。

为什么它仍然有趣

尽管有这些局限性,这种模式展示了重要的概念:

  1. binlog 作为事件流。 MariaDB / MySQL 的 binlog 是一个有序的、持久的、可复制的事件流。概念上接近 Kafka 日志。

  2. Blackhole 引擎作为适配器。 Blackhole 允许"发布"而不存储,使用 binlog 作为传输通道。

  3. 复制作为分发机制。 多从库复制提供原生的扇出分发,无需额外配置。

  4. 数据库作为多功能基础设施。 如果你的生产环境中已经有 MariaDB,你就已经拥有简单消息传递的基础设施。

对于简单的使用场景——服务间的内部通知、事件审计、站点间的事件复制——MMQ 可能足够用了,无需添加额外的基础设施组件。

结论

MariaDB 作为消息队列:一个疯狂的想法,一个有趣的概念验证,以及 Blackhole 引擎 + binlog 复制灵活性的展示。不要在生产环境中将其用于关键消息传递。但记住这个概念——有时候最好的架构就是利用你已经拥有的东西。


本文最初发表于 Medium。

分享 X LinkedIn Facebook Email PDF
← 返回博客

评论 (0)

暂无评论。

发表评论

PmaControl
+33 6 63 28 27 47 contact@pmacontrol.com
法律声明 GitHub 联系我们
不要等到故障发生才了解您的架构。 © 2014-2026 PmaControl — 68Koncept