使用Mysql实现消息队列

本文介绍了如何通过在MySQL中添加状态和版本号字段,利用乐观锁机制实现消息队列的更新与确认。通过设置状态机,确保消息的正确消费,并避免了悲观锁带来的额外开销。这种方法减少了对外部组件如RabbitMQ的依赖,简化了服务架构,同时也解决了更新未改变值时无法判断是否找到记录的问题。此外,还提供了一个生产者自动测试脚本,用于插入消息到队列中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

实现起来就是 消息状态版本号 字段。
在这里插入图片描述
更新时用 版本号 做乐观锁。操作逻辑就是个状态机。

UPDATE mq SET mq.status=new_status mq.version = mq.version + 1 WHERE mq.version = old_version

实现

mysql mq 表结构设计

CREATE TABLE `mq` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `msg` varchar(1024) DEFAULT NULL,
  `status` varchar(100) DEFAULT 'ready',
  `version` bigint(20) unsigned DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;

生产者

测试,向队列插入两条消息。

insert into mq(msg) values('第一条消息 hello world! 1024');
insert into mq(msg) values('第二条消息 欢迎访问 https://spaceack.com');

在这里插入图片描述

消费者

  • 获取队列中的消息, 此时不会改变队列(mq表)中的数据。
select * from mq where status='ready' limit 1;

在这里插入图片描述

  • 消息确认
update mq set mq.status = 'ack', mq.version = mq.version + 1 WHERE mq.version = {query_version} and id = {query_id}

确认后的状态:
在这里插入图片描述
再次获取数据仅能获取第二条数据。在这里插入图片描述


这样的一个好处就是消息都是可见的。 可以直接查数据库。

不用加悲观锁,因为update成功后就带锁。其它同版本的更新都会失败。

还有个好处就是减少组件依赖。 简单的服务数据库就能搞定。 不用再起个rabbitmq服务啥的。 节约运维成本。

版本号 另一个小作用:InnoDB如果更新语句没有改变任何字段值时,影响行数会返回0.那么是没找到记录还是没改变值的0呢?前者是bug, 后者是正常情况但区分不了。加版本号后每次修改+1,影响行数一定不为0。


隐藏福利:生产者自动批量测试脚本:

import random
import subprocess

def runcmd(command):
    ret = subprocess.run(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8",timeout=1)
    if ret.returncode == 0:
        # print("success:",ret, ret.stdout)
        return ret.stdout
    else:
        print("error:",ret)


def producer():
    sql = "\"insert into mq(msg) values('%s');\"" % (str(random.randint(1,99999)))
    cmd = """mysql -uroot -ppassword test -e %s """ % (sql)
    runcmd(cmd)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spaceack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值