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. MVC之Session State性能

    ASP.NET MVC之Session State性能问题(七)   前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Sess ...

  2. linux的tr命令

    tr(translate缩写)主要用于删除文件中的控制字符,或进行字符转换. 语法 tr [ -c | -cds | -cs | -C | -Cds | -Cs | -ds | -s] [ -A] S ...

  3. malloc函数的一种简单的原理性实现

    malloc()是C语言中动态存储管理的一组标准库函数之一.其作用是在内存的动态存储区中分配一个长度为size的连续空间.其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针 ...

  4. U5首次登录

    1.在Llinx中,大小写字母是不一样的东西. 2.date可以查看日期,date的正确格式是:date +%Y/%m/%d/%H/%M(左边这句话所想表达的意思是年的字母必须为大写,月的必须为小写. ...

  5. OCP读书笔记(17) - 计划任务

    轻量级作业: 也称为持久性轻量级作业,如果当我们的数据库每秒钟需要创建.删除或修改数十个或数百个作业时,使用轻量级作业是降低开销的最佳方法 常规作业:是由oracle 11g Scheduler 所支 ...

  6. 二叉树的建立与遍历(山东理工OJ)

    题目描写叙述 已知一个按先序序列输入的字符序列,如abc,,de,g,,f,,,(当中逗号表示空节点).请建立二叉树并按中序和后序方式遍历二叉树,最后求出叶子节点个数和二叉树深度. 输入 输入一个长度 ...

  7. leetcode先刷_Binary Tree Level Order Traversal II

    非常easy标题,在后面,我不认为它不是那么简单的回答更多的.我们将编写,没有人啊. 预购在基层上,加上节省每一层,加上从下往上的输出,是一家vector而一个stack那么问题,没有他,但另一方面- ...

  8. [置顶] 最优间隔分类器、原始/对偶问题、SVM的对偶问题——斯坦福ML公开课笔记7

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9774135 本篇笔记针对ML公开课的第七个视频,主要内容包括最优间隔分类器( ...

  9. shell脚本中的数学运算

    shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法.以后用到的时候能够来看,呵呵 1.错误方法举例 a) var=1+1 echo $var 输出的结果是1+1 ...

  10. 源代码分析:LayoutParams的wrap_content, match_parent, 而详细的价值观

    问题: 慢慢地熟悉android 的过程中.发现view 要么layout初始化,建或者生产活动是很清楚.被添加到父控制,然后开始了相应的生命周期.但父控件的整个界面.还是第一个系统view. 怎么来 ...