做中学, 学中做

2017-10-16
spark_dagscheduler

基于 spark 1.6

面向 Stage 的调度器,负责计算每个 job 的 DAG,并将 DAG 图划分为不同的 stage,对哪些 RDD 以及相应输出进行记录,寻找一个运行相应 job 所需要的最小 stage。然后将 stageTaskSet 的形式提交到下层的 TaskScheduler 进行具体的 task 调度。每个 TaskSet 包含整个可以独立运行的 task,这些 task 能够利用集群上已有的数据立即运行起来,如果集群上已有的数据已经不存在了,那么当前 task 就会失败。

Spark 的 stage 以 RDD 的 shuffle 为界进行划分。窄依赖的 RDD 操作会被穿起来放到一个 task 中,比如 map(), filter() 这样的操作。但是需要使用到 shuffle 依赖的操作,需要多个 stage(至少一个将中间文件写到特定的地方,另外一个从特定的地方进行读取)。每个 Stage,只会对其他 Stage 有 shuffle 依赖,在同一个 stage 中会进行很多计算。实际的将计算串起来的操作在 RDD.compute 中完成。

DAGScheduler 同样会基于缓存状态决定 task 希望运行在那(preferred location),如果 shuffle 输出文件丢失造成的 Stage 失败,会重新被提交。在 Stage 内部 的不是由 shuffle 文件丢失造成的失败,由 TaskScheduler 来完成,TaskScheduler 会在取消整个 stage 前进行小部分重试。
Read More

2017-09-22
GC 引用计数法

本文将将介绍 GC 算法中最基本的三种算法的第二种:引用计数法。

GC 引用计数法

GC 本来是一种“释放已经没有被引用的对象的机制”,人们自然就想到,通过记录所有对象的引用次数来进行,这就是 GC 引用计数法。

引用计数法,一句话来说就是,记录每个对象被引用的多少次,如果引用次数为零,就编程“垃圾”了,可以被回收。

下面给出引用计数法的基本代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//分配对象
new_object(size) {
obj = pickup_chunk(size, $free_list) //从 free_list 中查找一个符合大小的块
if (obj == NULL) //分配失败
allocation_fail()
else //分配成功
obj.ref_cnt = 1 //更新引用计数
return ojb
}
//更新指针
update_ptr(ptr, obj) {
inc_ref_cnt(obj) // 更新 obj 的引用
dec_ref_cnt(*ptr) // 更新 *ptr 的引用,注意这两句话的顺序,思考是否可以调换顺序
*ptr = obj
}
inc_ref_cnt(obj) {
obj.ref_cnt++
}
dec_ref_cnt(obj) {
obj.ref_cnt-- // 更新引用计数
if(obj.ref_cnt == 0) //如果该对象变成了 “垃圾”,进行回收
for (child: children(obj)) //更新所有子节点的引用
dec_ref_cnt(*child)
reclaim(obj)
}

GC 引用计数法的大致流程如上所述,其中 update_ptr 可以用下图描述

优缺点

对于引用计数法,我们可以来看看它到底有哪些优缺点呢?

优点

  1. 可即刻回收垃圾。

    在引用计数法中,每个对象都知道自己的被引用数,一旦计数变为 0,就会被链接到空闲链表中。换句话说,所有对象在被标记为垃圾的同时就会被回收。

  2. 最大暂停时间短

    只有更新指针的时候才会执行垃圾回收,

优化方案

2017-09-17
GC 标记-清除算法

GC 的世界中有三种基本的算法,分别是:

  • 标记清除
  • 引用计数
  • GC 复制

其他的 GC 算法都是在这三种算法上进行修改,优化得来。本文将要介绍的是 标记-清除 算法。

Read More

2017-07-14
tmux 简单使用指南

Tmux 的简单使用说明

工欲善其事,必先利其器

Tmux 是一个多窗口管理程序。可以让用户在一个地方管理多个终端。而不需要在不同的终端间来回切换。

在 Mac 下如何安装

直接使用 brew install tmux 就可以了,如果没有 brew,则需要先安装 brew,然后再执行上述命令。

简单使用流程

首先,需要了解 tmux 中的几个概念。session,window 以及 pane。这几者的关系如下,tmux 中可以起多个 session,每个 session 可以启动多个 window,然后每个 window 可以启动多个 pane。

这里给一个基本的流程

  1. 启动 tmux(默认会启动一个 session)
    使用 tmux 启动 tmux,使用 exit 退出 tmux,session 的命名默认是从 0 开始,一直往上加

  2. 在 session 中启动一个 window
    PREFIX c 会在当前 session 中创建一个 window, 其中 PREFIX 表示 tmux 中的命令前缀符(该条命令表示,先按下 PREFIX,然后按下 c),

  3. 在启动的 window 中创建一个 pane
    PREFIX % 竖直方向切分一个 window,PREFIX " 横向切分一个 window。这样就能够在 window 中创建 pane 了。基本的这些就够了。

  4. 如何在 session,window,pane 中进行移动
    能够创建 session,window,pane 了,接下来就是如何在 session,window,pane 间进行移动了。
    PREFIX s 会列出所有 session,然后进行具体的选择(可以上下移动光标,然后按 ENTRER 确定)
    PREFIX w 可以列出所有的 window,然后进行具体的筛选
    PREFIX n 可以切换到下一个 window
    PREFIX p 可以切换到上一个 window
    PREFIX & 可以关闭当前 window
    PREFIX o 可以在 pane 之间进行跳转
    tmux ls 会列出当前所有的 session(在非 tmux 环境下)

自定义 tmux

tmux 的配置文件可以保存在两个地方

  1. /etc/tmux.conf
  2. ~/.tmux.conf

其中 2 的优先级会更高,1 的影响面更广

接下来做什么

上面的仅仅是一个入门文档,也就是最少基本知识,接下来就是多实践。推荐一本小书《tmux productive mouse-free development》

tmux_pic.png

2017-06-20
风险不仅仅是事件发生的概率

风险不仅仅是事件发生的概率

风险可以定义为 = 事件结果对你的影响 * 事件发生的概率

风险在生活中处处存在,可能我们会想冒个险没啥关系,反正发生的概率小,而且在某些时候会有高收益/回报伴随这风险,这个时候就更有诱惑力了,总有人希望通过冒险得到高回报,但这恰恰是不可取的,是非常危险的。

Read More

2017-06-03
Streaming 程序调用 Producer.close hang 住问题追查复盘

本文作为一个问题追查过程的复盘记录,主要希望找出自己在解决问题中可以优化改进的地方。以后遇到问题,能够快速的进行定位,解决。

Read More

2017-06-01
如何在不重启 Spark Streaming 作业的情况下,增加消费的 topic

本文所有和 kafka 相关操作都基于 Direct 消费模式

在 Spark Streaming 作业中,每个作业会消费一个或多个 topic,但是这些 topic 需要在作业启动之前确定好,在作业运行中不能进行调整,之前修改了源码做到了自适应 topic partition 扩容的情况,但是无法动态调整消费的 topic。现在需要在不重启作业的情况下,动态调整消费的 topic。

Read More

2017-05-29
从源码级别分析 metric-core 的抽样算法

metric-core 是一个 java metric 库,用于统计 JVM 层面以及 服务级别 的各种 metric 信息。其中 metric-core 是其核心模块,代码量不多,总共 44 个文件,5700 行左右代码(包括注释)。算是一个很小的开源项目了。由于 metric 在所有项目中都非常重要,因此选择通读该项目,本文分析 metrci-core 中的抽样算法。

Read More

2017-05-19
Streaming 中 Receiver 相关源码分析

本文基于 spark 1.6.2
本次的源码全来自 org.apache.spark.streaming.receiver 这个 package 下,包括 BlockGenerator.scala, RateLimiter, ReceiverdBlock.scala, ReceivedBlockHandler.scala, Receiver.scala, ReceiverSupervisor.scala, ReceiverSupervisorImpl.scala

Read More

2017-05-10
Python 代码实践小结

最近写了较多的 Python 脚本,将最近自己写的脚本进行一个总结,其中有些是 Python 独有的,有些是所有程序设计中共有的:

  1. 考虑使用 Logger(logger 怎么配置,需要输出哪些信息 – 可以反向考虑,自己看到这个 logger 的时候想了解什么信息)
  2. 传递的数据结构如何考虑(是否对调用方有先验知识的要求,比如返回一个 Tuple,则需要用户了解 tuple 中元素的顺序,这样情况是否应该进行封装;),数据结构定义清楚了,很多东西也就清楚了。
  3. 如何操作数据库(可以学习 sqlalchemy,包括 core 和 orm 两种 api)
  4. 异常如何处理(异常应该分开捕获 – 可以清楚的知道什么情况下导致的,异常之后应该打印日志说明出现什么问题,如果情况恶劣需要进行异常再次抛出或者报警)
  5. 所有获取资源的地方都应该做 check(a. 没有获取到会怎么办;b.获取到异常的怎么办)
  6. 所有操作资源的地方都应该检查是否操作成功
  7. 每个函数都应该简短,如果函数过长应该进行拆分(有个建议值,函数包含的行数应该在 20-30 行之间,具体按照这个规范做过一次之后就会发现这样真好)
  8. 使用 class 之后,考虑重构 __str__ 函数,用户打印输出,如果对象放到 collection 中之后,需要实现 __repr__ 函数,用于打印整个 collection 的时候,直观显示(如果不实现 __str__,会调用 __repr__)
  9. 如果有些资源会发生变化,可以单独抽取出来,做成函数,这样后续调用就可以不用改变了

上述总结肯定有片面的地方,也有不全的地方,欢迎指出

Read More