人人网UGC海量存储系统Nuclear介绍 – 原理展望篇

原理篇

Nuclear系统构建于java之上,NIO组件使用Netty,数据序列化使用google的Protocol Buffers,Spring当然是用了的。下图是Nuclear系统内部的一个预览:

Nuclear Overview

嗯……其实这张图对各位看官意义不大,只是罗列出了Nuclear中的各个组件及简单的层次关系。下面着重分析分区、节点增减、路由的原理。

分区

前文讲到,我们是一个分布式的Key-Value存储系统,那么key对应的数据分布在什么节点上,需要遵守一定的规则。熟悉Memecached Client的同学一定清楚一致性Hash的应用,没错,Hash Ring就是我们的不二选择。在Nuclear中,数据分布在0~264的Hash Ring上,Nuclear集群初始化的时候,根据节点数均分整个Hash Ring。如下图所示:

Snap3

在N=3时,A,B,C三个节点的配置就是系统需要的最少节点了。Nuclear中,顺时针的开始值和结束值确定一个分区管理的数据范围,同时规定分区的范围左开右闭。因此,如上图,我们记录A,B,C分别管理的分区范围是:
A {[c,a],[b, c],[a,b]}
B {[a,b],[c,a],[b,c]}
C {[b,c],[a,b],[c,a]}
可以看出,A处理管理自己的分区数据外,还会把自己管理的数据顺时针往前复制到2(N-1)个节点中。

节点变更

Nuclear增加节点时需要制定目标节点的名称,即增加的节点是用来分担目标节点的负载的。这点不同于Dynamo的分区策略,节点增加的时候会均衡的从现有的节点窃取分区,Nuclear中增加的节点只会影响到邻近的三个节点。加入我们在上面的例子中增加一个新节点N后分区图如下所示:

Snap2

记录N,A,B,C管理的分区如下:
N {[c,n],[b,c],[a,b]}
A {[n,a],[c,n],[b,c]}
B {[a,b],[n,a],[c,n]}
C {[b,c],[a,b],[n,a]}
Nuclear的分区管理模块将自动的计算出需要同步到N上的数据:
A [a,b] => N
B [b,c] casino online => N
C [c,n] => N
各位看官不难明白,其实就是把A,B,C不再需要的数据挪给新的节点了。删、替换节点原理大同小异,不再冗述。

路由

Nuclear提供服务器端路由策略,Client的请求随机落在Node节点上,由接收到请求的节点处理后续的逻辑。相对于Client端路由来说,优点是Client无需知道Nuclear集群元数据,易于维护;缺点是会造成一定程度的延时,不过我们的测试结果显示延时在可接受范围之内。

两个设计上的Tips贡献给大家:
1. 万事皆异步
我们在编码的过程中走了一些弯路,同步的操作在高并发的情况下带来的性能下降是非常恐怖的,于是乎,Nuclear系统中任何的高并发操作都消除了Block。no waiting, no delay。

2. 根据系统负载控制后台线程的资源占用
Nuclear系统中有不少的后台线程默默无闻的做着各种辛苦的工作,但是它们同样会占用系统资源,我们的解决方案是根据系统负载动态调整线程的运行和停止,并达到平衡。

展望篇

Nuclear中计划在不远的将来(不远有多远?)实现如下功能:

  1. Eventually Consistent 最终的一致性问题,在保重数据完整性上至关重要。
  2. Async Store 异步数据库存储,各位可以参考:adbcjasync-mysql-connector
  3. Read Cache
  4. Balance Monitor 建立集群的负载监控体系,在新节点加入的时候可以自动去平衡负载最高的节点

转载自:http://ugc.renren.com/2010/01/28/ugc-nuclear-guide-theory/

anyShare赠人玫瑰,手有余香,分享知识,德艺双馨!
          

无觅相关文章插件,快速提升流量