C ++ implementation of consistent hash

Source: Internet
Author: User

C ++ implementation of consistent hash

Consistent hash is an algorithm widely used in distributed computing. It is used in many distributed systems, including Amazon Dynamo, memcached, and Riak.

The principle of consistent hash is relatively simple. There are many good articles on the Internet and some related code, but they are not very satisfactory. Therefore, we have implemented one by ourselves. The code is very simple and put on github.

Consistent_hash_map

The consistent hash function is encapsulated in the template class consistent_hash_map:

 
 
  1. template <typename T, 
  2.         typename Hash, 
  3.         typename Alloc = std::allocator<std::pair<const typename Hash::result_type,T > > > 
  4. class consistent_hash_map 

Consistent_hash_map uses the stl map interface. In fact, std: map is used internally to manage and maintain all nodes.

Consistent_hash_map only provides the most basic consistent hash function and does not directly support the concept of virtual nodes. However, the concept of virtual nodes can be easily achieved through the customized T and Hash types. The benefit of this design is that it makes the design and implementation of consitent_hash_map very simple, and leaves users with great flexibility and customization.

The following example describes how to implement virtual nodes.

Template parameters

Member type

 
 
  1. Size_type Hash: Type of the return value of the reslut_type hash Function
  2. Value_type std: pair <const size_type, T> first is the hash value of the node, and second is the node
  3. Iterator a bidirectional iterator to value_type bidirectional iterator
  4. Reverse_iterator <iterator> reverse iterator

Member function

 
 
  1. Std: size_t size () const;
  2. Returns the number of nodes in consistent_hash_map.
  3.  
  4. Bool empty () const;
  5. Determine whether consistent_hash_map is null
  6.  
  7. Std: pair <iterator, bool> insert (const T & node );
  8. Insert a node. If the bool variable in the return value is true, iterator is the iterator pointing to the inserted node. If bool is false, insertion fails.
  9. Insertion failed because the node already exists or the hash value of the node conflicts with other nodes.
  10.  
  11. Void erase (iterator it );
  12. Delete a specified node through the iterator.
  13.  
  14. Std: size_t erase (const T & node );
  15. Deletes a specified node by using the node value.
  16.  
  17. Iterator find (size_type hash );
  18. Find the iterator for the corresponding node in consistent_hash by passing in the hash value.
  19.  
  20. Iterator begin ();
  21. Iterator end ();
  22. Returns the corresponding iterator
  23.  
  24. Reverse_iterator rbegin ();
  25. Reverse_iterator rend ();
  26. Returns the corresponding reverse iterator.

Example of a virtual node

The complete code of the entire example is here.

In this example, we first define the virtual node type and its corresponding hasher.

 
 
  1. # Include <stdint. h>
  2. # Include <boost/format. hpp>
  3. # Include <boost/crc. hpp>
  4.  
  5. # Include "consistent_hash_map.hpp"
  6.  
  7. // List of all hosts
  8. Const char * nodes [] = {
  9. "192.168.1.100 ",
  10. "192.168.1.101 ",
  11. "192.168.1.102 ",
  12. "192.168.1.103 ",
  13. "192.168.1.104"
  14. };
  15.  
  16. // Virtual node
  17. Struct vnode_t {
  18. Vnode_t (){}
  19. Vnode_t (std: size_t n, std: size_t v): node_id (n), vnode_id (v ){}
  20.  
  21. Std: string to_str () const {
  22. Return boost: str (boost: format ("% 1%-% 2%") % nodes [node_id] % vnode_id );
  23. }
  24.  
  25. Std: size_t node_id; // host ID, index of the host in the host list
  26. Std: size_t vnode_id; // virtual node ID
  27.  
  28. };
  29.  
  30. // Hasher, using CRC32 as the hash algorithm. Note that you need to define result_type.
  31. Struct crc32_hasher {
  32. Uint32_t operator () (const vnode_t & node ){
  33. Boost: crc_32_type ret;
  34. Std: string vnode = node. to_str ();
  35. Ret. process_bytes (vnode. c_str (), vnode. size ());
  36. Return ret. checksum ();
  37. }
  38. Typedef uint32_t result_type;
  39. };

Generate 100 virtual nodes for each host and add them to consistent_hash_map.

 
 
  1. typedef consistent_hash_map<vnode_t,crc32_hasher> consistent_hash_t; 
  2. consistent_hash_t consistent_hash_; 
  3.  
  4. for(std::size_t i=0;i<5;++i) { 
  5.     for(std::size_t j=0;j<100;j++) { 
  6.         consistent_hash_.insert(vnode_t(i,j)); 
  7.     } 

Find the vnode and host corresponding to a hash value:

 
 
  1. Consistent_hash_t: iterator it;
  2. It = consistent_hash _. find (290235110 );
  3. // It-> first is the hash value of the node, and it-> second is the virtual node.
  4. Std: cout <boost: format ("node: % 1%, vnode: % 2%, hash: % 3% ")
  5. % Nodes [it-> second. node_id] % it-> second. vnode_id % it-> first <std: endl;

Traverse all vnodes in consistent_hash and count the number of keys of each virtual node and the number of keys contained in each host:

 
 
  1. Std: size_t sums [] = {0, 0, 0 };
  2. Consistent_hash_t: iterator I = consistent_hash _. begin (); // The first node
  3. Consistent_hash_t: reverse_iterator j = consistent_hash _. rbegin (); // The Last Node
  4. Std: size_t n = I-> first + UINT32_MAX-j-> first; // calculate the number of keys contained in the first Node
  5. Std: cout <boost: format ("vnode: % 1%, hash: % 2%, contains: % 3% ")
  6. % I-> second. to_str () % I-> first % n <std: endl;
  7. Sums [I-> second. node_id] + = n; // update the number of keys contained in the host.
  8.  
  9. // Calculate the number of keys contained in all remaining nodes and update the number of keys included in the host.
  10. Uint32_t priv = I-> first;
  11. Uint32_t cur;
  12. Consistent_hash_t: iterator end = consistent_hash _. end ();
  13. While (++ I! = End ){
  14. Cur = I-> first;
  15. N = cur-priv;
  16. Std: cout <boost: format ("vnode: % 1%, hash: % 2%, contains: % 3% ")
  17. % I-> second. to_str () % cur % n <std: endl;
  18. Sums [I-> second. node_id] + = n;
  19. Priv = cur;
  20. }
  21.  
  22. For (std: size_t I = 0; I <5; ++ I ){
  23. Std: cout <boost: format ("node: % 1% contains: % 2%") % nodes [I] % sums [I] <std: endl;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.