cassandra 服务启动流程

1.  setup

1)   CassandraDaemon ->main

publicstaticvoidmain(String[]args)

{

instance.activate();

}

2)   系统參数初始化

配置文件的读取和解析都是在org.apache.cassandra.config.DatabaseDescriptor 类中完毕的,这个类的作用很easy。就是读取配置文件里各个配置项所定义的值,经过简单的验证,符合条件就将其值赋给 DatabaseDescriptor 的私有静态常量。

详细的实现步骤例如以下:

DatabaseDescriptor.hasLargeAddressSpace() //载入了系统设置,静态变量,载入了系统的默认參数:

->applyConfig(loadConfig());

以下是获取系统须要的表格。

->// Hardcoded system keyspaces

List<KSMetaData> systemKeyspaces =Arrays.asList(KSMetaData.systemKeyspace());

assert systemKeyspaces.size() == Schema.systemKeyspaceNames.size();

for (KSMetaData ksmd : systemKeyspaces)

Schema.instance.load(ksmd);

->每个表格写入到Schema

/**

*Load specific keyspace into Schema

*

*@param keyspaceDef The keyspace to load up

*

*@return self to support chaining calls

*/

public Schema load(KSMetaData keyspaceDef)

{

for (CFMetaData cfm : keyspaceDef.cfMetaData().values())

load(cfm);

setKeyspaceDefinition(keyspaceDef);

return this;

}

最后的cfm都是存放到:private final ConcurrentBiMap<Pair<String,String>, UUID> cfIdMap = new ConcurrentBiMap<>();

上面的这段代码获取到系统须要默认的表格,可是这边还没有创建表格。

3)  keyspacemeta

a)        for(MemoryPoolMXBean pool:ManagementFactory.getMemoryPoolMXBeans())

logger.info("{} {}: {}",pool.getName(), pool.getType(), pool.getPeakUsage());//输出cassandra jvm的全部pool的信息

输出结果例如以下:

INFO 07:20:32 Heap size: 124780544/954728448

INFO 07:21:12 Code Cache Non-heap memory: init = 2555904(2496K) used =828800(809K) committed = 2555904(2496K) max = 50331648(49152K)

INFO 07:21:28 PS Eden Space Heap memory: init = 33030144(32256K) used =33030144(32256K) committed = 33030144(32256K) max = 347602944(339456K)

INFO 07:21:29 PS Survivor Space Heap memory: init = 5242880(5120K) used =5227632(5105K) committed = 5242880(5120K) max = 5242880(5120K)

INFO 07:22:43 PS Old Gen Heap memory: init = 86507520(84480K) used =351840(343K) committed = 86507520(84480K) max = 715653120(698880K)

INFO 07:22:49 PS Perm Gen Non-heap memory: init = 22020096(21504K) used =16674864(16284K) committed = 22020096(21504K) max = 85983232(83968K)

b)        检查文件夹是否存在和权限

c)        启动内存初始化

private CacheService()

{

............................................

keyCache = initKeyCache();

//keycache初始化

rowCache = initRowCache();

// rowCache初始化

counterCache = initCounterCache();

// counterCache处理化

}

以下我们分析keycache处理化的实现过程:

private AutoSavingCache<KeyCacheKey,RowIndexEntry> initKeyCache() {

longkeyCacheInMemoryCapacity = DatabaseDescriptor.getKeyCacheSizeInMB() * 1024 *1024;

ICache<KeyCacheKey,RowIndexEntry> kc;

kc =ConcurrentLinkedHashCache.create(keyCacheInMemoryCapacity);

AutoSavingCache<KeyCacheKey,RowIndexEntry> keyCache = new AutoSavingCache<>(kc,CacheType.KEY_CACHE, new KeyCacheSerializer());

int keyCacheKeysToSave =DatabaseDescriptor.getKeyCacheKeysToSave();

keyCache.scheduleSaving(DatabaseDescriptor.getKeyCacheSavePeriod(),keyCacheKeysToSave);

return keyCache;

}

分析ConcurrentLinkedHashCache.create(keyCacheInMemoryCapacity)实现过程:

创建了一个:ConcurrentLinkedHashMap<K, V> map;存储所用cache。

详细的创建步骤例如以下:

ConcurrentLinkedHashMap<K, V> map =new ConcurrentLinkedHashMap.Builder<K, V>()

.weigher(entryWeiger)

.maximumWeightedCapacity(weightedCapacity)

.concurrencyLevel(DEFAULT_CONCURENCY_LEVEL)

.build();

d)        initialize keyspaces

for (String keyspaceName :Schema.instance.getKeyspaces())

{

if (logger.isDebugEnabled())

logger.debug("openingkeyspace {}", keyspaceName);

// disable auto compaction untilcommit log replay ends

for (ColumnFamilyStore cfs :Keyspace.open(keyspaceName).getColumnFamilyStores())

{

for (ColumnFamilyStore store :cfs.concatWithIndexes())

{

store.disableAutoCompaction();//关闭完以后。关闭自己主动compaction功能

}

}

}

4)  commlogrecover

代码入口:CommitLog.instance.recover();

为了保证系统出现异常情况。如今系统选择从系统默认的commitlog恢复日志。这里主要完毕这几个操作,发现是否有没有被写到磁盘的数据,恢复这个数据,构建新的日志文件。

CommitLog 日志文件的恢复策略是,在头文件里发现没有被序列化的最新的ColumnFamily Id,然后取出这个这个被序列化 RowMutation 对象的起始地址。反序列化成为 RowMutation 对象,后面的操作和新添一条数据的流程是一样的。假设这个 RowMutation 对象中的数据被成功写到磁盘中。那么会在 CommitLog
去掉已经被持久化的 ColumnFamily Id。关于 CommitLog 日志文件的存储格式以及数据怎样写到 CommitLog 文件里。

5)   auto compaction

在启动过程中。须要让每一个keyspace去compaction。sstable的数据的也将flush到磁盘。全部假设在集群重新启动以后。这里会提交compact。

详细的实现代码例如以下:

if(store.getCompactionStrategy().shouldBeEnabled())

store.enableAutoCompaction();

6)  GCInspectorregister

GCInspector.instance.start 服务。主要是统计统计当前系统中资源的使用情况。将这个信息记录到日志文件里。这个能够作为系统的监控日志使用。

7)  StorageService.instance.initServer()

Ø  init StorageProxy

Class.forName("org.apache.cassandra.service.StorageProxy");

Ø  init IndexSummaryManager

Class.forName("org.apache.cassandra.io.sstable.IndexSummaryManager");

Ø  从系统peers获取该节点的ring和hostid;

Ø  启动gossipservice,保证能够与其它节点通信;关于gossip怎么样通信。后面会具体分析其通信过程。

Ø  HintedHandOffManager.instance.start();

Ø  BatchlogManager.instance.start();

Ø  MessagingService.instance().listen(FBUtilities.getLocalAddress());

Ø  LoadBroadcaster.instance.startBroadcasting();

Ø  Thift  init

Ø  native transport int

2.  start

启动过程主要包括2个步骤:

1)        nativeServer.start();

2)        thriftServer.start();

务启动工作已经setup步骤完毕;以下专门分析nativeServer的启动过程。nativeServer使用了netty的通信模型,Netty提供异步的、事件驱动的网络应用程序框架和工具,用以高速开发高性能、高可靠性的网络server和client程序。

本文第四小节的代码是使用netty

的example。读者感兴趣能够调试。

nativeserver 详细设置例如以下:

eventExecutorGroup = newRequestThreadPoolExecutor();

workerGroup= newNioEventLoopGroup();

ServerBootstrapbootstrap

= new ServerBootstrap().group(workerGroup)

.channel(NioServerSocketChannel.class)

.childOption(ChannelOption.TCP_NODELAY,true)

.childOption(ChannelOption.SO_KEEPALIVE,DatabaseDescriptor.getRpcKeepAlive())

.childOption(ChannelOption.ALLOCATOR,CBUtil.allocator)

.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK,32 * 1024)

.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK,8 * 1024);

在执行过程中,会对channel进行操作注冊:

protected voidinitChannel(Channel channel) throws Exception

{

ChannelPipeline pipeline =channel.pipeline();

//pipeline.addLast("debug",new LoggingHandler());

pipeline.addLast("frameDecoder", newFrame.Decoder(server.connectionFactory));

pipeline.addLast("frameEncoder",frameEncoder);

pipeline.addLast("frameDecompressor",frameDecompressor);

pipeline.addLast("frameCompressor",frameCompressor);

pipeline.addLast("messageDecoder", messageDecoder);

pipeline.addLast("messageEncoder",messageEncoder);

pipeline.addLast(server.eventExecutorGroup,"executor", dispatcher);

}

3.  接受ConcurrentLinkedHashMap数据结构

Cassandra 源代码里面具体该数据结构。实现了能够用来实现一个基于LRU策略的缓存。

1)    linkedHashMap

import java.util.HashMap;

import java.util.Iterator;

import java.util.LinkedHashMap;

import java.util.Map;

public class TestLinkedHashMap {

public static void main(String
args[])

{

System.out.println("*************************LinkedHashMap*************");

Map<Integer,String>map = new LinkedHashMap<Integer,String>();

map.put(6, "apple");

map.put(3, "banana");

map.put(2,"pear");

for (Iterator it = map.keySet().iterator();it.hasNext();)

{

Objectkey = it.next();

System.out.println(key+"="+ map.get(key));

}

System.out.println("*************************HashMap*************");

Map<Integer,String>map1 = new  HashMap<Integer,String>();

map1.put(6, "apple");

map1.put(3, "banana");

map1.put(2,"pear");

for (Iterator it = map1.keySet().iterator();it.hasNext();)

{

Objectkey = it.next();

System.out.println(key+"="+ map1.get(key));

}

}

}

输出:

执行结果例如以下:

*************************LinkedHashMap*************

6=apple

3=banana

2=pear

*************************HashMap**************************

2=pear

6=apple

3=banana

分析:

l   LinkedHashmap的特点是put进去的对象位置未发生变化,而HashMap会发生变化;

l   LinkedHashMap非线程安全 须要採用google的ConcurrentLinkedHashMap(https://code.google.com/p/concurrentlinkedhashmap/)

l   能够实现last recently used 功能

2)    ConcurrentLinkedHashMap

ConcurrentHashMap的封装。能够用来实现一个基于LRU策略的缓存.

public static voidmain(String[] args) {

ConcurrentLinkedHashMap<Integer,Integer> map = new

ConcurrentLinkedHashMap.Builder<Integer,Integer>().maximumWeightedCapacity(2);

weigher(Weighers.singleton()).build();

map.put(1, 1);

map.put(2, 2);

map.put(3, 3);

System.out.println(map.get(1));//null已经失效了

System.out.println(map.get(2));

}

3)    总体架构

l  它本质是额外维护了一个双向链表。每次读和写都要改变对应节点的位置。将其移至队列头;

l  什么时候推断easy已经满了,是依据weight。每一个元素都有一个weight,每添加一个元素。weight累计。

l  当达到最大值的时候,就须要剔除最少操作的那个元素了,而且触发相关的事件;

cassandra 服务启动流程的更多相关文章

  1. Netty 拆包粘包和服务启动流程分析

    Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Ch ...

  2. 【转】Netty 拆包粘包和服务启动流程分析

    原文:https://www.cnblogs.com/itdragon/archive/2018/01/29/8365694.html Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你 ...

  3. Oracle RAC 服务启动流程

    启动流程步骤层次梳理:第一层:OHASD 启动: cssdagent - 负责启动 CSSD 的 Agent.orarootagent - 负责启动所有 root 用户下的 ohasd 资源 的Age ...

  4. Cinder Volume 服务启动流程分析和周期性任务分析

    1.cinder-volume服务的程序入口 #!/usr/bin/python2 # PBR Generated from u'console_scripts' import sys from ci ...

  5. 老李推荐:第5章2节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动流程概览

    老李推荐:第5章2节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 启动流程概览   每个应用都会有一个入口方法来供操作系统调用执行,Monkey这个应用的入口方法就 ...

  6. Apache ZooKeeper 服务启动源码解释

    转载:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper-code/ 本文首先讲解了 Apache ZooKeeper 服 ...

  7. 菜鸟系列Fabric源码学习—orderer服务启动

    Fabric 1.4 orderer 服务启动流程 1.提要 orderer提供broadcast和deliver两个服务接口.orderer节点与各个peer节点通过grpc连接,orderer将所 ...

  8. dubbo系列一、dubbo启动流程

    目录 dubbo启动流程分析记录 一.dubbo provider启动流程 1.自动装配 2.ServiceBean处理 3.服务暴露export() 3.1.检测dubbo.xxx.配置属性,配置到 ...

  9. centOS7服务管理与启动流程

    centOS7服务管理与启动流程 centOS7启动流程 systemd简介 unit对象 unit类型 特性 service unit文件格式 service unit file文件通常由三部分组成 ...

随机推荐

  1. Date和String类型的相互转换

    String转Date: SimpleDateFormat bartDateFormat = new SimpleDateFormat("MM-dd-yyyy"); String ...

  2. SVN的命令行操作

    最近在进行svn二次开发,使用的是svnkit.看了很多svnkit的api,渐渐发现都是和SVN的命令行操作对应的.顺便研究一下svn的命名行操作. 1.将文件checkout到本地目录: 基本命令 ...

  3. 利用h5标签在网页上播放音乐

    方案1: <embed src="等一分钟.mp3" id="aa"> <input type=button value=暂停 onclick ...

  4. 作为一个.net程序猿,需要掌握这些有点前途的人才,一些开发---Shinepans

    1.基础 C#基础                    参考书目:   <c#入门经典>         <ASP.NET揭秘> IIS  HTML              ...

  5. Acquire and Release Semantics

    An operation has acquire semantics if other processors will always see its effect before any subsequ ...

  6. TextView 使用自定义的字体和亮点

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/40478815 如今非常多应用中喜欢使用自己定义字体,今天我就来实如今TextView中使用自 ...

  7. Visual Studio Tips: How to change project namespace

    /* Author: Jiangong SUN */ If you want to modify a project's namespace and its physical container na ...

  8. linux grep命令详解(转)

    简介 grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它 ...

  9. java表达式陷阱

    以下是一些常见的面试java问题的表达,我将造成直接的形式附加目光. 问题1: int a = 10; int b = a + (a = 5) + a + (a = 10); System.out.p ...

  10. IP Camera 和 Web Camera 差分

    一直以来,,没太注意IP camera 和 Web Camera之间的差,这两个摄像头,昨天晚上.闲来无事Google少数,我们发现,还有两者之间的差异. 1) IP Camera IP Camera ...