Storm-源码分析-LocalState (backtype.storm.utils)
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)的更多相关文章
- Storm源码分析--Nimbus-data
nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...
- JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler
EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...
- JStorm与Storm源码分析(三)--Scheduler,调度器
Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...
- JStorm与Storm源码分析(二)--任务分配,assignment
mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理.代码注释如下: ;;参数nimbus为nimb ...
- storm源码分析之任务分配--task assignment
在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...
- JStorm与Storm源码分析(一)--nimbus-data
Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...
- Nimbus<三>Storm源码分析--Nimbus启动过程
Nimbus server, 首先从启动命令开始, 同样是使用storm命令"storm nimbus”来启动看下源码, 此处和上面client不同, jvmtype="-serv ...
- storm源码分析之topology提交过程
storm集群上运行的是一个个topology,一个topology是spouts和bolts组成的图.当我们开发完topology程序后将其打成jar包,然后在shell中执行storm jar x ...
- JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式
本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...
随机推荐
- C# fixed详解
相信很多人在这样或那样的项目中,或者无意间看到了fixed语句块,看到之后你肯定会疑问: 1.这个fixed关键字是做什么用的? 2.什么情况下需要该关键字? 3.这个关键字该怎么用? 我相信解决了上 ...
- meta 标签的学习
meta name="viewport" content="width=device-width,initial-scale=1.0" 解释 <meta ...
- 利用css3背景位置完成拼图
.duo { width: 623px; height: 417px; margin: 100px auto; background: url(images/bg1.png) left top no- ...
- swift基础知识
let 声明常量var 声明变量 ?可以为空 !必须为所声明类型 swift中文教程:http://c.biancheng.net/cpp/swift/jiaocheng/
- Can't zip RDDs with unequal numbers of partitions
java.lang.IllegalArgumentException: Can't zip RDDs with unequal numbers of partitions //如果两个RDD分区数不同 ...
- su和sudo命令
su命令用于在不同的用户之间切换,比如使用user1登陆了系统,但要执行一些管理操作,比如useradd,普通用户没有这个权限的,解决的办法有两个. 1:退出user1用户,重新以root用户登录系统 ...
- node.js在2018年能继续火起来吗?我们来看看node.js的待遇情况
你知道node.js是怎么火起来的吗?你知道node.js现在的平均工资是多少吗?你知道node.js在2018年还能继续火吗?都不知道?那就来看文章吧,多学点node.js,说不定以后的你工资就会高 ...
- nginx的root alias 指令
location /img/ { alias /var/www/image/; } #若按照上述配置的话,则访问/img/目录里面的文件时,ningx会自动去/var/www/image/目录找文件 ...
- 容斥 + 组合数学 ---Codeforces Round #317 A. Lengthening Sticks
Lengthening Sticks Problem's Link: http://codeforces.com/contest/571/problem/A Mean: 给出a,b,c,l,要求a+x ...
- 28Mybatis_查询缓存-二级缓存-二级缓存测试-
二级缓存原理: