hw8- 设计消息队列存储消息数据的 MySQL 表格
表:t_queue_meta, t_messages, t_messages_archived, t_queues
t_queue_meta
“load_balancer_info” VARCHAR(255) #把多服务器间分配流量的方式简化为一个字段
“Msg_receiving_method” TINYINT # 0 是消费者被推送消息,1 是消费者主动拉取
“replication_policies” VARCHAR(255) #一台机器的消费者,生产者和队列信息复制到多台机器。当一台机器宕机后,其他机器可以继续生产消费(简化)
t_messages
“id” INT
“service” VARCHAR(255) # msg 来源
“status” TINYINT #消费者修改状态: waiting 是 0,consumed 是 1
“msg_body” VARCHAR(255)
“queue_name” VARCHAR(255)
id 用 INT 就行,unsigned INT 最大值是 4294967295。假设每天有 100 万条 msg,需要 4000 天才能达到 40 亿的 INT 最大值。存档被消费的 msg 一般是为了查询近期的近期异常,所以 INT 足够。
对 id 索引,消费者在 t_queue_meta 获取 last_consumed_msg_id 后,通过 id 查询对应 msg。
如果已被消费的 msg 保存在 t_messages,随着 msg 的堆积,msg 查询时间会增加。为了减少 msg 查询时间,每消费 1k 条,就把这 1k 条消息移到 t_messages_archived。所以 t_messages_archived 跟 t_messages 的字段一致。
当消息被一个队列领取后,把队列名字或 ID 添加上。如果每个消息队列一张表,每条被消费的消息 id 又需要添加一行,增加了不必要的存储。
t_messages_archived
“id” INT
“service” VARCHAR(255) # msg 来源
“status” TINYINT #消费者修改状态: waiting 是 0,consumed 是 1
“msg_body” VARCHAR(255)
t_queue_xxx
“id” INT
“queue_size” SMALLINT
“num_of_consumers” SMALLINT
“num_of_producers” SMALLINT
“owner” VARCHAR(255)
“creation_time” DATETIME
“update_time” DATETIME
“updated_by” VARCHAR(255)
“last_consumed_msg_id” INT
消费者和生产者是为队列服务的,每个队列可以配置不同数量。
锁表,在同一个时间段,只能有一个消费者读写 last_consumed_msg_id(读 last_consumed_msg_id 时就加一)。
last_consumed_msg_id 是 t_messages 的 id。
每个队列都是独立的表,因为 msg 是排在 queue 被消费的,所以 last_consumed_msg_id 也是针对每个 queue 的。如果每次读 last_consumed_msg_id 都锁表,然后所有的 queue 都放同一张表,一个 queue 读 last_consumed_msg_id 会影响其他 queues 同时消费。
评论