当前位置:网站首页>消息队列存储消息数据的MySQL表设计
消息队列存储消息数据的MySQL表设计
2022-07-31 00:08:00 【InfoQ】
消息队列存储结构分析
message表
首先,需要一张表去存储消息体,我们先暂定为message表。有几个要点:
- 由于系统架构的设计上数据是进行分组,所以表中需要一个代表分组的字段:shard_id。每一组数据分组集群,其shard_id是固定的。这个类似于kafka的partition分区设计,不同的consumer可以拉取不同的shard,达到加速消费的目的;
- 此处设计每个topic用一张单独的表去存储,即message_{topic},原因是1.MySQL理论上支持的表上亿,能满足topic数量要求 2.用单张表存可以隔离各topic的影响(物理上的逻辑上的)3.使用起来比较简单,因为单表中只可能是该topic的消息,id也可以使用自增的。
所以最终消息表的设计如下:

consume_log表
光有消息表还不够,还需要一张表记录消费状态。也有几个要点:
- 我们支持多个消费者组,每个消费者组共享一条消费进度记录,所以表中需要有group字段来区分是哪个消费者组的消费记录;
- 消费偏移量是最重要的,记录了消费到哪条数据,用offset来标识,即message表中的msg_id,因为msg_id在一个数据分组,一个topic下是严格递增的;
所以最终消息消费记录表设计如下:

如果不考虑太复杂的设计,核心主要就这两个表。
索引分析
我们先从几个高频场景来分析:
发送消息
- 客户端完成分片路由,分配到某个shard,发送消息数据
- 消息队列服务器根据topic找到对应的消息表message_{topic},然后插入数据,msg_id自增
消费消息
- 客户端完成分片的路由,向对应服务器拉取消息,带上参数topic,group
- 查询consumer_log表,根据topic,group通过索引找到对应的数据,取出offset
- 根据offset查询对应的message表,通过主键id,找出下个offset的记录,取出并准备返回
- 更新consumer_log的offset信息
- 返回数据
以上2,3,4在一个事务中执行。
从2可以看出,message_log需要加个topic+group组合索引,命名为idx_topic_group
从3可以看出,message表需要msg_id的索引,但是其本身已经是主键,无需额外增加
消息过期
1.定时任务定期启动(如1天),计算需要清理的日期值,扫描message表,找到需要过期记录,批量更新状态为删除(或者直接物理删除)
此处可以看出为了方便快速扫描到要过期的记录,message的born_date需要加个索引,命名为idx_born_date
索引总结
所以根据分析,需要如下索引:
- message_log表增加idx_topic_group,是topic+group的组合索引
- message表增加idx_born_date,是born_date的索引
边栏推荐
猜你喜欢
随机推荐
一款好用的接口测试工具——Postman
47. 【Pointers and Arrays】
An easy-to-use interface testing tools - the Postman
software development design process
The difference between ?? and ??= and ?. and || in JS
Lambda表达式
【VisDrone数据集】YOLOV3训练VisDrone数据集步骤与结果
机器学习1一回归模型(二)
2022 China Logistics Industry Conference and Entrepreneur Summit Forum will be held in Hangzhou!
从两个易错的笔试题深入理解自增运算符
宽客必备神器-AKShare
mysql中关于存储过程无法实现迁移复制表中数据问题
47.【指针与数组】
joiplay模拟器如何使用
Shell编程条件语句 test命令 整数值,字符串比较 逻辑测试 文件测试
作业:iptables防止nmap扫描以及binlog
A Brief Talk About MPI
正则表达式密码策略与正则回溯机制绕过
Soft Exam Summary
45. [Application of list linked list]








