Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HashCodeMessageExtractor can create inconsistent ShardId's #3361

Closed
IanPattersonMuo opened this issue Mar 15, 2018 · 1 comment
Closed

HashCodeMessageExtractor can create inconsistent ShardId's #3361

IanPattersonMuo opened this issue Mar 15, 2018 · 1 comment

Comments

@IanPattersonMuo
Copy link

Akka.Net 1.3.5

I have a question around the HashCodeMessageExtractor, it uses a GetHashCode on the EntityId which is a string. The problem is that this would appear lead to inconsistent ShardIds between runs of the code. So for example if I create an envelope with an EntityId of 1, the HashCodeMessageExtractor produce a ShardId of 10 consistently for the lifetime of run of the code. However restarting the same code will produce a different ShardId for the same EntityId. When using multiple nodes this would break as the ShardIds for a given EntityId would not be consistent across all of the nodes. This appears to be caused by using the GetHashCode on the EntityId as a String as they not guaranteed to be consistent outside of the app domain.

https://msdn.microsoft.com/en-us/library/system.string.gethashcode(v=vs.110).aspx

The hash code itself is not guaranteed to be stable. Hash codes for identical strings can differ across versions of the .NET Framework and across platforms (such as 32-bit and 64-bit) for a single version of the .NET Framework. In some cases, they can even differ by application domain.

As a result, hash codes should never be used outside of the application domain in which they were created, they should never be used as key fields in a collection, and they should never be persisted.

A simple unit test where the output of the ShardId is verified for consistency shows the problem.

            var extractor = new MessageExtractor();
            var env = new ShardEnvelope(1, "test");
            Assert.Equal("25", extractor.ShardId(env));    

This may work the first time, but subsequent runs of the test fail.

@Horusiath
Copy link
Contributor

Horusiath commented Mar 15, 2018

@IanPattersonMuo thanks for the info. This indeed may be an issue. We've already met this problem (just in different pieces of project). The fix is quite fast and straightforward - in the following line we should replace GetHashCode with consistent hashing:

return (Math.Abs(id.GetHashCode()) % MaxNumberOfShards).ToString();

Inside akka.net there's a MurmurHash.StringHash method, which can be used to generate consistent hashes for strings - we already use them in other parts of the project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants