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. HTML与XML关系分析

    本来这篇是为CSS准备的,但看到视频中CSS和HTML.XML都有关系,即,都是设置他们的样式.而XML和HTML的格式看着也有些类似,就不得不分析一下二者之间的关系了. 要想分析事物关系,要先弄清他 ...

  2. Java调用IIS发布的WebService

    之前的一篇博客说了一个实例,就是用VS2005在IIS上发布WebService.今天我们来实现在Eclipse上用Java来调用昨天发布的WebService. 首先咋在浏览器中输入http://1 ...

  3. 什么样的企业造什么样的软件最easy成功?

    事件1: 一般软件企业按功能分,大体分业务应用型软件和系统工具型软件. 按市场分,应用型软件企业较多,直接贴近生活:系统工具类较少,间接贴近大众较少. 事件2: 软件企业中,当中中小型企业老板存在非常 ...

  4. gdb学习(一个)[再版]

    概要 gdb是GNU debugger的缩写,是编程调试工具. 功能 1.启动程序,能够依照用户自己定义的要求随心所欲的执行程序. 2.可让被调试的程序在用户所指定的断点处停住 (断点能够是条件表达式 ...

  5. sharpSVN说明文档

    http://sharpsvn.open.collab.net/docs/walkthrough.htm

  6. 数据库采用多表连接查询,对应javaBean文件连接方式

    在一个Web项目中,只要是存在数据库就一定会有JavaBean文件.一个JavaBean文件会对应一张数据库中的表,供dao中的代码来调用用来存取数据.我们都知道,在数据库设计的时候,如果A.B两张表 ...

  7. windows phone 7 通过麦克风录音,并且播放

    原文:windows phone 7 通过麦克风录音,并且播放 //模拟XNA的框架(凡是在wp7中应用xna的都必须先模拟此类) public class XNAAsyncDispatcher : ...

  8. 使用Sublime Text 2编辑和运行node-webkit应用程序

    开发工具目录结构 --E:\develop\ ----node-webkit-v0.9.2-win-ia32 ----Sublime Text 2.0.2 x64 为Sublime text2构建Bu ...

  9. boost::signals::signal的使用方法

    吃力的讲完boost::signals的ppt.然后接着就是做练习题. 通过讲ppt,发现有一句话说的真好:你自己知道是一回事.你能给别人讲明确又是另外一回事.真的有些东西你自己理解,可是用语言去非常 ...

  10. POJ 1146:ID Codes

    ID Codes Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6281 Accepted: 3769 Description ...