LocalState

A simple, durable, atomic K/V database. *Very inefficient*, should only be used for occasional reads/writes. Every read/write hits disk.

基于map实现, 每次读写都需要从磁盘上将数据读出, 并反序列化成map, 这个过程称为snapshot. 所以说是比较简单和低效的, 只能用于读取配置或参数, 这种偶尔读取的场景.

    public synchronized Map<Object, Object> snapshot() throws IOException {
int attempts = 0;
while(true) {
String latestPath = _vs.mostRecentVersionPath();
if(latestPath==null) return new HashMap<Object, Object>();
try {
return (Map<Object, Object>) Utils.deserialize(FileUtils.readFileToByteArray(new File(latestPath)));
} catch(IOException e) {
attempts++;
if(attempts >= 10) {
throw e;
}
}
}

读写操作都是基于map的操作, get和put, 但是put需要做persist操作.

这里使用synchronized来做对象的线程间同步, 对于一个LocalState对象, 所有synchronized标有的函数只能被串行操作.

    public Object get(Object key) throws IOException {
return snapshot().get(key);
}
public synchronized void put(Object key, Object val, boolean cleanup) throws IOException {
Map<Object, Object> curr = snapshot();
curr.put(key, val);
persist(curr, cleanup);
}

当然不止这么简单, 为了达到atomic, 还使用了VersionedStore, 参考下一章

persist不会去update现有的文件, 而是不断的产生递增version的文件, 故每一批更新都会产生一个新的文件

把需要写入的数据序列化

创建新的versionfile的path

把数据写入versionfile

调用succeedVersion, 创建tokenfile以标志versionfile的写入完成

清除旧版本, 只保留4个版本

    private void persist(Map<Object, Object> val, boolean cleanup) throws IOException {
byte[] toWrite = Utils.serialize(val);
String newPath = _vs.createVersion();
FileUtils.writeByteArrayToFile(new File(newPath), toWrite);
_vs.succeedVersion(newPath);
if(cleanup) _vs.cleanup(4);
}

 

VersionedStore

    public VersionedStore(String path) throws IOException {
_root = path;
mkdirs(_root);
}

这个store, 其实就是_root目录下的一堆文件

文件分两种,

VersionFile, _root + version, 真正的数据存储文件

TokenFile, _root + version + “.version”, 标志位文件, 标志version文件是否完成写操作, 以避免读到正在更新的文件

getAllVersions就是读出所有_root目录下的所有完成写操作的文件, 读出version, 并做从大到小的排序

    public List<Long> getAllVersions() throws IOException {
List<Long> ret = new ArrayList<Long>();
for(String s: listDir(_root)) {
if(s.endsWith(FINISHED_VERSION_SUFFIX)) {
ret.add(validateAndGetVersion(s));
}
}
Collections.sort(ret);
Collections.reverse(ret);
return ret;
}

 

找到最新的版本文件

    public Long mostRecentVersion() throws IOException {
List<Long> all = getAllVersions();
if(all.size()==0) return null;
return all.get(0);

 

创建新版本号, 用当前时间作为version

    public String createVersion() throws IOException {
Long mostRecent = mostRecentVersion();
long version = Time.currentTimeMillis();
if(mostRecent!=null && version <= mostRecent) {
version = mostRecent + 1;
}
return createVersion(version);
} public String createVersion(long version) throws IOException {
String ret = versionPath(version);
if(getAllVersions().contains(version))
throw new RuntimeException("Version already exists or data already exists");
else
return ret;
}
 

创建tokenfile, 以标记versionfile写完成

    public void succeedVersion(String path) throws IOException {
long version = validateAndGetVersion(path);
// should rewrite this to do a file move
createNewFile(tokenPath(version));
}
 

清除旧的版本, 只保留versionsToKeep个, 清除操作就是删除versionfile和tokenfile

    public void cleanup(int versionsToKeep) throws IOException {
List<Long> versions = getAllVersions();
if(versionsToKeep >= 0) {
versions = versions.subList(0, Math.min(versions.size(), versionsToKeep));
}
HashSet<Long> keepers = new HashSet<Long>(versions); for(String p: listDir(_root)) {
Long v = parseVersion(p);
if(v!=null && !keepers.contains(v)) {
deleteVersion(v);
}
}
}

Storm-源码分析-LocalState (backtype.storm.utils)的更多相关文章

  1. Storm源码分析--Nimbus-data

    nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...

  2. JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler

    EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...

  3. JStorm与Storm源码分析(三)--Scheduler,调度器

    Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...

  4. JStorm与Storm源码分析(二)--任务分配,assignment

    mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理.代码注释如下: ;;参数nimbus为nimb ...

  5. storm源码分析之任务分配--task assignment

    在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...

  6. JStorm与Storm源码分析(一)--nimbus-data

    Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...

  7. Nimbus<三>Storm源码分析--Nimbus启动过程

    Nimbus server, 首先从启动命令开始, 同样是使用storm命令"storm nimbus”来启动看下源码, 此处和上面client不同, jvmtype="-serv ...

  8. storm源码分析之topology提交过程

    storm集群上运行的是一个个topology,一个topology是spouts和bolts组成的图.当我们开发完topology程序后将其打成jar包,然后在shell中执行storm jar x ...

  9. JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式

    本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...

随机推荐

  1. makefile之override

    override指示符 通常在执行 make 时,如果通过命令行定义了一个变量,那么它将替代在 Makefile中出现的同名变量的定义. 就是说,对于一个在 Makefile 中使用常规方式(使用&q ...

  2. c语言中struct的内存对齐

    为了让CPU能够更舒服地访问到变量,struct中的各成员变量的存储地址有一套对齐的机制.这个机制概括起来有两点:第一,每个成员变量的首地址,必须是它的类型的对齐值的整数倍,如果不满足,它与前一个成员 ...

  3. SQL Server 2014 Agent 无法启动

    - <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">- <System& ...

  4. jquery头文件的引入

    <script type="text/javascript" src="/library/js/jquery/jquery-1.9.1.min.js"&g ...

  5. CEF Xilium.CefGlue 在当前窗体中打开全部链接(防止弹窗)

    我们在使用Xilium.CefGlue编写浏览器应用程序时.对于嵌入的网页假设有链接会在新窗体打开.这种用户体验会非常差.因此我们须要改动程序,使全部链接都在当前窗体中打开. 首先引用Xilium.C ...

  6. Unix系统编程()信号:概念和概述

    这篇将一口气学完信号的基本概念,但是有很多的细节,所以篇幅较长,请做好心理准备. (他大爷的,一口气没有学完,太懒了) 有以下主题: 各种不同信号及其用途 内核可能为进程产生信号的环境,以及某一进程向 ...

  7. C#中利用JQuery实现视频网站的缩略图采集

    最近有朋友想要采集优酷的视频标题和缩略图 (哈哈, 并非商业目的). 找到我帮忙, 考虑到有我刚刚发布的SpiderStudio, 我毫不犹豫的答应了. 首先在网页上视频的基本结构为: div.v - ...

  8. Android基础总结(十)ContentProvider

    内容提供者(掌握) 应用的数据库是不允许其他应用访问的 内容提供者的作用就是让别的应用访问到你的私有数据 自定义内容提供者,继承ContentProvider类,重写增删改查方法,在方法中写增删改查数 ...

  9. 更新加子查询加相同的表解决办法 mysql

    UPDATE ofuser SET auid = '0' WHERE uid in (SELECT uid FROM (select tmp.* from ofuser tmp)a WHERE aui ...

  10. Web前端开发中的MCRV模式(转)

    作者: izujian  来源: baiduux 摘要:针对前端开发中基于ajax的复杂页面开发所面临的代码规模大,难以组织和维护,代码复用性.扩展性和适应性差等问题,本文尝试以MVC思想为 基础,结 ...