NServiceBus will make the process of setting up the queues much easier. This (the msmq design) is a common pattern to use for this operation, but it is not your only option.
You can also look at SQL Server Service Broker and many other similar technologies to do this same thing.
There are a couple of caveats you should be aware of with MSMQ:
- Transactional Queues cannot be load balanced, unless they are a Active Directory Domain Queue. The big take away here is that the queue must be on a single machine, which means that it is susceptible to loss if the machine is lost (either permenantly or temporarily). This is not a huge concern but one to take note of
- MSMQ queues have two "modes" transactional and non-transactional. Transactional queues are the only ones that guarantee message delivery.
- MSMQ messages are themselves limited to 4MB (or so) natively, and you must manage serialization yourself (though default .NET serialization is pretty easy with the XML serializer). If you want messages larger than 4MB you will need to either manage them outside of the queue, or manage multiple queued messages yourself (BizTalk has a way of doing this so its not a huge issue). 4MB should be plenty big for your needs.
- Once you "accept" a message from the queue it is immediately removed, so depending on your design this might be an issue. It will be possible for your consumers to "accept" a message, fail and have the message not make it back to the queue.
Having said all of that, MSMQ is very reliable and stable, if you plan your implementation out and use it for the messaging part of your process, not the data storage part.
Finally, as an alternative to your current proposal (and so you have something to compare to) you could implement your described scenario directly from the DB. As a napkin sketch:
- A process runs in the db and populates a table with "pending" rows to process, assign each one a unique id (guid, etc)
- Create a SP which returns "n" of these rows to a caller, and marks those same rows as "pending" in the db. If there are no rows it returns 0 or -1, or whatever
- Create a SP which recieves a list of row ids, and the disposition (completion info) for the job and updates the pending table, either marking them done or removing them and logging the completion data
- Your consumers call into the first SP and request a set of rows to work on
- Your consumers process the rows
- Your consumers call the second SP to log the work done
You could then periodically run reports to see what work was done and still pending, and if needed change rows from pending to waiting, etc. This would have roughly the same scaling as your other solution, remove a layer of indirection (which may be a bad thing, depending) and provide a slightly more linear process. This process is essentially how Service Broker works (very distilled of course).
It all depends on how you feel most comfortable implementing this. I have done it both ways, and both have their pros and cons.