本文首发于体内互联网技术微信公众号
引用>
链接:https://mp.weixin.qq.com/s/LGLqEOlGExKob8xEXXWckQ
钱幸川在分布式环境下面,我们经常会通过一定的规则来进行数据分布的定义,本文描述的取模算法和一致性散列(一致性哈希)是通过一定规则产生一个键,对这个关键进行一定规则的运算,得出这个数据该去哪儿。
本文使用软件环境:Java 8
一、数据分布接口定义
<>强概述强>
在分布式环境下面,我们经常会通过一定的规则来进行数据分布的定义,比如用户1的数据存储到数据库1,用户2的数据存储到数据库2…
一般来说,有这么几种常用的方式:
<李>
有一个分布式环境中唯一的中心分发节点,每次在数据存储的时候,都会询问中心节点这个数据该去哪儿,这个分发节点明确告诉这个数据该去哪儿。
李> <李>通过一定规则产生一个键,对这个关键进行一定规则的运算,得出这个数据该去哪儿。本文描述的取模算法和一致性散列,就是这样一种方式。李><>强接口定义强>
<代码>/* * *数据分布哈希算法接口定义 * @author xingchuan.qxc * */公共接口HashNodeService {/* * *集群增加一个数据存储节点 * @param节点 */公共空间addNode(节点);/* * *数据存储时查找具体使用哪个节点来存储 * @param关键 * @return */公共节点lookupNode (String键);/* * *哈希的算法 * @param关键 * @return */公共长哈希(String键);/* * *模拟意外情况断掉一个节点,用于测试缓存命中率 * @param节点 */公共空间removeNodeUnexpected(节点); }代码>二、数据分布算法实现,取模算法
<>强概述强>
取模算法的应用场景描述如下:
需要在集群中实现一个用户数据存储的负载均衡,集群中有n个存储节点,如何均匀的把各个数据分布到这n个节点呢?
实现步骤大概分成两步:
<李>
通过用户的关键来取一个哈希值
李> <李>通过这个哈希值来对存储节点数n进行取模,得出一个指数
李> <李>上面这就个指数是待存储的节点标识李>注意:本文例子我生成散列值的方式,我采用CRC32的方式。
<>强代码实现:强>
<代码>/* * *取模数据分布算法实现 * @author xingchuan.qxc * */公共类NormalHashNodeServiceImpl实现HashNodeService {/* * *存储节点列的表 */私人List节点=new ArrayList<在(); @Override 公共空间addNode(节点节点){ this.nodes.add(节点); } @Override 公共节点lookupNode (String键){ 长k=散列(关键); int指数=(int) (k % nodes.size ()); 返回nodes.get(指数); } @Override 公共长哈希(String键){ CRC32 CRC32=new CRC32 (); crc32.update (key.getBytes ()); 返回crc32.getValue (); } @Override 公共空间removeNodeUnexpected(节点节点){ nodes.remove(节点); } }代码> 通过上述例子我们可以看的到,lookupNode的时候,是要先去取这个关键的CRC32的值,然后对集群中节点数进行取模得到r,最后返回下标为r的节点。
测试代码如下:
<代码> HashNodeService nodeService=new NormalHashNodeServiceImpl (); 节点addNode1=新节点(“xingchuan。node1”、“192.168.0.11”); 节点addNode2=新节点(“xingchuan。node2”、“192.168.0.12”); 节点addNode3=新节点(“xingchuan。node3”、“192.168.0.13”); 节点addNode4=新节点(“xingchuan。node4”、“192.168.0.14”); 节点addNode5=新节点(“xingchuan。node5”、“192.168.0.15”); 节点addNode6=新节点(“xingchuan。node6”、“192.168.0.16”); 节点addNode7=新节点(“xingchuan。node7”、“192.168.0.17”); 节点addNode8=新节点(“xingchuan。node8”、“192.168.0.18”); nodeService.addNode (addNode1); nodeService.addNode (addNode2); nodeService.addNode (addNode3); nodeService.addNode (addNode4); nodeService.addNode (addNode5); nodeService.addNode (addNode6); nodeService.addNode (addNode7); nodeService.addNode (addNode8);//用于检查数据分布情况 Integer> Map<字符串;,countmap=new HashMap<的在(); 节点的节点=零; for (int i=1;我& lt;=100000;我+ +){ 字符串键=String.valueOf(我); 节点=nodeService.lookupNode(关键); 节点。cacheString(键,“TEST_VALUE”); 字符串k=node.getIp (); 整型数=countmap.get (k); 如果(count==null) { 数=1; countmap。把(k,数); 其他}{ 数+ +; countmap。把(k,数); } } system . out。println(“初始化数据分布情况:”+ countmap);一文了散列解一致