首先是 message 表:
字段名 | 类型及描述 |
---|---|
id | 主键 |
status | 消息状态(待处理,进行中,成功,失败) |
try_count | 消费者重试次数 |
lock_expires | 锁过期时间 |
created | 创建时间 |
data | 消息数据 |
然后消费端轮询:
select *
from message
where status in ('PENDING', 'STARTED', 'FAILED')
and try_count < max_tries
and lock_expires < now()
order by created
limit 1 for update
skip locked;
解释下 sql:
利用关系数据库持久化消息,支持索引,可以灵活检索,关键是无需额外引入组件,请问这种方案是否可行呢?
1
chesha1 14 天前
为啥不用 redis ,redis 做消息队列不是比 sqldb 更成熟的方案吗?
|
2
nulIptr 14 天前
看你侧重哪部分功能,简单少量数据的场景随便怎么搞都行,无需引入额外组件也确实是一个优点,古时候在金蝶做某个项目的时候真是你这种用法,除了数据库是 sqlserver 。
不过消息队列主要还是数据量大的时候为了高吞吐量,就要花点心思了。 |
3
julyclyde 14 天前
举个例子:
一个消息需要被 不定量的消费者 分别读取 就这个“不定量”,你用关系型数据库就不好搞吧 |
4
Need4more OP |
7
HENQIGUAI 14 天前
不是很理解为什么说 Redis 不支持持久化
|
![]() |
9
codingKingKong 14 天前 ![]() 1.首先看规模, 如果数据量不大, 资源竞争不严重, 我同意其他人的观点, 怎么搞都行
2.然后还是看规模, 如果都上到 sql 上, 发现性能能接受, 那其实就是合适的方案 3.如果流量再高些, 请考虑 redis, 你可以不用它的 push, pop 这些来实现, 但是它能提供比高并发下 mysql 更好的性能, 毕竟它是做缓存用的 4.如果还有些特殊需求, 请考虑上专业的延迟队列, 例如延迟消费, 自动重试, 精确消费, 至多至少消费语义等, 这些不是 sqldb 不能实现, 而是你需要自己实现, 你需要考虑性价比 最后, 是否有必须要这个问题需要你自己考虑, 不同场景下答案不一样 |
![]() |
10
ratazzi 14 天前
|
11
neilq 14 天前
恭喜你发现了 `本地消息表`
完全可以这么做 |
12
neilq 14 天前
另针对 redis 消息队列补充一句,现在 redis 5.0 以上不推荐使用 pub/sub ,pub/sub 确实不能持久化。
现在 redis 消息队列推荐使用 redis streams 。不过需要自己实现清理消息的机制。 redis 服务器压力没那么大的情况下不需要考虑持久化稳定性,尤其在你`系统没那么大规模`的情况下。 |
13
zepc007 13 天前
All In Postgres
|
![]() |
14
banmuyutian 13 天前
可以呀,我司在用的 solace 就是这么实现的
|
15
moyupai 13 天前
完全可以,但完全没必要,
量不大,用啥都行 量大,你要想想数据库怎么扩喽 |
![]() |
16
8355 13 天前
数据库性能难道不是比队列或者 redis 更贵吗。。。
这到底是轻量化需求还是受环境限制? |
![]() |
17
mightofcode 13 天前
业务量小 实时性要求低
其实没啥问题 |
18
bbao 13 天前
redis 从来不推荐你做消息队列使用,sql 做消息队列, 内部系统随便你;
toC 系统,HR 这个人不合适,我们启动招聘吧。 |
19
cookii 13 天前
多一个消息队列多一个维护成本,优先在已有的技术栈上进行业务实现。性能扛不住了再换到消息中间件。
唯一注意的是代码做好抽象,以便未来切换。 |
20
z1829909 13 天前
消费端从数据库获取消息 + 标记消息状态 不是原子性的, 会导致一个消息同时被多个地方执行吧
|
21
z1829909 13 天前
超时时间也不是很合理, 因为对于不同的任务, 能忍受的长度不一样, 感觉还是约定一个心跳间隔, 只要消息还在被处理, 就定时更新这条记录某个字段的时间. 这样当这个字段超过心跳间隔没有更新, 视为处理的进程已经无了.
|
![]() |
24
kaffka 13 天前
可以考虑添加成熟的 PG mq 拓展
|
25
spritecn 13 天前
没 redis leftPop+rightPush 好用,还有 3/5/10/15 秒后重试你这个不太好实现,fro update 如果消息处理时间稍长,一直占着连接是个问题
|
![]() |
26
fionasit007 13 天前
@HENQIGUAI #7 用的阿里云 redis ,六七年的数据都还在,不过因为数据量太大不知道有没有丢数据的情况
|
27
spritecn 13 天前
@fionasit007 阿里 1G 一年 500 块,我好像 10 分之 1 都用不到
|
![]() |
28
fionasit007 13 天前
@spritecn #27 个人的话我是肯定不用,挺贵的,不过这样的云服务用着就是省心,阿里云 redis 反正这么多次事故好像都幸免于难
|
![]() |
29
mightybruce 13 天前
如果就是简单的消息队列需要落盘, 不如采用 redis + rocksdb 持久化的项目 kvrocks
https://github.com/apache/kvrocks https://kvrocks.apache.org/docs/supported-commands/ 支持 redis 消息操作。 |
![]() |
30
darrenxyli 12 天前
我们现在就是这么干的,做过压测,瓶颈全在数据库能够支持的 QPS 上面
|
31
Need4more OP @darrenxyli 性能能抗住吗?
|