Tair源码分析_对照表创建流程

Tair 中存放在主节点中的表的创建共分为五步:

1)根据当前m_hash_table表,统计出每一个alive节点上存储的bucket数量(包括master bucket和slave bucket)。假设有节点A,B,C和D,则形成数据如下的map,同时在扫描主节点的过程当中判断主节点是否down,如果不可用,则需要执行第五步快速建表:

注意:

在检查可用节点列表的过程中如果为负载均衡优先策略,group会统计当前可用节点列表,将该列表与m_hash_table一起作为算法的输入。这里对可用节点列表的唯一约束就是,列表中的节点都是alive的。而在位置优先策略中,对可用节点列表的约束加强了,即除了要求列表中的每个节点是alive的外,还需要统计2个机房中dataserver的数量差异不超过一个阈值。(若不满足这个2个约束,在该策略下,对照表是无法正常构建的)

例如:有两个集群一个集群70台机器一个有30台,阈值为0.5,那么该例子中的数量差异为(70-30)/7>0.5故不满足策略建表失败。

其中Xa表示节点A上存储的bucket数量,Xb,Xc,Xd亦然。显然,在启动时Xa = Xb = Xc = Xd = 0;

2) 根据1)中生成的map构建一个index map,即对于hold相同数量bucket的节点存放在同一列表里,举例如下:

3)  给每一个节点分配存储bucket的数量。这一步只是确定每一个节点上可以储存多少个bucket,而不确定到底存储哪一些bucket。对于不同的构建对照表策略,这一步骤是不同的。

在具体给每个节点分配bucket的过程中,假设某个节点上已经分配了b个bucket,现在N个节点已经负责了X个bucket,若b < X/N,则让该节点负责B/N个bucket,否则该节点负责B/N+1个节点。这样做的目的是,在负载均衡的前提下,减少数据迁移。由于允许数据存放多备份,对于某个bucket而言,可能会存储copyCount次,也就是说存在copyCount个bucket的内容是完全一样的,这些一样的backet,我们将其中的一个称作为master bucket,其余的称为slave bucket。那对于master
bucket显然不能存放在过于集中,也需平均分配在每一个节点上。也类似地构造一个map,如下:

其中,第二列中的30和31表示节点A最终要存储的bucket总数。

计算bucket的流程如下图所示:

注意: 在位置安全优先策略中,根据配置掩码pos_mask来将节点分成2个机房,并且统计出每个机房中可用的存储节点数量。当确定出2个机房后,依次确定每个机房中的存储节点的平均负载bucket的数量(记为B), 拥有B个bucket的节点数量,拥有B+1个bucket的节点数量。接下来,为存储节点分配bucket数量,会根据其所在节点的平均bucket数量(每个机房的这3个数据可能是不同的)等数据,确定该节点的负载的bucket数量。

4) 计算每一个节点预期可存储bucket的数量;有了1) ~ 3)步的数据,现在可以计算每一个节点还可以存储的bucket的数量。

5)  快速创建对照表,确定每一个bucket的存储位置。

在初始化的过程中首先为master bucket 安排存储节点,依次按列扫描对照表中主节点所在列,备份节点1所在列,备份节点2所在列。

扫描主节点:当主节点无法使用的时候,将备份桶所在节点提升成为主节点,如果备份桶所在节点都不可用,建表失败。

扫描备份节点:备份节点不可用时,设置为0。

如果快速建表流程执行完成后不必执行第六步。

6)判断这个bucket是否适合存储在该节点

该功能由get_suitable_node函数实现,并且该函数通过调用is_this_node_ok函数。将在这里展开叙述get_suitable_node函数。该函数正如其名,其功能是选择一个合适的节点。虽然,configserver提供两种不同的建表策略,但是选择合适节点的框架是相同的。主要不同点在于,判断某一个节点是否适合存储某个特定bucket的约束是不同的,显然在不同的创建策略下,约束是不同的。这里我们分别来详述:根据第四步我们算出每一个节点还可以存储的bucket的数量:

按照key值从小到大选取节点进行判断。

1. 考察在负载均衡策略下,判断一个节点是否为适合存储某个bucket的约束归纳如下:

1)该节点上存储master bucket的数量约束;

2)该节点上存储总的bucket数量约束;

3)拥有最多bucket的节点总数量约束;

4)欲存储的bucket与其备份bucket不能在同一个节点上。

而选择合适节点采用的约束级别分为4类,根据其约束强弱,依次定义为ALL,POS,BASE和FORCE。如下图所示:

如果不满足节点约束,我们顺序查找其他节点,在上个例子中选择E节点进行验证,如果E不符合标准则顺次寻找下一个,同时修改列表中关于E的数据。

2. 在位置优先策略下,也是通过通过各种约束条件来实现这一功能的。位置安全优先策略将所有节点按位置分为2类。与负载均衡策略所不同的是:首先,判断某个节点是否可以存储某个bucket的时候,需要考虑其所属位置类别的信息,而非负载均衡那种全局信息(例如,A机房中的节点n, 其存储bucket的数量是以该机房中所有节点的平均负载 bucket数量为基准的,而不是以所有机房中的为基准);其次,每种约束级别需满足的约束条件不同;然后,没有添加随机扰动因子。现将这些约束归类如下:

1)在所在机房里,该节点上存储master bucket的数量约束;

2)在所在机房里,该节点上存储总的bucket数量约束;

3)在所在机房了,拥有最多bucket的节点总数量约束;

4)欲存储的bucket与其备份bucket不能在同一个节点上;

5)欲存储的bucket与其备份bucket不能在同一个机房中。

而选择合适节点采用的约束级别分为4类,根据其约束强弱,依次定义为ALL,POS,BASE和FORCE,如下图所示:

通过表中数据,我们可以看出负载均衡策略与位置安全策略在判断某bucket是否适合存储在某个节点上的判断策略还是很不同的。

有了上述介绍,我们就开始介绍描述get_suitable_node函数的工作方式吧。实际上,该函数异常降低约束级别来选择合适的节点。例如,在ALL级别下,无法选择合适的节点,那么就将约束级别降低到POS,直到降低到FORCE级别。在每一级别的约束下,依次遍历一个节点存储bucket容量的map(该map在对照表构建过程的第2步创建),选择一个节点。

通过以上六步我们初步建立了Tair的对照表。

时间: 2024-10-04 11:45:42

Tair源码分析_对照表创建流程的相关文章

tair源码分析——leveldb新增的CompactRangeSelfLevel过程

tair是一个分布式KV存储引擎,当新增机器或者有机器down掉的时候,tair的dataserver会根据ConfigServer生成的新的对照表进行数据的迁移和清理.在数据清理的过程中就用到了在tair中新增的Compaction方式——CompactRangeSelfLevel,顾名思义,这个CompactRangeSelfLevel就是对自己所在(指定)的Level进行一定Key范围的Compaction然后将生成的输出文件也写入到自己所在的Level而不是父层(L + 1).下面我们来

Solr4.8.0源码分析(5)之查询流程分析总述

Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilter的dofilter开始.dofilter包含了对http的各个请求的操作.Solr的查询方式有很多,比如q,fq等,本章只关注select和q.页面下发的查询请求如下:http://localhost:8080/solr/test/select?q=code%3A%E8%BE%BD*+AND+l

tair源码分析——leveldb存储引擎使用

分析完leveldb以后,接下来的时间准备队tair的源码进行阅读和分析.我们刚刚分析完了leveldb而在tair中leveldb是其几大存储引擎之一,所以我们这里首先从tair对leveldb的使用和修改来窥探在这个分布式的存储引擎中是如何将area和bucket持久化到存储,并且方便bucket和area的处理的. 我们首先来看tair中key的结构,我们以大致梳理存储和查询一个KV的流程来确认key的处理.tair_client_api::put直接调用tair_client_impl:

mybatis源码分析之cache创建

XMLMapperBuilder.java //解析<cache /> 配置元素,创建cache对象 private void cacheElement(XNode context) throws Exception {     if (context != null) {       String type = context.getStringAttribute("type", "PERPETUAL");       Class<? exten

(转)linux内存源码分析 - 内存回收(整体流程)

http://www.cnblogs.com/tolimit/p/5435068.html------------linux内存源码分析 - 内存回收(整体流程) 概述 当linux系统内存压力就大时,就会对系统的每个压力大的zone进程内存回收,内存回收主要是针对匿名页和文件页进行的.对于匿名页,内存回收过程中会筛选出一些不经常使用的匿名页,将它们写入到swap分区中,然后作为空闲页框释放到伙伴系统.而对于文件页,内存回收过程中也会筛选出一些不经常使用的文件页,如果此文件页中保存的内容与磁盘中

Tomcat源码分析之—具体启动流程分析

从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息.Catalina.base信息,在initClassLoaders方法中初始化类加载器,然后通过反射初始化org.apache.catalina.startup.Catalina作为catalina守护进程: 一.load Bootstrap中load流程: 反射调用Catalina的load方法

【Spring源码分析】配置文件读取流程

前言 Spring配置文件读取流程本来是和http://www.cnblogs.com/xrq730/p/6285358.html一文放在一起的,这两天在看Spring自定义标签的时候,感觉对Spring配置文件读取流程还是研究得不够,因此将Spring配置文件读取流程部分从之前的文章拆出来单独成为一文. 为了看一下Spring配置文件加载流程,先定义一个bean.xml: 1 <?xml version="1.0" encoding="UTF-8"?>

源码分析 Kafka 消息发送流程(文末附流程图)

温馨提示:本文基于 Kafka 2.2.1 版本.本文主要是以源码的手段一步一步探究消息发送流程,如果对源码不感兴趣,可以直接跳到文末查看消息发送流程图与消息发送本地缓存存储结构. 从上文 初识 Kafka Producer 生产者,可以通过 KafkaProducer 的 send 方法发送消息,send 方法的声明如下: Future<RecordMetadata> send(ProducerRecord<K, V> record) Future<RecordMetada

netty 5 alph1源码分析(服务端创建过程)

参照<Netty系列之Netty 服务端创建>,研究了netty的服务端创建过程.至于netty的优势,可以参照网络其他文章.<Netty系列之Netty 服务端创建>是 李林锋撰写的netty源码分析的一篇好文,绝对是技术干货.但抛开技术来说,也存在一些瑕疵. 缺点如下 代码衔接不连贯,上下不连贯. 代码片段是截图,对阅读代理不便(可能和阅读习惯有关) 本篇主要内容,参照<Netty系列之Netty 服务端创建>,梳理出自己喜欢的阅读风格. 1.整体逻辑图 整体将服务