janusgraph源码分析8-底层交互

反向分析cassandra 写数据 APIcassandra 的结构类似 bigtable ,数据实际上是多层嵌套的 map,第一个 key 是 rowkey,第二层key 是 columnFamily,第三层key 是 column,第四层(也可以忽略) 是 timestamp,然后是 value。写数据的 API 如下: CTConnection conn = null; try {...
摘要由CSDN通过智能技术生成

反向分析

cassandra 写数据 API

cassandra 的结构类似 bigtable ,数据实际上是多层嵌套的 map,第一个 key 是 rowkey,第二层key 是 columnFamily,第三层key 是 column,第四层(也可以忽略) 是 timestamp,然后是 value。

写数据的 API 如下:

 CTConnection conn = null;
 try {
   
     conn = pool.borrowObject(keySpaceName);
     Cassandra.Client client = conn.getClient();
     if (atomicBatch) {
   
         client.atomic_batch_mutate(batch, consistency);
     } else {
   
         client.batch_mutate(batch, consistency);
     }
 } catch (Exception ex) {
   
     throw CassandraThriftKeyColumnValueStore.convertException(ex);
 } finally {
   
     pool.returnObjectUnsafe(keySpaceName, conn);
 }

这里的 batch 就是一个多层嵌套的map。final Map<ByteBuffer, Map<String, List<org.apache.cassandra.thrift.Mutation>>> batch = new HashMap<>(size);

这里看起来只有两层,第一层的 ByteBuffer 当然是 rowKey,第二层是 String 是 columnFamily。而 List<org.apache.cassandra.thrift.Mutation> 很明显就是添加或者删除的 key:value。

写入 cassandra 的数据格式

上面是写 cassandra 的 API,而最终调用这段代码的位置在 CassandraThriftStoreManager.mutateMany(Map<String, Map<StaticBuffer, KCVMutation>> mutations, StoreTransaction txh) 方法。

我们需要了解的就是 Map<String, Map<StaticBuffer, KCVMutation>> mutationsMap<ByteBuffer, Map<String, List<org.apache.cassandra.thrift.Mutation>>> batch 的对应关系。

从代码可以看出:

final Map<ByteBuffer, Map<String, List<org.apache.cassandra.thrift.Mutation>>> batch = new HashMap<>(size);

for (final Map.Entry<String, Map<StaticBuffer, KCVMutation>> keyMutation : mutations.entrySet()) {
   
    
    // mutations 的 key 是 columnFamily
    final String columnFamily = keyMutation.getKey(); 
    
    for (final Map.Entry<StaticBuffer, KCVMutation> mutEntry : keyMutation.getValue().entrySet()) {
   
        
        // mutations 的第二层 key 是 rowKey
        ByteBuffer keyBB = mutEntry.getKey().asByteBuffer();

        // Get or create the single Cassandra Mutation object responsible for this key
        // Most mutations only modify the edgeStore and indexStore
        
        final Map<String, List<org.apache.cassandra.thrift.Mutation>> cfmutation
            = batch.computeIfAbsent(keyBB, k -> new HashMap<>(3));

        final KCVMutation mutation = mutEntry.getValue();
        final List<org.apache.cassandra.thrift.Mutation> thriftMutation = new ArrayList<>(mutations.size());
        
        // 省略删除的代码。
        
        if (mutation.hasAdditions()) {
   
            
            for (final Entry ent : mutation.getAdditions()) {
   
                final ColumnOrSuperColumn columnOrSuperColumn = new ColumnOrSuperColumn();
                
                // mutations 的第三层 key 是 column
                final Column column = new Column(ent.getColumnAs(StaticBuffer.BB_FACTORY));
                // mutations 的 value 是 value
                column.setValue(ent.getValueAs(StaticBuffer.BB_FACTORY));

                column.setTimestamp(commitTime.getAdditionTime(times));

                final Integer ttl = (Integer) ent.getMetaData().get(EntryMetaData.TTL);
                if (null != ttl && ttl > 0) {
   
                    column.setTtl(ttl);
                }

                columnOrSuperColumn.setColumn(column);
                org.apache.cassandra.thrift.Mutation m = new org.apache.cassandra.thrift.Mutation();
                m.setColumn_or_supercolumn(columnOrSuperColumn);
                thriftMutation.add(m);
            }
        }

        cfmutation.put(columnFamily, thriftMutation);
    }
}

我们可以看出 mutateMany 方法的参数和写到 cassandra 的结果不是完全一致,主要是 rowkey 和 columnFamily 的位置是反的。

传入 mutateMany 的数据

通过调试可以看出,调用 mutateMany 的地方主要是 CacheTransation.persist ,而调用 persist 的就是 flushInternal 方法。相应代码:

// 成员变量: Map<KCVSCache, Map<StaticBuffer, KCVEntryMutation>> mutations

// 新建Map,这个 map 就是上面 mutateMany 的参数,key 分别是 columnFamily 和 rowKey ,
final Map<String, Map<StaticBuffer, KCVMutation>> subMutations = new HashMap<>(mutations.size());

int numSubMutations = 0;
// 遍历 mutations
for (Map.Entry<KCVSCache,Map<StaticBuffer, KCVEntryMutation>> storeMutations : mutations.entrySet()) {
   
    final Map<StaticBuffer, KCVMutation> sub = new HashMap<>();
    
    // KCVSCache 的 getKey().getName() 就是 columnFamily
    subMutations.put(storeMutations.getKey().getName(),sub);
   
    // mutations 的 value
    for (Map.Entry<StaticBuffer,KCVEntryMutation> mutationsForKey : storeMutations.getValue().entrySet()) {
   
        if (mutationsForKey.getValue().isEmpty()) continue;
        
        // 将 mutationsForKey 放进去,这个 convert 做了啥没有具体研究,可能只是一个适配。
        sub.put(mutationsForKey.getKey(), convert(mutationsForKey.getValue()));
        numSubMutations+=mutationsForKey.getValue().getTotalMutations();
        if (numSubMutations>= persistChunkSize) {
   
            numSubMutations = persist(subMutations);
            sub.clear();
            subMutations.put(storeMutations.getKey().getName(),sub);
        }
    }
}

mutations 的构造

上面我们看出了,其实基本上没复杂处理,接下来我们看看 mutations 数据哪里来的。

对于 mutations 的修改操作,来自于 mutate 方法,代码:

// 传入的是 store(包含了columnFamily) key(rowKey) additions 和 deletions
void mutate(KCVSCache store, StaticBuffer key, List<Entry> additions, List<Entry> deletions) throws BackendException {
   
    Preconditions.checkNotNull(store);
    if (additions.isEmpty() && deletions.isEmpty()) return;
    
    // 构造 KCVEntryMutation
    KCVEntryMutation m = new KCVEntryMutation(additions, deletions
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值