Backend Development 9 min read

Design and Implementation of a Transactional Message Module Using RabbitMQ and MySQL

This article explains a lightweight transactional message solution for microservices that leverages RabbitMQ, MySQL, and Spring Boot to achieve eventual consistency, detailing design principles, compensation mechanisms, table schemas, and deployment considerations for high‑throughput asynchronous processing.

Top Architect
Top Architect
Top Architect
Design and Implementation of a Transactional Message Module Using RabbitMQ and MySQL

Distributed transactions are a difficult problem in microservice practice; the author adopts a compromise approach that avoids strong consistency by using a lightweight transactional message module built on RabbitMQ and MySQL.

The design assumes transaction messages are suitable only for weak‑consistency (eventual‑consistency) scenarios such as user registration notifications or order‑approval events, while strong‑consistency cases should not use this mechanism.

Key principles include: the upstream service pushes a correct message to RabbitMQ and then considers its duty finished; the module relies on Spring's programmatic or declarative transactions (TransactionTemplate or @Transactional) to keep code intrusion low.

The module provides three core functions: persisting the message record, pushing the message to RabbitMQ, and offering query/compensation capabilities. Compensation is handled via a finite‑state check that marks a message as "processing" when saved, then updates the status to "sent" after the TransactionSynchronization.afterCommit() callback pushes it.

Special cases such as afterCommit() failures (e.g., service restart before push) and RabbitMQ server outages are addressed with retry logic using exponential back‑off and a configurable maximum retry count.

Two MySQL tables are defined to store message metadata and large message content separately, reducing I/O pressure during bulk queries. The DDL is shown below:

CREATE TABLE `t_transactional_message` (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    edit_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    creator VARCHAR(20) NOT NULL DEFAULT 'admin',
    editor VARCHAR(20) NOT NULL DEFAULT 'admin',
    deleted TINYINT NOT NULL DEFAULT 0,
    current_retry_times TINYINT NOT NULL DEFAULT 0 COMMENT '当前重试次数',
    max_retry_times TINYINT NOT NULL DEFAULT 5 COMMENT '最大重试次数',
    queue_name VARCHAR(255) NOT NULL COMMENT '队列名',
    exchange_name VARCHAR(255) NOT NULL COMMENT '交换器名',
    exchange_type VARCHAR(8) NOT NULL COMMENT '交换类型',
    routing_key VARCHAR(255) COMMENT '路由键',
    business_module VARCHAR(32) NOT NULL COMMENT '业务模块',
    business_key VARCHAR(255) NOT NULL COMMENT '业务键',
    next_schedule_time DATETIME NOT NULL COMMENT '下一次调度时间',
    message_status TINYINT NOT NULL DEFAULT 0 COMMENT '消息状态',
    init_backoff BIGINT UNSIGNED NOT NULL DEFAULT 10 COMMENT '退避初始化值,单位为秒',
    backoff_factor TINYINT NOT NULL DEFAULT 2 COMMENT '退避因子(也就是指数)',
    INDEX idx_queue_name (queue_name),
    INDEX idx_create_time (create_time),
    INDEX idx_next_schedule_time (next_schedule_time),
    INDEX idx_business_key (business_key)
) COMMENT '事务消息表';

CREATE TABLE `t_transactional_message_content` (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    message_id BIGINT UNSIGNED NOT NULL COMMENT '事务消息记录ID',
    content TEXT COMMENT '消息内容'
) COMMENT '事务消息内容表';

Because the module may be extended with a management UI, message metadata and large payloads are stored separately to avoid high I/O during bulk reads. Business fields (business_module, business_key) identify the originating domain (e.g., order number).

When sending messages, the service primarily uses exchangeName and routingKey; if the queue‑exchange binding is missing, the module declares it on first use and caches the relationship, ensuring idempotent declarations.

In summary, the transactional message module provides a near‑complete solution for asynchronous message delivery, includes compensation and monitoring features, and can be integrated with observability stacks such as Micrometer, Prometheus, and Grafana to improve system throughput and reliability.

Demo repository: rabbit-transactional-message . The demo requires local MySQL, Redis, and RabbitMQ instances and a database named local .

distributed systemsMicroservicesSpring BootMySQLRabbitMQcompensationTransactional Messaging
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.