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

Add hashing client #59

Merged
merged 23 commits into from Jul 17, 2015
Merged

Add hashing client #59

merged 23 commits into from Jul 17, 2015

Conversation

sontek
Copy link
Contributor

@sontek sontek commented Jun 20, 2015

This is the beginning of how I would expect the hashing client to work. It is built off of #51 so that would need to be merged first.

It is an alternative to #44 and a fix for #52

Things left to do:

  • Implement all client functions (set_many, get_many, incr, etc)
  • Implement failover detection if a client is detected as down
  • Write Integration Tests
  • Write Unit tests
  • Add proper logging
  • Write detailed documentation

For failover support HashClient will support the following settings:

retry_attempts - After retry_attempts has been hit it will mark the server as dead and remove it from the rotation.
retry_timeout - It will wait this long in between retries
dead_timeout - After retry_attempts have been reached it will wait this long before attempting to add the server back into the pool.

Once a server is marked dead the keys that were allocated to it will be rebalanced across the nodes that are still up.

You can use this like this:

from pymemcache.client.hash import HashClient
import time

client = HashClient([
    ('127.0.0.1', 11211),
    ('127.0.0.1', 11212)
])

while True:
    for key in ['foo', 'bar', 'baz']:
        client.set(key, 'bar')
        result = client.get(key)
        print(result)
    time.sleep(1)

@sontek
Copy link
Contributor Author

sontek commented Jun 20, 2015

With babb8c0 I added support for failover. This doesn't recover dead servers yet but it will remove misbehaving servers from the pool.

@sontek
Copy link
Contributor Author

sontek commented Jun 20, 2015

8879147 brings dead servers back into rotation after the dead_timeout

@sontek sontek mentioned this pull request Jun 20, 2015
@sontek
Copy link
Contributor Author

sontek commented Jun 21, 2015

With 2470508 this is fairly feature complete. There is a lot of polish I need to throw in like better logging / error checking and plenty more unit tests but its definitely working.

@sontek sontek changed the title Add hashing client (Work in progress) Add hashing client Jun 21, 2015
@cgordon
Copy link
Collaborator

cgordon commented Jun 22, 2015

I did a quick first pass on the code, and it looks good! I'll take a closer look this week, probably on Wednesday (that's the first day I don't have wall-to-wall meetings). We use a memcache proxy internally, so we haven't needed this, but it's been high on my list of things to add for people that aren't using a proxy.

@sontek
Copy link
Contributor Author

sontek commented Jun 22, 2015

@cgordon Sounds good, what proxy do you guys use? We currently use pylibmc with ketama but have thought about using mcrouter or twemproxy instead

@sontek
Copy link
Contributor Author

sontek commented Jun 22, 2015

@cgordon One thing I thought about with this is making clandestined an optional extra pip install pymemcache[murmur3] or something. Then we can default to using crc32 which is built into the standard library. crc32 isn't perfect but it works

@@ -684,7 +650,7 @@ def _fetch_cmd(self, name, keys, expect_cas):
result[key] = value
else:
raise MemcacheUnknownError(line[:32])
except Exception:
except Exception as e:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the "as e" here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, added that during a debugging session, wasn't supposed to be included in the commit

@cgordon
Copy link
Collaborator

cgordon commented Jun 28, 2015

@sontek The code looks great, I just have a few cosmetic comments and one comment about the overall contract of the methods. Let's talk about that a little bit when you have time.

Also, we're currently using mcrouter, and previously used twemproxy. I haven't been very involved in those decisions, but my understanding is that mcrouter is the better of the two.

@sontek
Copy link
Contributor Author

sontek commented Jul 2, 2015

@cgordon Addressed all of your concerns in a935261, what do you think about the overall contract? I initially was trying to clean the contract up with this but I think we can do that slower with v2 clients and deprecation warnings for the old ones.

I'm not completely against having the hashing client raise an exception but it would mean you would have to opt-in to graceful failover (unless we made it not raise exceptions by default)

@sontek
Copy link
Contributor Author

sontek commented Jul 2, 2015

@cgordon The big question I have about this is if the murmur3/clandestined hash client should be the default. clandestined uses murmur3 C extension for performance, which makes this client no longer pure python.

What I think might be better is provide a less efficient/less consistent default using CRC32 which is pure python and provide an extras (client.ext.murmur3) that can be used like:

pip install pymemcache[murmur3] and then they will get the better client. What do you think? Is it fine to depend on the C extension in clandestined or should we make it optional?

@sontek
Copy link
Contributor Author

sontek commented Jul 2, 2015

@cgordon I decided to go ahead and make a pure python3 version of this and make using the C dependency a documentation issue, here is the PR:

sontek#1

I haven't merged it yet because I want to hear your feedback first.

@cgordon
Copy link
Collaborator

cgordon commented Jul 2, 2015

@sontek I agree with your last comment, that we should make the C dependency possible but optional. I took a look at the branch and it looks great to me.

@cgordon
Copy link
Collaborator

cgordon commented Jul 8, 2015

@sontek Sorry for the long pause, was out of town for the 4th. Would you mind re-basing this change to pick up the documentation and test changes that we've already merged? The rest of the code looks great, but I just want to do one more pass through it before merging.

@cgordon
Copy link
Collaborator

cgordon commented Jul 13, 2015

@sontek I'm ready to merge this change, but it needs to be merged with the documentation and testing changes from the last week. Can you take care of that?

@sontek
Copy link
Contributor Author

sontek commented Jul 13, 2015

@cgordon Yeah, sorry I was busy last week but I'll clean it up in the next few days! :)

@cgordon
Copy link
Collaborator

cgordon commented Jul 13, 2015

@sontek Awesome! Just double checking that I wasn't dropping the ball. Very excited about this change :)

@sontek
Copy link
Contributor Author

sontek commented Jul 16, 2015

@cgordon I think its ready for review! Want to take it for a spin on pinterest codebase to make sure I didn't break any backwards compatibility?

@thedrow
Copy link
Contributor

thedrow commented Jul 16, 2015

clandestined already doesn't compile murmur if on PyPy/PyPy3 and uses a pure python implementation of murmur instead following ewdurbin/clandestined-python#8 so that's a non-issue.

@sontek
Copy link
Contributor Author

sontek commented Jul 16, 2015

@thedrow Yeah, I think the important part is that pymemcache is pure python by default but people can opt-in to using clandestined with C dependencies if they want. This allows us to use universal wheels and deploy with platforms without having to compile anything.

@thedrow
Copy link
Contributor

thedrow commented Jul 16, 2015

can we please add a build job that tests this both with clandestined and without?

1 similar comment
@thedrow
Copy link
Contributor

thedrow commented Jul 16, 2015

can we please add a build job that tests this both with clandestined and without?

@sontek
Copy link
Contributor Author

sontek commented Jul 16, 2015

@thedrow I'll document how to use it instead of just recommending it in the docs

@sontek sontek mentioned this pull request Jul 16, 2015
cgordon added a commit that referenced this pull request Jul 17, 2015
@cgordon cgordon merged commit 63a2d96 into pinterest:master Jul 17, 2015
@cgordon
Copy link
Collaborator

cgordon commented Jul 17, 2015

LGTM. Thanks @sontek!

@cgordon
Copy link
Collaborator

cgordon commented Jul 17, 2015

@sontek, separately, can you switch the readthedocs page to use the master repository so the docs are up to date? It looks like they point at your personal branch right now.

@sontek sontek deleted the add_hashing_client branch July 17, 2015 00:51
@sontek
Copy link
Contributor Author

sontek commented Jul 17, 2015

@cgordon Done! Do you have a readthedocs user? I can add you on there as well

@cgordon
Copy link
Collaborator

cgordon commented Jul 17, 2015

@sontek I just created a user on readthedocs.org, I'm "charles.gordon".

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

Successfully merging this pull request may close these issues.

None yet

3 participants