rebus-org / Rebus

:bus: Simple and lean service bus implementation for .NET
https://mookid.dk/category/rebus
Other
2.32k stars 363 forks source link

SqlServerSagaStorage without GUIDs #1027

Open gscher opened 2 years ago

gscher commented 2 years ago

I'm wondering whether there are any alternatives to the uniqueidentifier data type for tracking sagas when using SQL Server as persistence layer?

We had some issues with GUIDs in the past, mostly surfacing on the database level including index fragmentation, page splits, bad I/O etc. And all these issues combined resulted in rather strict internal guidelines that basically prevent us from using anything close to GUIDs as primary keys or as part of indexes. Hence, I fear we won't be able to use the existing default implementation SqlServerSagaStorage.

When looking at the ISagaStorage interface and its default implementation, I think there might be the chance to replace the GUID with an int or bigint in a custom implementation of ISagaStorage and then make sure to adapt the queries and indexes as necessary. One issue I see is that for new sagas, GUIDs are created on the client side, so we probably would need to find a way to let the database return us a new unique ID to be used as GUID replacement? Maybe I'm missing some other use cases where the GUID needs to be known or derived upfront, or other parts of Rebus where we would need to tweak, so I would really appreciate some pointers here.

Obviously, I'm are also interested if we are the only ones doing a poor job with GUIDs, or is this a 'thing' somewhere else as well? :)

We would also be interested in contributing if we are able to find a reasonable way of persisting sagas without relying on GUIDs.

devbased commented 2 years ago

You could generate sequential GUIDs as MassTransit does.

dazinator commented 8 months ago

Obviously, I'm are also interested if we are the only ones doing a poor job with GUIDs, or is this a 'thing' somewhere else as well? :)

No you've got it spot on imho. I think there are people inexperienced with scaling apps where they've used indexes on non sequentual guids and to many demo apps promoting this paattern, like for DDD often the pattern is that when generating "domain events" you give each event its own random GUID. This can be fine as long as the GUID is not needed to be indexed in the DB for query purposes or your data volumes are so low as not to be a concern - but often the material / demo in question never goes on to discuss that. I think having a policy to catch this, and prevent it from later causing issues is probably a good thing.

Typically you should be able too use newsequentialid as a replacement. I think it would be valuable submitting a PR to allow this to be configured as the id strategy but not sure if @mookid8000 agrees or has other ideas / plans.

mookid8000 commented 8 months ago

Hi @dazinator , if you'd like to separate the saga ID generation out into something like an ISagaIdGenerator and make the strategy pluggable, that would be pretty awesome.

Let me know if you need any pointers. Since this is going to be part of the Rebus core, I will probably have strict requirements around the implementation, but it should be pretty straightforward to build.