跟我学Kafka之Controller控制器详解
作者:小程
我们的kafka源码分享已经进行过很多期了,主要的内容也都分享的差不多了,那么在今后的分享中,主要集中在kafka性能优化和使用。
Kafka集群中的其中一个Broker会被选举为Controller,主要负责Partition管理和副本状态管理,也会执行类似于重分配Partition之类的管理任务。如果当前的Controller失败,会从其他正常的Broker中重新选举Controller。
作者:小程
我们的kafka源码分享已经进行过很多期了,主要的内容也都分享的差不多了,那么在今后的分享中,主要集中在kafka性能优化和使用。
Kafka集群中的其中一个Broker会被选举为Controller,主要负责Partition管理和副本状态管理,也会执行类似于重分配Partition之类的管理任务。如果当前的Controller失败,会从其他正常的Broker中重新选举Controller。
原文链接 译者:小村长
本项目是 Apache Spark官方文档的中文翻译版,致力于打造一个全新的大数据处理平台来满足大数据处理和分析的各个使用场景,本次翻译主要针对对Spark感兴趣和致力于从事大数据方法开发的人员提供有价值的中文资料,希望能够对大家的工作和学习有所帮助。
Spark最近几年在国内外都比较火,在淘宝、百度、腾讯、高伟达等一些公司有比较成熟的应用,做大数据方面的开发人员或多或少都与其有接触。Spark的中文资料相对前几年相对较多,但是我认为官方文档才是最好最完美的学习资料,今天让小村长为你揭开Spark的神秘面纱,一同走进Spark的精神世界。 阅读全文
英文原文链接,译文链接,原文作者:Arun Manivannan ,译者:有孚
写过多线程的人都不会否认,多线程应用的维护是件多么困难和痛苦的事。我说的是维护,这是因为开始的时候还很简单,一旦你看到性能得到提升就会欢呼雀跃。然而,当你发现很难从子任务的错误中恢复或者有些僵尸BUG很难复现再或者你的分析器显示你的线程在写入一个共享状态前大部分时间都浪费在阻塞上面的时候,痛苦降临了。
我刻意没提Java的并发API,以及它里面的集合类使得多线程编程变得多么轻松简单,因为我相信既然你们点进了这篇文章,那就说明你希望能更好地控制你的子任务,或者你就是不喜欢使用锁以及同步块,希望能有一种更高层次的抽象。
感谢看处方的汪院长和烨明,为这次活动提供了场地和零食,去年在上海的scala聚会也是看处方的汪院长发起的。这次聚会人比上次略微多一些了,而且整体水平是不断提升的。
聚石分享了来往使用scala构建通讯的一些经验,来往的IM部分采用自己的协议(有些类似spdy,要简单很多),在协议网关的实现上主要使用scala、akka,他主要分享了这个过程中踩过的一些坑。
诺铁的分享是scala集合部分,这部分内容是小中见大的,有部分内容来自《scala in depth》(顺便提一下他翻译的这本书快要出版了)。整个ppt很清晰,把Vector
的细节讲的比较透,另外还提到Set的一个细节是继承自(T)=>Boolean
这个函数类型,也就是contains
方法,比如Set(1,2,3)(1)
将返回true,这种设计确实怪异,容易误解。 阅读全文
原文:Things You Didn’t Know About Synchronization in Java and Scala 译者: 李杰聪
在实际应用中所有的服务端程序都需要在多线程之间进行某种同步。大多数同步已经有框架完成了,比如我们的web服务器,DB客户端和消息框架。Java和Scala提供了大量的组件用来实现稳定的多线程程序。包括对象池,并发集合,高级锁,执行上下文等。
为了更好的理解这些组件,我们深入了解一下最常用的同步原语——对象所。这个是用synchronized 关键字来实现的,在Java中它是非常流行的多线程原语。这也是其他更复杂模式的基础,比如线程池和连接池,并发集合等。
Synchronized 关键字主要用在以下两个场景:
先抛个问题,下面的语句是否都合理(编译通过),哪些会引起模式匹配?
scala> val a = 100
scala> val A = 100
scala> val a@b = 100
scala> val (a,b) = (100,200)
scala> val (a,B) = (100,200) //第二个变量大写
scala> val Array(a,b) = Array(100,200)
scala> val Array(a,B) = Array(100,200)
scala> object Test { val 2 = 2 }
scala> object Test { val 2 = 3 }
我们先看看其他语言(对scala有影响的)有关赋值语句的定义:
val P = E
表示定义了模式P
中的变量,并赋予它们表达式E
中相应的值。
在这两种语言中,赋值语句都明确的定义为模式匹配,那么scala中,所有的赋值语句是否都是模式匹配呢?
尤其scala可以说在函数式风格上与ML(及其家族)语言有某种血缘,在这一点上是否也与ML完全一致呢?
先分析一下上面的每条赋值语句:val a = 100
和 val A = 100
是直观且没有歧义的。
val a@b = 100
是什么意思?回忆一下第一篇里讲过的“变量绑定模式”,当时的例子有点复杂,重新理解一下:
//给"hello"字符串对象用v1这个变量名
scala> "hello" match { case v1 => println(v1) }
//变量绑定模式,把变量v2 绑定在v1这个模式上
scala> "hello" match { case v2@v1 => println(v2) }
上面的例子中,第一行中v1是个变量模式。 第二行中v2是一个新的变量,只有在v1这个模式匹配成功的情况下,才会把自己绑定到v1上,而v1因为是一个变量模式,它总能匹配成功,所以这里v2也会绑定到”hello”对象上。变量绑定模式通常不会这么使用,更多用在绑定到一个复合结构的模式上,如:
scala> List(1,List(2,3)) match { case List(_, x@List(2,_*)) => println(x.size) }
2
把变量x绑定到了嵌套的 List(2,3) 这个对象上
但赋值语句val a@b = 100
跟上面的有关系么?我们通过ToolBox看看它”脱糖”后的语法树:
scala> tb.parse("val a@b=100")
res13: tb.u.Tree =
{
<synthetic> private[this] val x$3 = 100: @scala.unchecked match {
case (a @ (b @ _)) => scala.Tuple2(a, b) //这一句
};
val a = x$3._1;
val b = x$3._2
}
有注释的那一句里面把a,b两个局部变量绑定到通配符”_”上,而这个通配符模式case _ =>
可以匹配任何对象,所以相当于把a,b两个变量绑定到了100这个对象上,并产生了一个二元组记录这两个局部变量值。最终把二元组里的值分别赋给了我们定义的a,b两个变量。
接下来的val (a,b) = (100,200)
这个赋值也容易理解,把二元组里的值分别赋给a,b两个变量么,也是经过模式匹配的么?继续用ToolBox分析:
scala> tb.parse("val (a,b)=(100,200)")
res14: tb.u.Tree =
{
<synthetic> private[this] val x$4 = scala.Tuple2(100, 200): @scala.unchecked match {
case scala.Tuple2((a @ _), (b @ _)) => scala.Tuple2(a, b)
};
val a = x$4._1;
val b = x$4._2
}
看到了,是一个构造器模式与变量绑定模式的混合模式匹配。
再下一个val (a,B) = (100,200)
这个与上一个有区别么?回顾一下第一篇里讲到的“常量模式”:当变量大写时将被对待为常量模式,也就是说 大写B 和上面的 小写b 是两种不同的模式!!
scala> tb.parse("val (a,B)=(100,200)")
res15: tb.u.Tree =
val a = scala.Tuple2(100, 200): @scala.unchecked match {
case scala.Tuple2((a @ _), B) => a
}
大写B在这里当作常量来解析,但又找不到B这个变量(除非之前有定义过),就报错了:
scala> val (a,B) = (100,200)
<console>:8: error: not found: value B
val (a,B) = (100,200)
^
后边两个Array的赋值语句与这两个类似,小括号写法只是元组(Tuple)的语法糖而已。
最后,真正有趣,且会让新手崩溃的情况 object Test { val 2 = 2 }
为什么这个编译和初始化都没问题?
scala> object Test { val 2 = 2 }
defined module Test
scala> Test
res16: Test.type = Test$@3042dc22
简直逆天,难道这个背后也与模式匹配有关系么?
scala> tb.parse(" object Test { val 2 = 2 }")
res0: tb.u.Tree =
object Test extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
<synthetic> private[this] val x$1 = 2: @scala.unchecked match {
case 2 => ()
}
}
确实又是一个常量模式匹配,2匹配2,成功。
同理,下一个 object Test { val 2 = 3 }
也是个常量模式匹配,但为何明显不匹配,却可以编译时成功,而运行时时才报错呢?
scala> object Test { val 2 = 3 }
defined module Test
scala> Test
scala.MatchError: 3 (of class java.lang.Integer)
at Test$.<init>(<console>:8)
这是因为object 是惰性初始化的原因(lazy),如下:
// 对下面的单例
object Test { val a = 2 }
$ scalac -Xprint:jvm A.scala
package <empty> {
object Test extends Object {
private[this] val a: Int = _;
<stable> <accessor> def a(): Int = Test.this.a;
def <init>(): Test.type = {
Test.super.<init>();
Test.this.a = 2; //在初始化时才对成员赋值
()
}
}
}
在对多个变量赋值,或变量中有@符合,导致模式匹配还好理解,但”2=2″也引起模式匹配就会让我产生疑问:
是否所有的赋值语句都是模式匹配?
为了验证,通过编译选项查看val a=2
这样对单个变量的赋值却没有看到模式匹配。
另外,如果单个变量也是模式匹配,为何大写字母val A=2
没问题?假设对单个变量赋值也是模式匹配,那岂不无法定义大写的变量了;肯定是有区别的,但又怎么区分的?
我最初遇到这个困惑,在邮件列表里问了这个问题,得到了一些回复,并且有人给了一个老帖子链接说早就讨论过val 1=2
这个话题了:http://thread.gmane.org/gmane.comp.lang.scala.user/44036
在那个帖子里,martin也回复了为何 val 1=2
是模式匹配,并且为何不把这种情况作为错误给修复掉:
A value definition is of the form
val <pattern> = <expression> // 这个同ML和Erlang语言
1 is a <pattern>
There is one edge case:
If the pattern is a single variable (upper or lower case or backquoted), then it is always treated as a variable, not a constant. Otherwise, there would be no way to define such a value.只有一种边缘情况:如果模式是一个单独的变量(大写、小写、或用反引号引起来的),那么它总被当作变量,而非常量。否则就没法定义这样的一个值。
所以1=2
, "a"="b"
这样的赋值语句虽然是一个变量,但变量名称不符合上面的约束,产生了模式匹配。至于为何不修复这个问题(直接在编译时报错),也可以从这个帖子的线索中找到原因。
在这篇martin和另外两位模式匹配领域专家的论文里说了模式匹配的几种实现方式,以及scala是选择哪种方式来实现的。
http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
我引用了里面的一些描述。
在面向对象的程序中数据被组织为一级一级的类(class)
面向对象语言在模式匹配方面的问题在于如何从外部探测这个层级。
有6种实现模式匹配的方法:
1) 面向对象的分解 (decomposition)
2) 访问器模式 (visitor)
3) 类型测试/类型造型 (type-test/type-cast)
4) typecase
5) 样本类 (case class)
6) 抽取器 (extractor) 阅读全文