数据库 – 使用数据库表作为消息/作业队列的最佳方式

前端之家收集整理的这篇文章主要介绍了数据库 – 使用数据库表作为消息/作业队列的最佳方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个数据库表,其中有大约50K行,每行表示需要完成的作业.我有一个程序从数据库提取一个作业,做这个工作并将结果放回数据库. (这个系统现在运行)

现在我想允许多个处理任务执行任务,但确保没有任务完成两次(作为性能问题,不会导致其他问题).因为访问是通过一个新鲜的,我目前的目的是用一些看起来像这样的东西取代所说的鲜花

update tbl set owner=connection_id() where avalable and owner is null limit 1;
select stuff from tbl where owner = connection_id();

BTW;工作人员的任务可能会在获得工作和提交结果之间留下联系.此外,我不期望数据库甚至接近成为瓶颈,除非我把这部分弄乱了(每分钟约5个工作)

有什么问题吗?有没有更好的方法来做到这一点?

注意:“Database as an IPC anti-pattern”在这里只是稍微apropos因为1)我没有做IPC(没有生成行的进程,它们现在已经存在)和2)为反模式描述的主要原因是它的结果在数据库中不必要的加载,因为进程等待消息(在我的情况下,如果没有消息,一切都可以关闭,因为一切都完成)

解决方法

以下是我过去成功使用的:

MsgQueue表模式

MsgId identity -- NOT NULL
MsgTypeCode varchar(20) -- NOT NULL  
SourceCode varchar(20)  -- process inserting the message -- NULLable  
State char(1) -- 'N'ew if queued,'A'(ctive) if processing,'C'ompleted,default 'N' -- NOT NULL 
CreateTime datetime -- default GETDATE() -- NOT NULL  
Msg varchar(255) -- NULLable

您的消息类型是您期望的 – 符合进程(插入)和进程(读取)之间的合同的消息,使用XML或其他选择的表示形式(JSON在某些情况下会很方便,实例).

然后0到n进程可以插入,0到n进程可以读取和处理消息,每个读取进程通常处理单个消息类型.可以运行多个流程类型的实例来进行负载平衡.

读者拉一个消息,并将状态更改为“A”ctive,而它的工作原理.完成后,将状态更改为“C”.根据您是否要保留审计跟踪,它可以删除消息. State =’N’的消息以MsgType / Timestamp顺序拉,所以在MsgType State CreateTime上有一个索引.

变化:
状态为“E”rror.
读者流程代码列.
状态转换的时间戳.

这提供了一个很好的,可扩展的,可见的,简单的机制来执行诸如你所描述的一些事情.如果你对数据库有一个基本的了解,那么它是非常笨重和可扩展的.

评论代码

CREATE PROCEDURE GetMessage @MsgType VARCHAR(8) ) 
AS 
DECLARE @MsgId INT 

BEGIN TRAN 

SELECT TOP 1 @MsgId = MsgId 
FROM MsgQueue 
WHERE MessageType = @pMessageType AND State = 'N' 
ORDER BY CreateTime


IF @MsgId IS NOT NULL 
BEGIN 

UPDATE MsgQueue 
SET State = 'A' 
WHERE MsgId = @MsgId 

SELECT MsgId,Msg 
FROM MsgQueue 
WHERE MsgId = @MsgId  
END 
ELSE 
BEGIN 
SELECT MsgId = NULL,Msg = NULL 
END 

COMMIT TRAN

猜你在找的MsSQL相关文章