快捷搜索:  as  test  1111  test aNd 8=8  test++aNd+8=8  as++aNd+8=8  as aNd 8=8

bet356体育在线靠谱吗_酒文化网进入



Cassandra 的数据存储布局

Cassandra 中的数据主要分为三种:

CommitLog:主要记录下客户端提交过来的数据以及操作。这个数据将被持久化到磁盘中,以便数据没有被持久化到磁盘时可以用来规复。

Memtable:用户写的数据在内存中的形式,它的工具布局在后面具体先容。着实还有别的一种形式是 BinaryMemtable 这个款式今朝 Cassandra 并没有应用,这里不再先容了。

SSTable:数据被持久化到磁盘,这又分为 Data、Index 和 Filter 三种数据款式。

CommitLog 数据款式

CommitLog 的数据只有一种,那便是按照必然款式组成 byte 组数,写到 IO 缓冲区中准时的被刷到磁盘中持久化,在上一篇的设置设置设备摆设摆设文件详解中已经有说到 CommitLog 的持久化要领有两种,一个是 Periodic 一个是 Batch,它们的数据款式都是一样的,只是前者是异步的,后者是同步的,数据被刷到磁盘的频繁度不一样。关于 CommitLog 的相关的类布局图如下:

图 1. CommitLog 的相关的类布局图

它持久化的策略也很简单,便是首先将用户提交的数据所在的工具 RowMutation 序列化成 byte 数组,然后把这个工具和 byte 数组传给 LogRecordAdder 工具,由 LogRecordAdder 工具调用 CommitLogSegment 的 write 措施去完成写操作,这个 write 措施的代码如下:

清单 1. CommitLogSegment. write

public CommitLogSegment.CommitLogContext write(RowMutation rowMutation,

Object serializedRow){

long currentPosition = -1L;

...

Checksum checkum = new CRC32();

if (serializedRow instanceof DataOutputBuffer){

DataOutputBuffer buffer = (DataOutputBuffer) serializedRow;

logWriter.writeLong(buffer.getLength());

logWriter.write(buffer.getData(), 0, buffer.getLength());

checkum.update(buffer.getData(), 0, buffer.getLength());

}

else{

assert serializedRow instanceof byte[];

byte[] bytes = (byte[]) serializedRow;

logWriter.writeLong(bytes.length);

logWriter.write(bytes);

checkum.update(bytes, 0, bytes.length);

}

logWriter.writeLong(checkum.getValue());

...

}

这个代码的主要感化便是假如当前这个根据 columnFamily 的 id 还没有被序列化过,将会根据这个 id 天生一个 CommitLogHeader 工具,记录下在当前的 CommitLog 文件中的位置,并将这个 header 序列化,覆盖曩昔的 header。这个 header 中可能包孕多个没有被序列化到磁盘中的 RowMutation 对应的 columnFamily 的 id。假如已经存在,直接把 RowMutation 工具的序列化结果写到 CommitLog 的文件缓存区中后面再加一个 CRC32 校验码。Byte 数组的款式如下:

图 2. CommitLog 文件数组布局

上图中每个不合的 columnFamily 的 id 都包孕在 header 中,这样做的目的是更轻易的判断那些数据没有被序列化。

CommitLog 的感化是为规复没有被写到磁盘中的数据,那若何根据 CommitLog 文件中存储的数据规复呢?这段代码在 recover 措施中:

清单 2. CommitLog.recover

public static void recover(File[] clogs) throws IOException{

...

final CommitLogHeader clHeader = CommitLogHeader.readCommitLogHeader(reader);

int lowPos = CommitLogHeader.getLowestPosition(clHeader);

if (lowPos == 0) break;

reader.seek(lowPos);

while (!reader.isEOF()){

try{

bytes = new byte[(int) reader.readLong()];

reader.readFully(bytes);

claimedCRC32 = reader.readLong();

}

...

ByteArrayInputStream bufIn = new ByteArrayInputStream(bytes);

Checksum checksum = new CRC32();

checksum.update(bytes, 0, bytes.length);

if (claimedCRC32 != checksum.getValue()){continue;}

final RowMutation rm =

RowMutation.serializer().deserialize(new DataInputStream(bufIn));

}

...

}

这段代码的思路是:反序列化 CommitLog 文件的 header 为 CommitLogHeader 工具,探求 header 工具中没有被回写的最小 RowMutation 位置,然后根据这个位置掏出这个 RowMutation 工具的序列化数据,然后反序列化为 RowMutation 工具,然后掏出 RowMutation 工具中的数据从新保存到 Memtable 中,而不是直接写到磁盘中。CommitLog 的操作历程可以用下图来清楚的表示:

图 3. CommitLog 数据款式的变更历程

Memtable 内存中数据布局

Memtable 内存中数据布局对照简单,一个 ColumnFamily 对应一个独一的 Memtable 工具,以是 Memtable 主要便是掩护一个 ConcurrentSkipListMap 类型的数据布局,当一个新的 RowMutation 工具加进来时,Memtable 只要看看这个布局是否聚拢已经存在,没有的话就加进来,有的话掏出这个 Key 对应的 ColumnFamily,再把它们的 Column 合并。Memtable 相关的类布局图如下:

图 4. Memtable 相关的类布局图

Memtable 中的数据会根据设置设置设备摆设摆设文件中的响应设置设置设备摆设摆设参数刷到本地磁盘中。这些参数在上一篇中已经做了具体阐明。

前面已经多处提到了 Cassandra 的写的机能很好,好的缘故原由便是由于 Cassandra 写到数据首先被写到 Memtable 中,而 Memtable 是内存中的数据布局,以是 Cassandra 的写是写内存的,下图基础上描述了一个 key/value 数据是怎么样写到 Cassandra 中的 Memtable 数据布局中的。

图 5. 数据被写到 Memtable

SSTable 数据款式

每添加一条数据到 Memtable 中,法度榜样都邑反省一下这个 Memtable 是否已经满意被写到磁盘的前提,假如前提满意这个 Memtable 就会写到磁盘中。先看一下这个历程涉及到的类。相关类图如图 6 所示:

图 6. SSTable 持久化类布局图

Memtable 的前提满意后,它会创建一个bet356体育在线靠谱吗 SSTableWriter 工具,然后掏出 Memtable 中所有的聚拢,将 ColumnFamily 工具的序列化布局写到 DataOutputBuffer 中。接下去 SSTableWriter 根据 DecoratedKey 和 DataOutputBuffer 分手写到 Date、Index 和 Filter 三个文件中。

Data 文件款式如下:

图 7. SSTable 的 Data 文件布局

Data 文件便是按照上述 byte 数组来组织文件的,数据被写到 Data 文件中是接着就会往 Index 文件中写,Index 中到底写什么数据呢?

着实 Index 文件便是记录下所有 Key 和这个 Key 对应在 Data 文件中的启示地址,如图 8 所示:

图 8. Index 文件布局

Index 文件实际上便是 Key 的一个索引文件,今朝只对 Key 做索引,对 super column 和 column 都没有建索引,以是要匹配 column 相对来说要比 Key 更慢。

Index 文件写完后接着写 Filter 文件,Filter 文件存的内容便是 BloomFilter 工具的序列化结果。它的文件布局如图 9 所示:

图 9. Filter 文件布局

BloomFilter 工具实际上对应一个 Hash 算法,这个算法能够快速的判断给定的某个 Key 在不在当前这个 SSTable 中,而且每个 SSTable 对应的 BloomFilter 工具都在内存中,Filter 文件唆使 BloomFilter 持久化的一个副本。三个文件对应的数据款式可以用下图来清楚的表示:

图 10. SSTable 数据款式转化

这个三个文件写完后,还要做的一件事故便是更新前面提到的 CommitLog 文件,奉告 CommitLog 的 heabet356体育在线靠谱吗der 所存确当前 ColumnFamily 的没有写到磁盘的最小位置。

在 Memtable 往磁盘中写的历程中,这个 Memtable 被放到 memtablesPendingFlush 容器中,以包管在读时刻它里面存的数据能被精确读到,这个在后面数据读取时还会先容。

数据的写入

数据要写到 Cassandra 中有两个步骤:

找到应该保存这个数据的节点

往这个节点写数据。客户端写一条数据必须指定 Keyspace、ColumnFamily、Key、Column Name 和 Value,还可以指定 Timestamp,以及数据的安然等级。

数据写入涉及的主要相关类如下图所示:

图 11. Insert 相关类图

大年夜慨的写入逻辑是这样bet356体育在线靠谱吗的:

CassandraServer 接管到要写入的数据时,起开创建一个 RowMutation 工具,再创建一个 QueryPath 工具,这个工具中保存了 ColumnFamily、Column Name 或者 Super Column Name。接着把用户提交的所稀有据保存在 RowMutation 工具的 Map 布局中。接下去便是根据提交的 Kebet356体育在线靠谱吗y 谋略集群中那个节点应该保存这条数据。这个谋略的规则是:将 Key 转化成 Token,然后在全部集群的 Token 环中根据二分查找算法找到与给定的 Token 最靠近的一个节点。假如用户指bet356体育在线靠谱吗定了数据要保存多个备份,那么将会顺序在 Token 环中返回与备份数相等的节点。这是一个基础的节点列表,后面 Cassandra 会判断这些节点是否正常事情,假如不正常探求调换节点。还有还要反省是否有节点正在启动,这种节点也是要在斟酌的范围内,终极会形成一个目标节点列表。着末把数据发送到这些节点。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

您可能还会对下面的文章感兴趣: