# Consistent hashing for upstreams

**URL:** <https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044>\
**Category:** NGINX\
**Created:** [March 19, 2012, 5:54pm UTC](https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044 "2012-03-19T17:54:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [March 19, 2012, 5:54pm UTC](https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044/1 "2012-03-19T17:54:58Z")

</div>

Has anybody used ngx\_http\_upstream\_consistent\_hash with newer nginx  
releases (\>1.0)?

If so, is it possible to use ngx\_http\_upstream\_consistent\_hash with  
HTTP-based back-ends, or does it only work with memcahe backends? The  
documentation isn’t at all clear.

We want to load-balance multiple static file servers behind nginx, and  
basing the upstream chosen on consistent hash will drastically increase  
the filesystem cache hit ratios the back-end servers, while preventing a  
“thundering herd” issue when one fails. Basically you get to use all of  
your RAM amongst the back ends for cache, rather than having the same  
objects in the cache of multiple back end servers.

I thought of trying to use map directives and regexes to pick a back  
end, but handling weighting and failover makes this a complex and  
therefore brittle approach. Could consistent hashing for upstreams be  
achieved with embedded lua or perl?

I know HAproxy has consistent hashing features for this use case (as do  
almost all commercial load balancers), but I would prefer not adding  
layers to my stack if it can be avoided. We’re already using nginx and  
proxy\_cache and it has been rock-solid and stable for us.

Posted at Nginx Forum:

> **[consistent hashing for upstreams](https://forum.nginx.org/read.php?2,224038,224038#msg-224038)**
>
> Has anybody used ngx\_http\_upstream\_consistent\_hash with newer nginx releases (\>1.0)? If so, is it possible to use ngx\_http\_upstream\_consistent\_hash with HTTP-based back-ends, or does it only work with memcahe backends? The documentation isn't at...

---

<div class="post-metadata">

**Author:** ![rmalayter](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/a4c791/32.png) [@rmalayter](https://www.ruby-forum.com/u/rmalayter)\
**Post date:** [March 19, 2012, 8:10pm UTC](https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044/2 "2012-03-19T20:10:09Z")

</div>

> achieved with embedded lua or perl?  
> Here’s a simple approach on consistent hashing with embedded perl:  
> [2124034’s gists · GitHub](https://gist.github.com/2124034)

---

<div class="post-metadata">

**Author:** ![rmalayter](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/a4c791/32.png) [@rmalayter](https://www.ruby-forum.com/u/rmalayter)\
**Post date:** [March 19, 2012, 11:09pm UTC](https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044/3 "2012-03-19T23:09:14Z")

</div>

> The only potential issues I foresee are:

> 1. performance, as this perl will be called for 1000+ requests per  
> second, and there are going to be potentially many upstream blocks.  
> Maybe Digest::MurmurHash would help with performance instead of MD5  
> (it’s supposedly 3x faster in Perl than Digest::MD5 while using far less  
> state). A native hash ring implementation in C would obviously be far  
> more performant.

Couple of microseconds per request isn’t something to worry about here.

> 1. a single backup server is problematic, but that can be fixed by  
> adding more backups to the upstream blocks I think, or doing an error  
> location that hashes again to find a new upstream. Not sure if a server  
> being down would cause it to fail inside all upstream blocks it appears  
> though, which might mean some very slow responses when a server goes  
> offline.

But at least it’s simple.

> 1. Perl module is still marked as experimental, which scares me

Don’t be scared, it’s not really experimental. Build it with  
relatively modern perl and you’ll be fine.

---

<div class="post-metadata">

**Author:** ![rmalayter](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/a4c791/32.png) [@rmalayter](https://www.ruby-forum.com/u/rmalayter)\
**Post date:** [March 19, 2012, 10:16pm UTC](https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044/4 "2012-03-19T22:16:32Z")

</div>

Alexandr G. Wrote:

> Here’s a simple approach on consistent hashing  
> with embedded perl:  
> [2124034’s gists · GitHub](https://gist.github.com/2124034)

Interesting. Clearly one could generate the upstream blocks via script.

The only potential issues I foresee are:  
1) performance, as this perl will be called for 1000+ requests per  
second, and there are going to be potentially many upstream blocks.  
Maybe Digest::MurmurHash would help with performance instead of MD5  
(it’s supposedly 3x faster in Perl than Digest::MD5 while using far less  
state). A native hash ring implementation in C would obviously be far  
more performant.  
2) a single backup server is problematic, but that can be fixed by  
adding more backups to the upstream blocks I think, or doing an error  
location that hashes again to find a new upstream. Not sure if a server  
being down would cause it to fail inside all upstream blocks it appears  
though, which might mean some very slow responses when a server goes  
offline.  
3) Perl module is still marked as experimental, which scares me

I will give it a good long-term load test though, it might just be good  
enough!

## Thanks!

RPM

Posted at Nginx Forum:  
[http://forum.nginx.org/read.php?2,224038,224045#msg-224045](http://forum.nginx.org/read.php?2,224038,224045#msg-224045)

---

<div class="post-metadata">

**Author:** ![rmalayter](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/a4c791/32.png) [@rmalayter](https://www.ruby-forum.com/u/rmalayter)\
**Post date:** [March 20, 2012, 2:55am UTC](https://www.ruby-forum.com/t/consistent-hashing-for-upstreams/218044/5 "2012-03-20T02:55:12Z")

</div>

Hi,

On Tue, Mar 20, 2012 at 12:54 AM, rmalayter [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> “thundering herd” issue when one fails. Basically you get to use all of  
> layers to my stack if it can be avoided. We’re already using nginx and  
> proxy\_cache and it has been rock-solid and stable for us.

Please try this fork:

> **[GitHub - yaoweibin/ngx\_http\_consistent\_hash: a module which enables the nginx to use the same...](https://github.com/yaoweibin/ngx_http_consistent_hash)**
>
> a module which enables the nginx to use the same consistent hashing distribution for memcache servers as the php memcache module

BTW, this module will be officially supported by the Tengine team soon.

Regards,
