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. HDU 4916 树分治

    Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  2. VB.NET版机房收费系统---导出Excel表格

    datagridview,翻译成中文的意思是数据表格显示,使用DataGridView控件,能够显示和编辑来自不同类型的数据源的表格,将数据绑定到DataGridView控件很easy和直观,大多数情 ...

  3. Linux+Apache+Mysql+Php

    CentOS 6.3下源码安装LAMP(Linux+Apache+Mysql+Php)环境 一.简介 什么是LAMP    LAMP是一种Web网络应用和开发环境,是Linux, Apache, My ...

  4. IE浏览器审查密码的清除

    上周去188工业区,总装厂的喷油部的电脑上被谁设置了IE的审查密码,后来通过电话沟通,运维岗给出了具体的解决方法: 进入注册表HKEY_LOCAL_MACHINE\Software\Microsoft ...

  5. PSU 离11.2.0.3.0 -&gt; 11.2.0.3.11 如果解决冲突的整个

    Oracle rdbms 扑灭psu离11.2.0.3.0升级到11.2.0.3.11 参考patch :18522512 停止应用,停止听音乐并DB,将db的oracle_home在下面OPatch ...

  6. android &quot;Missing type parameter&quot; 错误

    近期在做android应该的时候出现这个问题,分析了一下日志,发现是在gosn解析的时候会出现,并且出现的时候非常诡异.于是去网上找相关资料. 发现这个问题还是比較常见的,原来是公布版本号和非正式公布 ...

  7. C#之网络

    首先很不好意思,前段时间把评论的功能给关掉啦,BUT NOW 此功能以开放,欢迎小伙伴们拍砖. 1网络 在网络环境下,我们最感兴趣的两个名称空间是System.Net和System.Net.Socke ...

  8. 使用windows-SQLyog连接linux-mysql

          嘿嘿,最近又清闲了一点,重新安装了mysql去学习.   -----博客园-邦邦酱好 系统环境: 1. 主机为windows系统,安装了SQLyog. 2. 主机上还安装了虚拟机,系统为c ...

  9. POJ 1205 Water Treatment Plants(递推)

    题意   建设一条河岸的污水处理系统  河岸有n个城市   每一个城市都能够自己处理污水 V   也能够把污水传到相邻的城市处理 >或<   除了你传给我我也传给你这样的情况   其他都是 ...

  10. Python学习入门基础教程(learning Python)--3.1Python的if分支语句

    本节研究一下if分支语句. if分支语句是Python下逻辑条件控制语句,用于条件执行某些语句的控制操作,当if后的条件conditon满足时,if其下的语句块被执行,但当if的控制条件condito ...