写点什么

架构师训练营第 1 期第 5 周作业

用户头像
好吃不贵
关注
发布于: 2020 年 10 月 25 日
架构师训练营第 1 期第 5 周作业

作业题目:自己实现一个 consistent hash。10 个节点,100 万个虚拟节点。


以下是 github 上的一致性 hash 的 cpp 代码。学习了代码实现,部分做了修改,因为虚拟节点多,所以注释掉了大部分打印,防止打印比较久。

一致性 hash 封装在模板类 consistent_hash_map 中,放在头文件,cpp 直接包含即可。使用了 stl map 风格的接口,内部用 map 来维护和管理所有节点。本身并不支持虚拟节点,而是实际的节点,但可以通过定制 T 和 hash 类型实现。

模板参数是:

T 是 consistent hash 的节点类型。

Hash 是一元函数对象。接收 T 类型对象作为参数,返回整型作为 hash 值,用于内部排序。

Alloc 是内存分配器,默认是 std::allocator。


#include <algorithm>#include <functional>#include <list>#include <map>#include <string>
#ifndef __CONSISTENT_HASH_H__#define __CONSISTENT_HASH_H__
template <typename T, typename Hash, typename Alloc = std::allocator<std::pair<const typename Hash::result_type, T>>>class consistent_hash_map { public: typedef typename Hash::result_type size_type; typedef std::map<size_type, T, std::less<size_type>, Alloc> map_type; typedef typename map_type::value_type value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename map_type::iterator iterator; typedef typename map_type::reverse_iterator reverse_iterator; typedef Alloc allocator_type;
consistent_hash_map() {} ~consistent_hash_map() {}
std::size_t size() const { return nodes_.size(); }
bool empty() const { return nodes_.empty(); }
std::pair<iterator, bool> insert(const T& node) { size_type hash = hasher_(node); return nodes_.insert(value_type(hash, node)); }
void erase(iterator it) { nodes_.erase(it); }
std::size_t erase(const T& node) { size_type hash = hasher_(node); return nodes_.erase(hash); }
iterator find(size_type hash) { if (nodes_.empty()) { return nodes_.end(); }
iterator it = nodes_.lower_bound(hash);
if (it == nodes_.end()) { it = nodes_.begin(); }
return it; }
iterator begin() { return nodes_.begin(); } iterator end() { return nodes_.end(); } reverse_iterator rbegin() { return nodes_.rbegin(); } reverse_iterator rend() { return nodes_.rend(); }
private: Hash hasher_; map_type nodes_;};
#endif
复制代码

实现虚拟节点的例子代码如下。例子用了 10 个节点,每个主机生成 1000000 个虚拟节点,然后加入 consistent_hash_map 中:


#include <stdint.h>#include <boost/crc.hpp>#include <boost/format.hpp>#include <boost/functional/hash.hpp>#include <iostream>#include <string>
#include "consistent_hash_map.hpp"
constexpr int NODE_COUNT = 100;constexpr int VIRTUAL_NODE_COUNT = 1000000;
const char* nodes[] = {"192.168.1.100", "192.168.1.101", "192.168.1.102", "192.168.1.103", "192.168.1.104", "192.168.1.105", "192.168.1.106", "192.168.1.107", "192.168.1.108", "192.168.1.109"};
struct vnode_t { vnode_t() {} vnode_t(std::size_t n, std::size_t v) : node_id(n), vnode_id(v) {}
std::string to_str() const { // return boost::str(boost::format("%1%-%2%") % nodes[node_id] % vnode_id); return "test"; }
std::size_t node_id; std::size_t vnode_id;};
struct crc32_hasher { uint32_t operator()(const vnode_t& node) { boost::crc_32_type ret; std::string vnode = node.to_str(); // std::cout << "vnode:" << vnode << std::endl; ret.process_bytes(vnode.c_str(), vnode.size()); return ret.checksum(); } typedef uint32_t result_type;};
int main(int argc, char const* argv[]) { typedef consistent_hash_map<vnode_t, crc32_hasher> consistent_hash_t; consistent_hash_t consistent_hash_;
for (std::size_t i = 0; i < NODE_COUNT; ++i) { for (std::size_t j = 0; j < VIRTUAL_NODE_COUNT; j++) { consistent_hash_.insert(vnode_t(i, j)); } }
{ // std::cout << "=========================================================" << std::endl; std::size_t sums[] = {0, 0, 0, 0, 0}; consistent_hash_t::iterator i = consistent_hash_.begin(); consistent_hash_t::reverse_iterator j = consistent_hash_.rbegin(); std::size_t n = i->first + UINT32_MAX - j->first; // std::cout << boost::format("vnode:%1%,hash:%2%,contains:%3%") % i->second.to_str() % i->first % // n // << std::endl; sums[i->second.node_id] += n;
uint32_t priv = i->first; uint32_t cur; consistent_hash_t::iterator end = consistent_hash_.end(); while (++i != end) { cur = i->first; n = cur - priv; // std::cout << boost::format("vnode:%1%,hash:%2%,contains:%3%") % i->second.to_str() % cur % n // << std::endl; sums[i->second.node_id] += n; priv = cur; }
// for (std::size_t i = 0; i < NODE_COUNT; ++i) { // std::cout << boost::format("node:%1% contains:%2%") % nodes[i] % sums[i] << std::endl; // } }
{ consistent_hash_t::iterator it; it = consistent_hash_.find(290235110); // std::cout << boost::format("node:%1%,vnode:%2%,hash:%3%") % nodes[it->second.node_id] % // it->second.vnode_id % it->first // << std::endl; }
return 0;}
复制代码


参考链接:https://github.com/ioriiod0/consistent_hash


注:如有侵权,请联系作者删除。

用户头像

好吃不贵

关注

还未添加个人签名 2018.11.20 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第 1 期第 5 周作业