-
Notifications
You must be signed in to change notification settings - Fork 816
Support consistent hashing in cache.NewMemcachedClient #1554
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
Support consistent hashing in cache.NewMemcachedClient #1554
Conversation
aeb25bf
to
38ea79e
Compare
I have a question about the sort of the hostnames returns from DNS. Are the numbers zero padded? Does the sort handled going from 10 to 11 servers correctly? Otherwise LGTM |
@tomwilkie The numbers aren't zero-padded; the sort won't handle it correctly and a lot of keys will start being moved after scaling past 10 servers. If that's a problem that needs to be addressed, most flexible solution would be to abandon the jump hash and use a different consistent hashing algorithm that doesn't depend on the order of the DNS names. Switching over to the rendezvous hash would handle arbitrarily ordered servers and allow to scale past 10 servers cleanly (i.e., only 1/N keys moved). |
FWIW I would look at something like https://github.com/facebook/mcrouter to scale memcached - this allows multiple replicas of the same data and back-filling data that is in one replica but not another. |
@rfratto could we use a natural sort on the domain names instead? https://godoc.org/bitbucket.org/zombiezen/cardcpx/natsort @bboreham Yeah I checked that out before we started this work - I don't think mcrouter actually helps the case we're looking at here; it suffers from the same problem that increasing the size of the pool resulting in a complete invalidation of the cache. And it doesn't do service discovery... If it was in go I'd have said add these features there, but this seems easier. |
@tomwilkie Ah, that’s cool, I didn’t know about natural sorts. That will fix our problem here. |
There are 3rd-party (4th-party?) projects that do that, e.g. https://github.com/mlaccetti/mcrouter-kubernetes-provisioner, https://github.com/ianlewis/memcached-operator |
accb411
to
8764c0c
Compare
@gouthamve @tomwilkie PTAL, the natural sort works as expected with StatefulSet DNS names. |
Can you find out what the result of an SRV lookup looks like on k8s, and make sure the natsort does the right thing? A unit test would be great. |
4a42f81
to
cdbada5
Compare
@tomwilkie PTAL. SRV lookup for a headless service backed by a stateful set in k8s looks like this:
|
ba17eae
to
f29c818
Compare
cache.MemcachedClientConfig has been updated with a new boolean variable ConsistentHash, available as consistent_hash in yaml and memcached.consistent-hash as a flag. When ConsistentHash is true, the MemcachedClient will use the newly created cache.MemcachedJumpHashSelector for server distribution. Jump hash is a consistent hashing algorithm that given a key and a number of buckets, returns a bucket number in the range [0, numBuckets). Adding or removing a bucket only results in 1/N keys being moved. A downside to using jump hash is that buckets can not be arbitrarily removed from the list; it effectively acts as a stack and only supports adding or removing buckets from the end. Therefore, jump hash is most effective when the servers are ordered and where the order is predicable. A good example of this is Kubernete's StatefulSet with a headless service. DNS names will be in the form memcached-[pod number], where the pod number will grow and shrink in the way that numBuckets does. There will never be a gap in the servers when scaling up or down. Signed-off-by: Robert Fratto <[email protected]>
Signed-off-by: Robert Fratto <[email protected]>
TestNatSort has been added to validate that the natsort package works as expected when sorting a list of servers that are returned from SRV lookups. The example used corresponds to SRV records that would be returned for a k8s headless service backed by a StatefulSet. Signed-off-by: Robert Fratto <[email protected]>
Signed-off-by: Tom Wilkie <[email protected]>
f29c818
to
1b76cee
Compare
This PR adds support for consistent hashing of memcached servers by server DNS name.
Support for this is behind a boolean configuration variable in the client config, available in the flags as
-memcached.consistent-hash
The use of jump hash enables consistent hashing when adding or removing a memcached server only requires 1/N keys being moved. A downside to jump hash in particular is that the order of DNS names used for the servers must be predictable to maximize efficiency. A good example of a predictable DNS name is
memcached-[pod index].cortex.svc.cluster.local
, which is what Kubernetes would create when running memcached as a StatefulSet on a headless service./cc @tomwilkie