mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-17 14:43:42 +08:00
del
This commit is contained in:
120
极客时间专栏/geek/大规模数据处理实战/专栏加餐 | 特别福利/FAQ第一期 | 学习大规模数据处理需要什么基础?.md
Normal file
120
极客时间专栏/geek/大规模数据处理实战/专栏加餐 | 特别福利/FAQ第一期 | 学习大规模数据处理需要什么基础?.md
Normal file
@@ -0,0 +1,120 @@
|
||||
<audio id="audio" title="FAQ第一期 | 学习大规模数据处理需要什么基础?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c4/6c/c475609d1106bae3e288397e46b6036c.mp3"></audio>
|
||||
|
||||
你好,我是蔡元楠。
|
||||
|
||||
专栏上线已经一个月了,在这里我要先感谢大家的留言,留言的对答可以使我们互有补益。
|
||||
|
||||
这段时间,我发现留言中的很多问题都很有价值,希望你也可以看到。所以,我根据已发布的文章中的思考题,从留言中摘录了一些典型的、常见的问题做出答疑集锦,最终成为了今天你看到的“特别福利篇”。
|
||||
|
||||
## “[开篇词](https://time.geekbang.org/column/article/90067)”问题精选
|
||||
|
||||
问题一:学习大规模数据处理需要有什么基础?
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a6/05/a6b4f451fde7e70d80649889d4d9b005.jpg" alt="">
|
||||
|
||||
这是一个很好的问题,虽然专栏已经更新了一个月,我还是要把这个开篇词中的提问放进来。就像你看到的那样,有好几位读者都问了类似的问题。
|
||||
|
||||
其实在最开始做专栏的内容设计时,我并没有对读者的知识背景作任何假设。
|
||||
|
||||
所以,即使是一些基础的技术概念,我也会举例解释一下(如果你已经会了可能会觉得啰嗦,这时候就需要你照顾一下其他同学了)。如果你有一些语言的编程经验(任何语言都可以)的话,看文章的理解速度会快一点。文章中会有一些示例代码,是用Python编写的。
|
||||
|
||||
但是在设计类型的案例中,我不觉得它对读者有特别的技术要求。
|
||||
|
||||
希望你在后面的阅读中提出建议,告诉我有哪些地方我讲得不够清楚,或者解释的过多,我会适当调整内容。
|
||||
|
||||
问题二:小型公司程序员学习大规模数据处理的意义?
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/76/8c/763eefc53ce0e3c4ce07240328c8358c.jpg" alt=""><br>
|
||||
这个问题问得很好。以客观条件来看,韩程的说法没有问题。
|
||||
|
||||
大规模的互联网公司天生数据量是要大一些的。但是,这并不意味着大数据处理只在大公司才能发挥价值。你也要考虑其他方面。
|
||||
|
||||
第一,对于公司来讲,小型互联网公司或者传统企业,并不是不需要数据处理技能,而是他们还没有从数据中挖掘business insight的意识,没有数据驱动决策的意识,甚至没有收集数据的意识。
|
||||
|
||||
举个我工作中见到的例子。比如,有些饲养奶牛的农户,他们几十年来根本不知道什么是数据。但是,当我们帮他们细致地搜集奶牛每天的活动数据,比如饮食、运动、作息、产奶,他们就能从中找到最经济(最优)的饲料投放方式。
|
||||
|
||||
第二,对于个人来讲,你就一定要看长期的职业发展,公司会从小变大,职位会从低变高。当你需要影响决策的时候,当你面临的数据量变多的时候,当你准备跳槽的时候,数据的处理能力都是至关重要的。
|
||||
|
||||
## “[第一讲](https://time.geekbang.org/column/article/90081)”问题精选
|
||||
|
||||
思考题:如果你在Facebook负责处理用户数据,你会选择什么样的分片函数来保证均匀分布的数据分片?
|
||||
|
||||
我发现有很多精彩的回答。比如下图中的CountingStars同学,他的思路非常有意思。是把年龄的数值前后颠倒进行分片。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ba/33/bae98a0e4b3c21418dd769fe96532433.jpg" alt="">
|
||||
|
||||
还有这位Mark Lee,他认为可以使用身份证后面的随机数来进行分片,纯技术上看起来似乎可行。但要使用用户的身份ID的话,你还需要考虑是否符合法律、道德、隐私方面的问题。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a0/60/a079de51a78ea36f01bde3a30da5a560.jpg" alt="">
|
||||
|
||||
而Freud的想法是引用随机标记来保证数据分片的随机性。但这里要保证数据的均匀可重复才行。如果你在shard2上的任务失败,你需要能够还原出错的任务并进行重试。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ba/cc/ba4a945178f382ea11f4e32d24d7dacc.jpg" alt="">
|
||||
|
||||
榣山樵客把这几个回答可能出现的问题做了个总结。他的回复是一切有效降低十位数权重的哈希算法都是可行的。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fe/05/fe092ac4cf0ae0d9562c0a1796460605.jpg" alt="">
|
||||
|
||||
倒置年龄可以明显改善分布不均的问题,但是也可能对某些单一热点无解,比如25岁的用户特别多的话还是会出问题。
|
||||
|
||||
随机分区可以做到均衡,但对combine、io等优化不够友好。还有一个缺点,是当分区任务失败,需要重新分区的时候,分区结果不再是deterministic的。如果某一台机器宕机了,你要如何重新分配原本属于这台机器上的用户数据?
|
||||
|
||||
先采样,再动态合并和拆分的实现过于复杂,效果可能不够稳定。
|
||||
|
||||
像他一样,在每个答案里都分别给出这个答案所存在的不足,这一点是我非常赞赏的。在开发设计中没有哪个答案是特别完美的,我们能做的是分析哪一个才是最符合自身应用需求,进而改善。
|
||||
|
||||
## “[第二讲](https://time.geekbang.org/column/article/90533)”问题精选
|
||||
|
||||
第二讲中,我留下的思考题是“你现在正在使用的数据处理技术有什么问题?你有怎样的改进设计?”。
|
||||
|
||||
mjl在回答中阐述了他比较了解的Spark和Flink,总结得很好。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ca/68/ca8501842f112eea2ae8e8c4d8ed6d68.jpg" alt="">
|
||||
|
||||
虽然原生Spark Streaming Model和Dataflow Model不一样,但是Cloudera Labs也有根据Dataflow Model的原理实现了Spark Dataflow,使得Beam也可以跑Spark runner。
|
||||
|
||||
而对于Flink来说的话,在0.10版本以后,它的DataStream API就已经是根据Dataflow Model的思想来重写了。
|
||||
|
||||
现在Flink也支持两套API,分别是DataStream版本的和Beam版本的。其实data Artisans一直都有和Google保持交流,希望未来两套Beam和Flink的API能达到统一。
|
||||
|
||||
最后赞一点,批处理是流处理的子集,这个观点我在第一讲的留言中也提到过。
|
||||
|
||||
[第三讲](https://time.geekbang.org/column/article/91125)和[第四讲](https://time.geekbang.org/column/article/91166)中问题较为开放,与读者自身的工作内容强相关,很多都是大家在分享自己的经验,内容很丰富,这里篇幅不足,建议大家去原文的留言中看一看。
|
||||
|
||||
## “[第五讲](https://time.geekbang.org/column/article/91647)”问题精选
|
||||
|
||||
第五讲中讲的主要是分布式处理系统的三个重要指标:扩展性,一致性和持久性。根据这个内容,3SKarl同学提问弱一致性和最终一致性的区别是什么。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d9/a4/d9d1829450683fbe555674c11dec61a4.jpg" alt="">
|
||||
|
||||
这是个很棒的问题。简而言之,弱一致性是个很宽泛的概念,它是区别于强一致性而定义的。广义上讲,任何不是强一致的,而又有某种同步性的分布式系统,我们都可以说它是弱一致的。
|
||||
|
||||
而最终一致性是弱一致性的一个特例,而且是最常被各种分布式系统用到的一个特例。
|
||||
|
||||
其他的比如因果一致性、FIFO一致性等都可以看作是弱一致性的特例,不同弱一致性只是对数据不同步的容忍程度不同,但是经过一段时间,所有节点的数据都要求要一致。
|
||||
|
||||
学习专栏时,重要的是理解它们的区别。这部分知识是为了后边讲CAP理论服务的,实际的工作中也不会像考试考概念题一样,让你背写这些一致性的定义。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4a/54/4a5e3922d78ec17c269691cc49869e54.jpg" alt="">
|
||||
|
||||
hua168同学问的是强一致性的误差范围。这个问题非常有趣,强一致性并没有误差可言的,强一致性简单地说指的就是如果更新一条数据,那所有用户读取数据的时候必须都看到这条更新了的数据。
|
||||
|
||||
在这里我也想借着FAQ分享一个自己当年在面试Bloomberg的面试经历。
|
||||
|
||||
面试官给我出的题目是这样的:如果要设计Bloomberg的股票信息系统中的数据库系统,系统需要实时更新股票价格,而数据更新的写入量非常大,用户也需要读取最新的股票资讯,你会如何设计这套系统。
|
||||
|
||||
这个问题其实有很多的未知区域需要我们去和面试官去阐明,例如用户的Use Cases是什么?在此我就不一一展开了,在这里我只想分享一个和一致性相关的内容。
|
||||
|
||||
在和Bloomberg的Tech Lead讨论时我发现,原来他们的股票系统显示的股价并不是强一致性的,延迟范围是1分钟左右。
|
||||
|
||||
因为应用场景上,普通股民并不会需要实时关心每秒钟股票价格的动态,更多的是关心大盘走势。而金融巨头在操作股票的时候,更多只关心特定的几只股票,所以这些股票的价格通常对于他们来说会更新快一点。
|
||||
|
||||
所以说,很多现实生活上的实际应用和我们本来想象的并不太一样。
|
||||
|
||||
到这里,我们的第一期答疑就结束了。
|
||||
|
||||
就像我在专栏一开始的时候与你说的一样,我希望你能够积极与我互动。其实很多同样的问题会在不同的人身上重复出现,你不表达出来的话,可能永远也不知道,原来有那么多人曾经和你遇到过同样的困境。
|
||||
|
||||
如果你觉得有所收获,欢迎你把文章分享给你的朋友。
|
||||
|
||||
|
||||
131
极客时间专栏/geek/大规模数据处理实战/专栏加餐 | 特别福利/FAQ第三期 | Apache Beam基础答疑.md
Normal file
131
极客时间专栏/geek/大规模数据处理实战/专栏加餐 | 特别福利/FAQ第三期 | Apache Beam基础答疑.md
Normal file
@@ -0,0 +1,131 @@
|
||||
<audio id="audio" title="FAQ第三期 | Apache Beam基础答疑" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/14/03/147bb1f2fa8ab19f6b8de19409503803.mp3"></audio>
|
||||
|
||||
你好,我是蔡元楠。
|
||||
|
||||
这里是“FAQ第三期:Apache Beam基础答疑”。这一期主要是针对上周结束的模块四——Apache Beam的基础知识部分进行答疑,并且做了一些补充。
|
||||
|
||||
如果你对文章的印象不深了,可以先点击题目返回文章复习。当然,你也可以继续在留言中提出疑问。希望我的解答对你有所帮助。
|
||||
|
||||
## [22 | Apache Beam的前世今生](https://time.geekbang.org/column/article/99379)
|
||||
|
||||
在第22讲中,我分享了Apache Beam的诞生历程。留言中渡码、coder和Milittle都分享了自己了解的技术变迁、技术诞生历史。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/33/cf/337b762426b35a4b4222f33f7def3dcf.jpg" alt="unpreview">
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1e/89/1e59031e7acad0480e41ff5d80c0c889.jpg" alt="unpreview">
|
||||
|
||||
而JohnT3e则是分享了我在文章中提到的几个论文的具体内容。他分享的论文是非常好的补充材料,也希望你有时间的话可以下载来看一看。我把链接贴在了文章里,你可以直接点击下载浏览。
|
||||
|
||||
[MapReduce论文](https://research.google.com/archive/mapreduce-osdi04.pdf)<br>
|
||||
[Flumejava论文](https://research.google.com/pubs/archive/35650.pdf)<br>
|
||||
[MillWheel论文](https://research.google.com/pubs/archive/41378.pdf)<br>
|
||||
[Data flow Model论文](https://www.vldb.org/pvldb/vol8/p1792-Akidau.pdf%5D)
|
||||
|
||||
Morgan在第22讲中提问:Beam和Spark是什么关系?
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/77/5e/772769f1de87b38363aa5aa59d22dd5e.jpg" alt="unpreview">
|
||||
|
||||
我的回答是,Spark可以作为Beam的一个底层Runner来运行通过Beam SDK所编写的数据处理逻辑。相信在读完第23讲的内容后,Morgan会对这个概念有一个更好的认识。
|
||||
|
||||
## [23 | 站在Google的肩膀上学习Beam编程模型](https://time.geekbang.org/column/article/100478)
|
||||
|
||||
在第23讲中,明翼提出的问题如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d2/be/d2c5d558c7ddab8e4fe5f80de4f92bbe.jpg" alt="unpreview">
|
||||
|
||||
其实明翼的这些问题本质上还是在问:Beam在整个数据处理框架中扮演着一个什么样的角色?
|
||||
|
||||
首先,为什么不是所有的大数据处理引擎都可以作为底层Runner呢?原因是,并不是所有的数据处理引擎都按照Beam的编程模型去实现了相应的原生API。
|
||||
|
||||
我以现在国内很火的Flink作为底层Runner为例子来说一下。
|
||||
|
||||
在Flink 0.10版本以前,Flink的原生API并不是按照Beam所提出的编程模型来写的,所以那个时候,Flink并不能作为Beam的底层Runner。而在Flink 0.10版本以后,Flink按照Beam编程模型的思想重写了DataStream API。这个时候,如果我们用Beam SDK编写完数据处理逻辑就可以直接转换成相应的Flink原生支持代码。
|
||||
|
||||
当然,明翼说的没错,因为不是直接在原生Runner上编写程序,在参数调整上肯定会有所限制。但是,Beam所提倡的是一个生态圈系统,自然是希望不同的底层数据处理引擎都能有相应的API来支持Beam的编程模型。
|
||||
|
||||
这种做法有它的好处,那就是对于专注于应用层的工程师来说,它解放了我们需要学习不同引擎中原生API的限制,也改善了我们需要花时间了解不同处理引擎的弊端。对于专注于开发数据处理引擎的工程师来说,他们可以根据Beam编程模型不断优化自身产品。这样会导致更多产品之间的竞争,从而最终对整个行业起到良性的促进作用。
|
||||
|
||||
在第23讲中,JohnT3e也给出了他对Beam的理解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/da/bf/da3bff05ff22f997f8e70cb87acf4abf.jpg" alt="">
|
||||
|
||||
我是很赞成JohnT3e的说法的。这其实就好比SQL,我们学习SQL是学习它的语法,从而根据实际应用场景来写出相应的SQL语句去解决问题。
|
||||
|
||||
而相对的,如果觉得底层使用MySQL很好,那就是另外的决定了。写出来的SQL语句是不会因此改变的。
|
||||
|
||||
## [24 | 为什么Beam要如此抽象封装数据?](https://time.geekbang.org/column/article/100666)
|
||||
|
||||
在第24讲中,人唯优的提问如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/10/a9/10d454ffc0205cf93023cd1a03022ea9.jpg" alt="unpreview">
|
||||
|
||||
确实,Beam的Register机制和Spark里面的kryo Register是类似的机制。Beam也的确为常见的数据格式提供了默认的输入方式的。
|
||||
|
||||
但这是不需要重复工作的。基本的数据结构的coder在[GitHub](https://github.com/apache/beam/tree/master/sdks/java/core/src/main/java/org/apache/beam/sdk/coders)上可以看到。比如String,List之类。
|
||||
|
||||
## [25 | Beam数据转换操作的抽象方法](https://time.geekbang.org/column/article/101735)
|
||||
|
||||
在第25讲中,我们学习了Transform的概念和基本的使用方法,了解了怎样编写Transform的编程模型DoFn类。不过,sxpujs认为通用的DoFn很别扭。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/22/07/22c8f87387991a176a5302d062675c07.jpg" alt="unpreview">
|
||||
|
||||
这个问题我需要说明一下,Spark的数据转换操作API是类似的设计,Spark的数据操作可以写成这样:
|
||||
|
||||
```
|
||||
JavaRDD<Integer> lineLengths = lines.map(new Function<String, Integer>() {
|
||||
public Integer call(String s) { return s.length(); }
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
我不建议你用自己的使用习惯去评判自己不熟悉的、不一样的API。当你看到这些API的设计时,你更应该去想的,是这种设计的目标是什么,又有哪些局限。
|
||||
|
||||
比如,在数据处理框架中,Beam和Spark之所以都把数据操作提取出来让用户自定义,是因为它们都要去根据用户的数据操作构建DAG,用户定义的DoFn就成了DAG的节点。
|
||||
|
||||
实际使用中,往往出现单个数据操作的业务逻辑也非常复杂的情况,它也需要单独的单元测试。这也是为什么DoFn类在实际工作中更常用,而inline的写法相对少一点的原因。因为每一个DoFn你都可以单独拿出来测试,或者在别的Pipeline中复用。
|
||||
|
||||
## [26 | Pipeline:Beam如何抽象多步骤的数据流水线?](https://time.geekbang.org/column/article/102182)
|
||||
|
||||
在第26讲中,espzest提问如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/30/3a/3059789b7b009adab91e12081327103a.jpg" alt="unpreview">
|
||||
|
||||
其实我们通过第24讲的内容可以知道,PCollection是具有无序性的,所以最简单的做法Bundle在处理完成之后可以直接append到结果PCollection中。
|
||||
|
||||
至于为什么需要重做前面的Bundle,这其实也是错误处理机制的一个trade-off了。Beam希望尽可能减少persistence cost,也就是不希望将中间结果保持在某一个worker上。
|
||||
|
||||
你可以这么想,如果我们想要不重新处理前面的Bundle,我们必须要将很多中间结果转换成硬盘数据,这样一方面增加很大的时间开销,另一方面因为数据持久化了在具体一台机器上,我们也没有办法再重新动态分配Bundle到不同的机器上去了。
|
||||
|
||||
接下来,是cricket1981的提问:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e6/80/e6baae616b335289b936853ea6f27680.jpg" alt="unpreview">
|
||||
|
||||
其实文章中所讲到的随机分配并不是说像分配随机数那样将Bundle随机分配出去给workers,只是说根据runner的不同,Bundle的分配方式也会不一样了,但最终还是还是希望能使并行度最大化。
|
||||
|
||||
至于完美并行的背后机制,Beam会在真正处理数据前先计算优化出执行的一个有向无环图,希望保持并行处理数据的同时,能够减少每个worker之间的联系。
|
||||
|
||||
就如cricket1981所问的那样,Beam也有类似Spark的persist方法,BEAM-7131 issue就有反应这个问题。
|
||||
|
||||
## [28 | 如何设计创建好一个Beam Pipeline?](https://time.geekbang.org/column/article/103301)
|
||||
|
||||
在第28讲中,Ming的提问如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f9/e8/f9997a5ae3e28a36a774bead6aaabce8.jpg" alt="unpreview">
|
||||
|
||||
对此,我的回答是,一个集群有可能同时执行两个pipeline的。在实践中,如果你的四个pipeline之间如果有逻辑依赖关系,比如一个pipeline需要用到另一个pipeline的结果的话,我建议你把这些有依赖关系的pipeline合并。
|
||||
|
||||
如果你的pipeline之间是互相独立,你可以有四个独立的二进制程序。这个提问里,Ming说的集群应该是物理上的机器,这和pipeline完全是两个概念。好的集群设计应该能够让你可以自由地提交pipeline任务,你不需要去管什么具体集群适合去安排跑你的任务。
|
||||
|
||||
JohnT3e的问题如下:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/78/6e/783aceb1758747ac07e579f497fa3b6e.jpg" alt="unpreview">
|
||||
|
||||
对于这个问题,我觉得JohnT3e可以先退一步,看看这个需求场景到底适不适用于分布式数据处理。
|
||||
|
||||
分布式的核心就是并行,也就是说同一批数据集合元素和元素之间是无依赖关系的。如果你的场景对于元素的先后顺序有业务需求,可能可以看看PubSub,RPC等是不是更适合。而不是Beam的PCollection。
|
||||
|
||||
好了,第三期答疑到这里就结束了。最后,感谢在Apache Beam的基础知识模块里积极进行提问的同学们,谢谢你们的提问互动。
|
||||
|
||||
@JohnT3e、@渡码、@coder、@morgan、@Milittle、@linuxfans、@常超、@明翼、@ditiki、@朱同学、@Bin滨、@A_F、@人唯优、@张凯江、@胡墨、@cricket1981、@sxpujs、@W.T、@cricket1981、@espzest、@沈洪彬、@onepieceJT2018、@fy、@Alpha、@TJ、@dancer、@YZJ、@Ming、@蒙开强
|
||||
|
||||
|
||||
95
极客时间专栏/geek/大规模数据处理实战/专栏加餐 | 特别福利/FAQ第二期 | Spark案例实战答疑.md
Normal file
95
极客时间专栏/geek/大规模数据处理实战/专栏加餐 | 特别福利/FAQ第二期 | Spark案例实战答疑.md
Normal file
@@ -0,0 +1,95 @@
|
||||
<audio id="audio" title="FAQ第二期 | Spark案例实战答疑" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/45/dd/455b975dbed8f274f7db554bbddb2bdd.mp3"></audio>
|
||||
|
||||
你好,我是蔡元楠。
|
||||
|
||||
这里是第二期答疑,上周我们结束了Spark部分的内容,时隔一周,我们的Spark案例实战答疑终于上线了。
|
||||
|
||||
通过10讲的Spark学习,相信你已经对Spark的基本特性有了深入的了解,也基本掌握了如何使用各类常用API,如RDD、DataSet/DataFrame、Spark Streaming和Structured Streaming。今天我将针对模块三中提出的一些共性留言做一个集中答疑。
|
||||
|
||||
我首先要为积极留言的同学们点个赞,感谢同学们亲自动手实践,有的同学还通过查阅官方API文档的形式找出了正确的实现方式,这非常值得鼓励。
|
||||
|
||||
## 第18讲
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/87/81/871a0e71b4bc152a33bc4429b1ce1881.jpg" alt="">
|
||||
|
||||
在第18讲中,kylin同学留言问到,为什么用我们通篇用的是DataFrame API而不是DataSet。这是因为PySpark的SQL库只有DataFrame,并没有DataSet。不过在Scala和Java中,DataSet已经成为了统一的SQL入口。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/f0/2d/f02f83eb7122e419a80467465d7f4f2d.jpg" alt="">
|
||||
|
||||
斯盖丸同学问道,第18讲代码中groupBy(‘value’)中value是什么意思?
|
||||
|
||||
这里我说一下,SparkSession.read.text()读取文件后生成的DataFrame只有一列,它的默认名字就是“value”。
|
||||
|
||||
在[第18讲](https://time.geekbang.org/column/article/97658)的代码中,我们用lines.value去读取这一列,是同样的道理。之后我们给新的列重命名为”word”,所以groupBy的参数变成了”word”。如果你印象不深了,可以返回去查看一下。
|
||||
|
||||
讲到这里,我要为Jerry同学点个赞。在开篇词中我就提到过,我希望你可以建立自己的批判性思维,不要盲目听从任何人的意见。除了认真实践,像Jerry一样通过查阅官方文档找到了正确的实现方式,做的真的很棒,希望可以在工作中也把这份批判性思维和独立学习的能力保持下去。
|
||||
|
||||
你可以发现,在第18讲中,我介绍的explode和split方法在官方文档中都有详细的讲解,这些内容并没有很大的难点,通过自己阅读官方文档都可以学会。官方文档中还有很多我没有提到的用法,在仅仅10讲的篇幅中我不能把Spark的每一个用法都教给你。我能做的,只是从源头出发,分析新的技术、新的API产生的原因,教会你思考的方式,并结合例子,让你体会一下如何在真实场景中利用这些技术,而不是照本宣科地把官方文档复述一遍。
|
||||
|
||||
学习新的技术跟上学时背单词不一样,我们要做的是在最短时间内掌握核心内容和设计的理念,至于具体的用法,完全可以在用到的时候查阅官方文档。
|
||||
|
||||
## 第19讲
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/1c/c8/1c0d97ad6c8f972e73d5f8b4f42226c8.jpg" alt="">
|
||||
|
||||
[第19讲](https://time.geekbang.org/column/article/98374)中,gotojeff提出的这个语言选择问题,其实我之前就提到过,PySpark现在不支持DataSet,只有Scala和Java支持。这是由语言特性决定的,Python是动态类型的语言,而DataSet是强类型的,要求在编译时检测类型安全。所以,在所有用Python的代码例子中,我用的都是DataFrame。
|
||||
|
||||
大部分人都同意在Spark中,Scala和Python是优于Java和R的。至于在Spark生态中,Scala和Python孰优孰劣,这是个很主观的问题,我们不能只因为不支持DataSet这一点就说Python比Scala差。
|
||||
|
||||
Scala确实很优秀,Spark原生的实现就是用Scala写的,所以任何新发布的功能肯定支持Scala,官方文档也都是用Scala来举例子。而且Scala的性能要优于Python。但是Python也有很多优点,比如容易学习、应用场景广。这两种语言在Spark的世界中都可以满足我们绝大多数的需求,选择任何一个都不是错误的。
|
||||
|
||||
## 第20讲
|
||||
|
||||
[第20讲](https://time.geekbang.org/column/article/98537)的思考题是,为什么流的Inner-Join不支持完全输出模式?对于Inner-Join而言,加水印是否是必须的? Outer-Join呢?
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fa/a1/fa0bb8291f2c598c132bcd25322691a1.jpg" alt="">
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/bf/86/bfcf59d05ac93f3a7583a03221abb786.jpg" alt="">
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/2a/19/2a5716bc940cf44729642af5e627f219.jpg" alt="">
|
||||
|
||||
这里,我节选了never leave、jon、Ming的留言,里面是他们对这个思考题的回答,不知道你是不是也进行了深入的思考?那么现在,让我也来分享一下我的看法吧。
|
||||
|
||||
首先,现阶段不仅Inner-join不支持完全输出模式,任何类型的Join都不支持完全输出模式。
|
||||
|
||||
这是因为完全输出模式要求每当有新数据输入时,输出完整的结果表。而对于无边界数据,我们很难把所有历史数据存在内存中。所以,一般Join的都是在某个时间窗口内的流数据,这就是引入watermarking的原因。希望将来Spark可以引入新的机制来支持这一点。
|
||||
|
||||
其次,我们都知道Outer join是要在Inner Join的基础上,把没有匹配的行的对应列设为NULL。但是由于流数据的无边界性,Spark永远无法知道在未来会不会找到匹配的数据。所以,为了保证Outer Join的正确性,加水印是必须的。这样Spark的执行引擎只要在水印的有效期内没找到与之匹配的数据,就可以把对应的列设为NULL并输出。
|
||||
|
||||
那么Inner Join呢?由于Inner Join不需要连接两个表中所有的行,所以在Spark官网的叙述中,水印和事件时间的限制不是必须的。但是如果不加任何限制,流数据会不断被读入内存,这样无疑是不安全的。所以,我推荐你即便是Inner Join也要加水印和事件时间的限制。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/d9/90/d99e079892a952534d9214628f3a9590.jpg" alt="">
|
||||
|
||||
Feng.X同学不是很理解实例中两个Streaming DataFrame Join时,为什么要加上事件时间的限制“endTime > startTime AND endTime <= startTime + interval 2 hours”。
|
||||
|
||||
事实上,这个限制会抛弃任何长于2个小时的出租车出行数据。确实,对于这个例子来说,这样一个对事件时间的限制并不是必须的。加入它其实是为了告诉你,在基于事件时间来join两个流时,我们一般不考虑时间跨度过大的情况,因为它们没有普遍意义,还会影响数据分析的结果。
|
||||
|
||||
举个例子吧,对于一个网页广告来说,我们需要知道用户看到一个广告后要多长时间才会去点击它,从而评估广告的效果。
|
||||
|
||||
这里显然有两个流:一个代表用户看到广告的事件,另一个代表用户点击广告的事件。尽管我们可以通过用户的ID来Join这两个流,但是我们需要加一个限制,就是点击广告的时间不能比看到广告的时间晚太久,否则Join的结果很可能是不准确的。比如,用户可能在1:00和2:00都看到了广告,但是只在2:01点击了它,我们应该把2:00和2:01Join起来,而不应该Join1:00和2:01,因为1:00看到的广告并没有促使他点击。
|
||||
|
||||
## 第21讲
|
||||
|
||||
[第21讲](https://time.geekbang.org/column/article/99152)的思考题是,除了高延迟的流处理这一缺点外,你认为Spark还有什么不足?可以怎样改进?
|
||||
|
||||
我们都知道,Spark并不是一个完美的数据处理框架,它的优点明显,也同样有不少不足之处。
|
||||
|
||||
- 在数据规模很大的场景中,靠内存处理的开销很大。如果内存不够把中间结果写入硬盘的话,又会影响处理速度;
|
||||
- Spark没有自己的文件管理系统,它对HDFS或者其他的文件系统依赖很强;
|
||||
- 在流处理中,只支持基于时间的窗口,而不支持其他种类的窗口,比如基于数据个数的窗口。
|
||||
|
||||
正是由于Spark还有诸多不足,所以众多开源的贡献者才会持续对Spark做改进,Spark也在不断发布新版本。此外,很多新的数据处理框架的发明也是为了从根本上解决Spark存在的问题,比如Flink,还有我们正在学习的Apache Beam。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/ac/33/acedc4e52bfe3ed31bff3afae3e0b633.jpg" alt="">
|
||||
|
||||
这位飞哥grapefruit不太明白Flink支持基于数据本身窗口是什么意思,我来回答一下。
|
||||
|
||||
窗口是流数据处理中最重要的概念之一,窗口定义了如何把无边界数据划分为一个个有限的数据集。基于事件时间的窗口只是窗口的一种,它是按照事件时间的先后顺序来划分数据,比如说1:00-1:10是一个集合,1:10-1:20又是一个集合。
|
||||
|
||||
但是窗口并不都是基于时间的。比如说我们可以按数据的个数来划分,每接受到10个数据就是一个集合,这就是Count-based Window(基于数量的窗口)。Flink对于窗口的支持远比Spark要好,这是它相比Spark最大的优点之一。它不仅支持基于时间的窗口(处理时间、事件时间和摄入时间),还支持基于数据数量的窗口。
|
||||
|
||||
此外,在窗口的形式上,Flink支持滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)、全局窗口(Global Window)和会话窗口(Session Windows)。
|
||||
|
||||
到这里,我们Spark案例实战篇的答疑就结束了。欢迎继续留言,与我分享你的问题与答案。如果你觉得有所收获,也欢迎把文章分享给你的朋友。
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<audio id="audio" title="加油站 | Practice makes perfect!" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b9/a4/b912ed8bf82ef1a11432bb7fa75b3da4.mp3"></audio>
|
||||
|
||||
你好,我是蔡元楠。
|
||||
|
||||
端午节了,先祝你节日快乐。不知道正在读文章的你这几天是不是有什么娱乐活动。我最近去参加了湾区一年一度的“三俗”活动——摘樱桃。而且,还看了一个有意思的电影《疾速备战》(John Wick: Chapter 3-Parabellum),推荐给你。
|
||||
|
||||
说归正题,在专栏的更新过程中,对于“留言的处理”这一点我还是要先道个歉,前段时间因为一些个人原因比较忙,所以对于问题的回复没有做好。我会努力把答疑这件事重新做起来。既然有问题了,就是要解决掉才行。
|
||||
|
||||
专栏进程也已经过半了,我好像感觉到同学们的阅读热情都在降低,排除“养肥了再读”的情况,可能是因为很多人进入了学习的“倦怠期”。我想了下,正好又到了假期,也许是应该专门写一篇文章,来跟你“聊聊天”。毕竟对于绝大部分人来说,“学习”这件事情真的是“逆人性”的,总需要一些建议和鼓励。
|
||||
|
||||
## 学习的目的就是解决问题
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/4c/d7/4c8d129902831f314e527e4c61ebe2d7.png" alt="unpreview">
|
||||
|
||||
说实话,我们都不是天生以学习为乐趣的“学神”,所以现在我们的学习目的往往就是集中在“解决问题”上。而事实上,“解决问题”这件事其实并不是我们从工作的时候才开始面对的。
|
||||
|
||||
还记得我们在校园时期受的最多的训练吗?那就是“做题”。枯燥无味的“做题”过程就是我们接受的最初的对于“解决问题”的训练。在这个“做题”过程中学会的解决问题的方法一定是你至今都在受用的。
|
||||
|
||||
只不过是不同阶段里,你需要解决的问题的主题会变化而已。小时候应付数学题,生活中要应对和男/女朋友吵架,工作中要应对定义设计技术系统,等等。
|
||||
|
||||
当然,我们要面对的这些问题的规模也一直在变化。就像我们小时候做的题:根据a和b,求c是多少?已知条件都有,正确解法只有一个。而成人世界的问题:怎样改善北京的交通?已知条件你不是很了解,解法也不止一个,而且很难验证。
|
||||
|
||||
我十分同意Amazon创始人贝索斯的一句话,“与其看20年后什么会变,不如看什么不会变”。在我们的人生中,不会变的就是“人要解决问题”这件事。
|
||||
|
||||
## 工作需要你解决沟通问题
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/22/07/224246427a0315702c42ebfac0651807.png" alt="unpreview">
|
||||
|
||||
其实学习方法有很多,如果套用机器学习的术语,我们在学生时期常用的解决问题方法是Reinforcement Learning的Imitation Learning,也就是模仿学习。孔子所说的举一反三也是在说这个道理,通过做一个题,学会做相似的其他题。
|
||||
|
||||
当然,不只是具体的技术问题,与他人的沟通交流中也可以用上这样简单的道理。
|
||||
|
||||
举个例子吧,之前有一段时间里,一直困扰我的问题是,我主持的会议议程总是被人打断。
|
||||
|
||||
>
|
||||
<p>Let’s take a step back, …<br>
|
||||
Before we talk about this, let’s talk about…<br>
|
||||
……</p>
|
||||
|
||||
|
||||
而解决这个问题的方法和学生时期一样,就是模仿。模仿那些把会议组织好的人,学习他们做了什么,看他们是如何沟通的,再套用到自己身上加以练习。这里我自己总结了很多细节,比如提前一天再把agenda发给参加会的人,会议开始前把agenda投影上去,被人打断了再强势打断回来,等等。
|
||||
|
||||
>
|
||||
<p>That’s an important topic, let’s have a separate meeting.<br>
|
||||
Let’s put it offline.<br>
|
||||
We only have 20min left, let’s…<br>
|
||||
……</p>
|
||||
|
||||
|
||||
前面说过,学习的目的是解决问题。知道学习的方法只是第一步,更重要的是你要把它用到自己的工作、生活中。
|
||||
|
||||
## 工作需要你解决技术问题
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/3c/99/3c0ed3b2efe24f213842df7762f79999.png" alt="unpreview">
|
||||
|
||||
说到这儿,我不知道你是不是了解我的工作,我给你简单介绍一下吧。其实这方面挺简单的,你随意Google一下,都能找到有关Google Brain的介绍。
|
||||
|
||||
Google Brain的雏形起源于一项斯坦福大学与Google的联合研究项目。
|
||||
|
||||
2011年,Google资深专家杰夫·迪恩(Jeff Dean)、研究员格雷·科拉多(Greg Corrado)和吴恩达(Andrew Ng)教授是这个小团队的最初三名成员。团队有多个主要研究方向,包括机器学习算法和技术、医疗健康、机器学习支撑计算机系统、机器人、自然语言理解、音乐艺术创作和知觉仿真等。
|
||||
|
||||
我现在的工作方向就是医疗健康,主要负责的是癌症相关的AI应用。
|
||||
|
||||
比如,能否把所有癌症相关的数据更有效地整理起来,让医生和研究者更方便地查询。这些数据非常多,包括诊断过程中的CT、活检切片、基因序列、治疗过程中患者对于不同疗法的反应,等等。
|
||||
|
||||
再举个细点的例子吧。有研究者发现,免疫疗法对于癌症患者的有效程度更多的是取决于癌变组织周围的免疫细胞环境。在这一前提下,我们要解决的问题就是:能否用AI来分析癌变组织的免疫细胞环境?
|
||||
|
||||
看到这,你大概能理解了,拥有**大规模数据的整理**、**搜集**、**存储**、**分析能力**,是我们完成工作内容的先决条件。而我们日常要锻炼的、加强的也就是这些解决技术问题的能力。
|
||||
|
||||
当然,可能大公司和小团队侧重的方面并不相同。如果你在一个小团队里,这个小团队里更看重的是你是否对这个事业有兴趣。但是,大公司主要看重的还是员工**解决沟通问题**和**解决技术问题**的能力。
|
||||
|
||||
这一点如果体现在面试流程的情境中,你可以这样理解:站在面试流程制定者的角度,他们设计一些面试流程的目的只是为了判定这个人进公司后是不是能成为一个好的同事,帮助公司成功。
|
||||
|
||||
所以,在面试的过程中,你可以先给自己一个人设,就是把自己当作是“面试官的同事”。把面试问题的内容定义成一个需要解决的问题,一个需要你们去共同解决的问题。比如,面试题条件没给全的时候,完全不需要惊慌,他很有可能是故意的,你需要做的是去和面试官沟通我们这个项目需求。
|
||||
|
||||
这与真实的工作中一样,拿到一个项目后,你要马上开始死命地工作吗?不是的。你应该是要多去问为什么。为什么做这个项目?团队想要达到什么目标?想要短期的方案还是长期的方案?这样的心态摆好之后,剩下的就是你的技术问题了。
|
||||
|
||||
从看到学,是一件事;从学到用,是一件事;从用到会,又是另外一件事了。而解决技术问题方法只有一个:Practice makes perfect!
|
||||
|
||||
今天说了这么多,其实都是我自己的一些经验。那么对于“如何解决问题”这一点,你可以分享一下你的经历吗?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user