KvBuffer
hadoop的环形缓冲区
Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方。要想理解MapReduce, Shuffle是必须要了解的。从这周开始,开始学习shuffle的整个过程,今天带来的是hadoop环形缓冲区的理解
代码(初始化环形缓冲区)
// 存储元数据信息 **注意这是一个intbuffer 存储int
private IntBuffer kvmeta;
//环形缓冲区的数组
byte[] kvbuffer;
//首先通过配置文件得到了环形缓冲区的大小,默认情况下是100M
final int sortmb = job.getInt(JobContext.IO_SORT_MB, 100);
int maxMemUsage = sortmb << 20; //通过位运算把100m转化成对应的字节
kvbuffer = new byte[maxMemUsage]; //创建一个buffer
bufvoid = kvbuffer.length;
kvmeta = ByteBuffer.wrap(kvbuffer) //通过伪装得到一个元数据数组
.order(ByteOrder.nativeOrder()) //这个数组是int 所以总大小/4
.asIntBuffer(); //100M位例值为26214400
setEquator(0); //设置初始的赤道的位置为0(稍后解释赤道)
bufstart = bufend = bufindex = equator; //初始化buffer参数
kvstart = kvend = kvindex; //初始化meta参数
private void setEquator(int pos) {
//在这里pos为0, 所以aligned=0
final int aligned = pos - (pos % METASIZE);
kvindex = ((aligned - METASIZE + kvbuffer.length) % kvbuffer.length) / 4;
}
解释:可以这么理解,通过读取配置文件获得一个100M大小的byte数据,然后这个数据再通过包装,包装成了一个intbuffer,此时,kvbuffer和kvmeta在内存中的指向都是用一个数组,既100m大小的byte数组。通过kvindex 和 kvmate 就可以看到,包装之后的kvindex是指向数组的末尾,由此我们可以知道,我们的元数据信息是从末尾到头的顺序写入的。
从网上大部分都是这张图,也算准确。
1,首先环形缓冲区以中心赤道为起点,开始向两边读数据
2,元数据信息是整数,是因为,它存储分区信息(分区信息是整数)和这个KVbuffer在数组的位置,每个元素信息是16字节
//写入过程中间的代码
int keystart = bufindex;
//序列化之后写入buffer,写入后获得新的bufindex
keySerializer.serialize(key);
//此时会判断是否已经连续写完,如果在内存满的时候进行写入,此时有可能空间不足,导致数据写入一半,为了保证数据完全写入此时判断并处理(之后会提到详细过程)
if (bufindex < keystart) {
// wrapped the key; must make contiguous
bb.shiftBufferedKey();
keystart = 0;
}
写入value的原理相同
final int valstart = bufindex;
valSerializer.serialize(value);
kvmeta.put(kvindex + PARTITION, partition);
kvmeta.put(kvindex + KEYSTART, keystart);
kvmeta.put(kvindex + VALSTART, valstart);
kvmeta.put(kvindex + VALLEN, distanceTo(valstart, valend));
// advance kvindex 改变每次index的值 每次4个位置!
kvindex = (kvindex - NMETA + kvmeta.capacity()) % kvmeta.capacity();