cassandra 服务启动流程
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 服务启动流程的更多相关文章
- Netty 拆包粘包和服务启动流程分析
Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Ch ...
- 【转】Netty 拆包粘包和服务启动流程分析
原文:https://www.cnblogs.com/itdragon/archive/2018/01/29/8365694.html Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你 ...
- Oracle RAC 服务启动流程
启动流程步骤层次梳理:第一层:OHASD 启动: cssdagent - 负责启动 CSSD 的 Agent.orarootagent - 负责启动所有 root 用户下的 ohasd 资源 的Age ...
- Cinder Volume 服务启动流程分析和周期性任务分析
1.cinder-volume服务的程序入口 #!/usr/bin/python2 # PBR Generated from u'console_scripts' import sys from ci ...
- 老李推荐:第5章2节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动流程概览
老李推荐:第5章2节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 启动流程概览 每个应用都会有一个入口方法来供操作系统调用执行,Monkey这个应用的入口方法就 ...
- Apache ZooKeeper 服务启动源码解释
转载:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper-code/ 本文首先讲解了 Apache ZooKeeper 服 ...
- 菜鸟系列Fabric源码学习—orderer服务启动
Fabric 1.4 orderer 服务启动流程 1.提要 orderer提供broadcast和deliver两个服务接口.orderer节点与各个peer节点通过grpc连接,orderer将所 ...
- dubbo系列一、dubbo启动流程
目录 dubbo启动流程分析记录 一.dubbo provider启动流程 1.自动装配 2.ServiceBean处理 3.服务暴露export() 3.1.检测dubbo.xxx.配置属性,配置到 ...
- centOS7服务管理与启动流程
centOS7服务管理与启动流程 centOS7启动流程 systemd简介 unit对象 unit类型 特性 service unit文件格式 service unit file文件通常由三部分组成 ...
随机推荐
- MVC之Session State性能
ASP.NET MVC之Session State性能问题(七) 前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Sess ...
- linux的tr命令
tr(translate缩写)主要用于删除文件中的控制字符,或进行字符转换. 语法 tr [ -c | -cds | -cs | -C | -Cds | -Cs | -ds | -s] [ -A] S ...
- malloc函数的一种简单的原理性实现
malloc()是C语言中动态存储管理的一组标准库函数之一.其作用是在内存的动态存储区中分配一个长度为size的连续空间.其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针 ...
- U5首次登录
1.在Llinx中,大小写字母是不一样的东西. 2.date可以查看日期,date的正确格式是:date +%Y/%m/%d/%H/%M(左边这句话所想表达的意思是年的字母必须为大写,月的必须为小写. ...
- OCP读书笔记(17) - 计划任务
轻量级作业: 也称为持久性轻量级作业,如果当我们的数据库每秒钟需要创建.删除或修改数十个或数百个作业时,使用轻量级作业是降低开销的最佳方法 常规作业:是由oracle 11g Scheduler 所支 ...
- 二叉树的建立与遍历(山东理工OJ)
题目描写叙述 已知一个按先序序列输入的字符序列,如abc,,de,g,,f,,,(当中逗号表示空节点).请建立二叉树并按中序和后序方式遍历二叉树,最后求出叶子节点个数和二叉树深度. 输入 输入一个长度 ...
- leetcode先刷_Binary Tree Level Order Traversal II
非常easy标题,在后面,我不认为它不是那么简单的回答更多的.我们将编写,没有人啊. 预购在基层上,加上节省每一层,加上从下往上的输出,是一家vector而一个stack那么问题,没有他,但另一方面- ...
- [置顶] 最优间隔分类器、原始/对偶问题、SVM的对偶问题——斯坦福ML公开课笔记7
转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9774135 本篇笔记针对ML公开课的第七个视频,主要内容包括最优间隔分类器( ...
- shell脚本中的数学运算
shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法.以后用到的时候能够来看,呵呵 1.错误方法举例 a) var=1+1 echo $var 输出的结果是1+1 ...
- 源代码分析:LayoutParams的wrap_content, match_parent, 而详细的价值观
问题: 慢慢地熟悉android 的过程中.发现view 要么layout初始化,建或者生产活动是很清楚.被添加到父控制,然后开始了相应的生命周期.但父控件的整个界面.还是第一个系统view. 怎么来 ...