声明

文章发布于CSDN

cassandra concurrent 具体实现

cassandra并发技术文中介绍了java的concurrent实现,这里介绍cassandra如何基于java实现cassandra并发包。

Figure1——cassandra并发实现

  1. cassandra各个Stage是通过StageManger来进行管理的,StageManager 有个内部类ExecuteOnlyExecutor。

  2. ExecuteOnlyExecutor继承了ThreadPoolExecutor,实现了cassandra的LocalAwareExecutorSerivce接口

  3. LocalAwareExecutorService继承了Java的ExecutorService,构建了基本的任务模型。添加了两个自己的方法.

    execute方法用于trace跟踪。

    public void execute(Runnable command, ExecutorLocals locals);
    public void maybeExecuteImmediately(Runnable command);
    

    对于Executor中的默认execute方法,和LocalAwareExecutorSerive中的execute方法都是new 一个task,然后将task添加到queue中。而maybeExecuteImmedicatly方法则是判断下是否有正在执行的task或者work,如果没有则直接执行,而不添加到队列中。

    public void maybeExecuteImmediately(Runnable command)
    {
        //comment1
        FutureTask<?> ft = newTaskFor(command, null);
        if (!takeWorkPermit(false))
        {
            addTask(ft);
        }
        else
        {
            try
            {
                ft.run();
            }
            finally
            {
                returnWorkPermit();
                maybeSchedule();
            }
        }
    }
    
  4. AbstractLocalAwareExecutorService实现LocalAwareExecutorSerive接口,提供了executor的实现以及ExecutorServie接口中的关于生命周期管理的方法实现,如submit,shoudown等方法。添加了addTask,和任务完成的方法onCompletion。

  5. SEPExecutor实现了LocalAwareExecutorService类,提供了addTask,onCompletion,maybeExecuteImmediately等方法的实现。同时负责队列的管理

  6. SharedExecutorPool,线程池管理,用来管理Executor

cassandra write

cassandra写操作涉及到MutationStage,FlushWriter,MemtablePostFlusher,ReplicateOnWriteStage

MutationStage

Figure2 cassandra mutation change(coordinator)





cassandra mutation时序图如上图所示。前面几个都是线程调用和request的”翻译”重点是最后一个类的执行StorageProxy.在#comment1处,cassandra对batch change 和涉及到view更新 与单条的insert操作进行了区分。

  • Single

    Coordinator:将request同时发给所有replicate节点

    Replicate:

    1.写数据到commitlog

    2. 写数据到MemTable

    3. 如果写操作是个delete操作,在commitlog和MemTable中添加墓碑tombstone

    4. 如果使用了row caching,需要失效这行的缓存

    5. 发送应答request到coordinator

  • View/Batch

    View是和Table绑定在一起的,所以要确保两者是一起更新的。cassandra通过batch log 来实现。无论write consistency level 是多少,batch log 要确保change写入到了quorum份replicate.

    Coordinator:创建batch log,确保quorum份replicate node写入change,客户端的响应仍然是按照write consistency level;将request同时发给所有replicate 节点。

    Replicate:完整调用栈见Figure3

    1. 获得partition 的锁,确保batch/view 的write request是串行化(BatchManger.store#comment1 处)
    2. 如果是视图,则需要读取partition 数据,生成物化视图的增量变化
    3. 写 commit log
    4. 生成batch log
    5. 存储batch log
    6. 发送batch的second write/物化视图的更新到相应的replicate node。因为batch/视图更新 等多条记录可能不在同一个replicate上
    7. 写MemTable
    8. 其他record的replicate会写更新,然后发送response到first record replicate node 上

      //BatchManager.store()

      public static void store(Batch batch, boolean durableWrites) {
      RowUpdateBuilder builder = new RowUpdateBuilder(SystemKeyspace.Batches, batch.creationTime, batch.id)
              .clustering().add("version", MessagingService.current_version);
      
      for (ByteBuffer mutation : batch.encodedMutations)
          builder.addListEntry("mutations", mutation);
      
      for (Mutation mutation : batch.decodedMutations) {
          try (DataOutputBuffer buffer = new DataOutputBuffer()) {
              //comment1 串行化多个mutation改变
              Mutation.serializer.serialize(mutation, buffer, MessagingService.current_version);
              builder.addListEntry("mutations", buffer.buffer());
          } catch (IOException e) {
              // shouldn't happen
              throw new AssertionError(e);
          }
      }
      
      builder.build().apply(durableWrites);
      }
      

      Figure3 cassandra mutation change(replicate)

FlushWriter&&MemtablePostFlusher

FlushWriter Stage 就是将数据从MemTable flush到SSTable中。有三种事件会导致发生

1. memtable 超过了设定的大小

2. nodetool flush

3. commit log 超过了设定的大小

ColumnFamilyStore.switchMemtable方法将Memtable flush到SSTable中.

public ListenableFuture<CommitLogPosition> switchMemtable()
{
    synchronized (data)
    {
        logFlush();
        Flush flush = new Flush(false);
        flushExecutor.execute(flush);
        ListenableFutureTask<CommitLogPosition> task = ListenableFutureTask.create(flush.postFlush);
        postFlushExecutor.submit(task);
        return task;
    }
}

flushExecutor,postFlushExecutor都JMX相关的ThreadPool,因为需要将相关的metrics通过JMX暴露出去

flushExecutor = new JMXEnabledThreadPoolExecutor(1,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(),new NamedThreadFactory("MemtableFlushWriter"),"internal");

postFlushExecutor = new JMXEnabledThreadPoolExecutor(1,StageManager.KEEPALIVE,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(),new NamedThreadFactory("MemtablePostFlush"),"internal");

参考

https://wiki.apache.org/cassandra/WritePathForUsers

http://www.mikeperham.com/2010/03/13/cassandra-internals-writing/

号外

打算翻译cassandra官方文档,有兴趣的小伙伴可以一起加入

cassandra官方文档翻译

加入cassandra学习群,一起学习

从Stage角度看cassandra write的更多相关文章

  1. Android IOS WebRTC 音视频开发总结(四八)-- 从商业和技术的角度看视频行业的机会

    本文主要从不同角度介绍视频行业的机会,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,欢迎关注个人微信公众号blacker ----------------------------- ...

  2. 【阿里云产品公测】以开发者角度看ACE服务『ACE应用构建指南』

    作者:阿里云用户mr_wid ,z)NKt#   @I6A9do   如果感觉该评测对您有所帮助, 欢迎投票给本文: UO<claV   RsfTUb)<   投票标题:  28.[阿里云 ...

  3. [置顶] 从引爆点的角度看360随身wifi的发展

    从引爆点的角度看360随身wifi的发展 不到一个月的时间,随身wifi预定量就数百万.它的引爆点在哪里,为什么相同的产品这么多它却能火起来,通过对随身wifi的了解和我知识层面分析,主要是因为随身w ...

  4. 站在Java的角度看LinkedList

    站在Java的角度看,玩队列不就是玩对象引用对象嘛! public class LinkedList<E> implements List<E>, Deque<E> ...

  5. 从源码的角度看 React JS 中批量更新 State 的策略(下)

    这篇文章我们继续从源码的角度学习 React JS 中的批量更新 State 的策略,供我们继续深入学习研究 React 之用. 前置文章列表 深入理解 React JS 中的 setState 从源 ...

  6. 从线程模型的角度看Netty的高性能

    转载:Netty(二) 从线程模型的角度看 Netty 为什么是高性能的? 传统 IO 在 Netty 以及 NIO 出现之前,我们写 IO 应用其实用的都是用 java.io.* 下所提供的包. 比 ...

  7. INDEX--从数据存放的角度看索引2

    在上次<INDEX--从数据存放的角度看索引>中,我们说到"唯一非聚集索引"和“非唯一非聚集索引”在存储上有一个明显的差别:唯一非聚集索引的非叶子节点上不会包含RID的 ...

  8. 从JDK源码角度看Short

    概况 Java的Short类主要的作用就是对基本类型short进行封装,提供了一些处理short类型的方法,比如short到String类型的转换方法或String类型到short类型的转换方法,当然 ...

  9. 从JDK源码角度看Byte

    Java的Byte类主要的作用就是对基本类型byte进行封装,提供了一些处理byte类型的方法,比如byte到String类型的转换方法或String类型到byte类型的转换方法,当然也包含与其他类型 ...

随机推荐

  1. Java中List集合的三种遍历方式(全网最详)

    List集合在Java日常开发中是必不可少的,只要懂得运用各种各样的方法就可以大大提高我们开发的效率,适当活用各种方法才会使我们开发事半功倍. 我总结了三种List集合的遍历方式,下面一一来介绍. 首 ...

  2. windows下 在cmd中输入ls命令出现“ls不是内部或外部命令“解决方法

    1.新建一个文件命名为 ls.bat 2.打开编辑这个文件 输入: @echo off dir 3.将这个文件放在C:\windows目录下

  3. 计算机网络-应用层之HTTP协议

    1.概念 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写:HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等). ...

  4. C#扩展方法(转)

    扩展方法使您能够向现有类型"添加"方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型." 这是msdn上说的,也就是你可以对String,Int,DataRo ...

  5. java 反射(Reflection)

    看了很多关于java 反射的文章,自己把所看到的总结一下.对自己,对他人或多或少有帮助吧. Java Reflection是什么? 首先来看看官方文档Oracle里面对Reflection的描述: R ...

  6. 运用正则+replace+substring将一段英语的字母大写 angurlar运用自定义指令filter完成首字母大写

    复习下js基础并运用正则+replace+substring将一段英语的字母大写 <!DOCTYPE html><html> <head> <meta cha ...

  7. python3全栈开发-socket编程

    一. 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视 ...

  8. ES6(正则扩展)

    ES6中正则的扩展 正则新增特性 一.构造函数的变化 1.ES5中new一个正则对象方法 (一行中2个参数,二行中1个参数) (第一行中的第一个参数必须是字符串) 2.ES6中新增一种方法(构造函数) ...

  9. [Codeforces 864A]Fair Game

    Description Petya and Vasya decided to play a game. They have n cards (n is an even number). A singl ...

  10. LOJ #6041. 事情的相似度

    Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...