头像
青藤木鸟
https://www.qtmuniao.com
单品
全家桶
关注
Kafka —— 弥合日志系统和消息队列的鸿沟
¥2
Kafka (该论文发表于 2011 年 6 月 [1])是日志处理和消息队列系统的集大成者。较低的延迟、极高的容量和吞吐,使其可以应用于在线服务和离线业务。为了兼顾性能和可扩展性,Kafka 做了一些看起来反直觉但是却很实用的设计。例行总结一下其设计特点:面向存储的消息队列:意味在近实时的情况下能够将传统消息队列的存储增加几个数量级。实现原理是充分利用了磁盘的顺序写和操作系统自身的缓存;此外为了提高访盘、传输效率,使用了文件分段、段首索引、零拷贝和批量拉取等技术。灵活的生产消费方式:总体而言是基于主题粒度的发布订阅式架构,并且既支持组内多消费者互斥消费,也支持不同消费者组间的重复消费。这里面涉及到消息队列的两个核心设计选择:pull 式消费以及客户端侧存储消费进度。拉式消费可能会导致空轮询以及稍微的延迟,好处在于灵活;客户端存储消费进度可以使的 broker 无状态,以进行灵活伸缩和容错。为了简化实现,消费时,每个分区最多为一个消费者所消费。Zookeeper 存储元信息:利用分布式一致性组件 Zookeeper 以注册表的形式存储系统元信息,包括 broker 和消费者的存活信息、消费者和分区间的对应关系、每个分区的消费进度等等。Zookeeper 作为一个前缀树形式组织 KV、支持发布订阅的高可用组件,可以满足 Kafka 进行消费协调和进度保存的协作需求。分区级别的多副本设计:这一点在论文中还没实现,应该是后来系统开源演进时加上的。利用该条可以实现对 broker 的容错。简洁强大的消费接口:Kafka 的客户端一般提供两层接口抽象。包括无需关注分区和偏移量信息的高层(high-level)简单读写接口,以及可以灵活控制分区组织和消费进度的低层(low-level)接口。论文中只提到了前者,以表现其简洁。作者:青藤木鸟 https://www.qtmuniao.com, 转载请注明出处
设计数据密集型应用(英文文字版)
¥0
Designing Data-Intensive Applicationsby Martin KleppmannCopyright ˝ 2017 Martin Kleppmann. All rights reserved.仅供分享
Bazel 构建 golang 项目
¥2
引子Bazel 是一款谷歌开源的非常优秀的构建系统。它的定位,用官方的话来说是: a fast, scalable, multi-language and extensible build system大意为: 一款速度极快、可伸缩、跨语言并且可扩展的构建系统使用 Bazel 构建 golang 项目,除了 Bazel 本身特性外,还需要了解针对 golang 的扩展包 rules_go。另外,可以使用 bazel gazelle 来进行一些自动生成的工作。
MapReduce —— 历久而弥新
¥2
MapReduce 是谷歌 2004 年(Google 内部是从03年写出第一个版本)发表的论文里提出的一个概念。虽然已经过去15 年了,但现在回顾这个大数据时代始祖级别概念的背景、原理和实现,仍能获得对分布式系统的很多直觉性的启发,所谓温故而知新。在Google 的语境里,MapReduce 既是一种编程模型,也是支持该模型的一种分布式系统实现。它的提出,让没有分布式系统背景的开发者,也能较轻松的利用大规模集群以高吞吐量的方式来处理海量数据。其解决问题思路很值得借鉴:找到需求的痛点(如海量索引如何维护,更新和排名),对处理关键流程进行高阶抽象(分片Map,按需Reduce),以进行高效的系统实现(所谓量体裁衣)。这其中,如何找到一个合适的计算抽象,是最难的部分,既要对需求有直觉般的了解,又要具有极高的计算机科学素养。当然,并且可能更为接近现实的是,该抽象是在根据需求不断试错后进化出的海水之上的冰山一角。作者:青藤木鸟 Muniao's blog 转载请注明出处
原来 Python logging 库要这么打开
¥2
使用 Logging 前可以先捋一下我们常见的日志输出需求,俗话说,不管需求的设计就是耍流氓。能够定位事件(Event)的产生位置(代码文件&行数)和生成时间,用于调试和跟踪。一份日志可以同时送到多个目标输出。可以通过不同级别或者更精细条件筛选日志输出。可以方便的控制第三方模块的日志输出。实现上面的一切的前提下,配置/设置 尽量简单。作者:青藤木鸟 Muniao's blog 转载请注明出处Python 的 Logging 模块通过神奇的模块化设计,树形的方式组织完美的实现了以上五点。
闭包面试不用愁--Python 闭包拆解
¥2
以前学 js 的时候第一次见到闭包,当时不甚了了,还为了应付面试强行记住了一个模棱两可的“定义”:在函数中嵌套定义函数,并且在外层将内层函数返回,一同返回了外层函数的环境。当时从字面意思以及当时一个经典例子试图去理解闭包,加之”闭包”这个翻译也很不容易让人味出其中的道理,导致对其总感觉懵懵懂懂。最近工作需要,用起 python,又遇到闭包,这次看到了一些新奇有趣的资料,这才算大致把一些字面上的概念(first-class functions,bind,scope等等)贯通在一起,反过来对闭包有了更深的理解。作者:青藤木鸟 Muniao's blog 转载请注明出处引用资料列在最后,十分推荐大家去读读。
GFS(Google File System)——取舍的艺术
¥2
GFS 是谷歌为其业务定制开发的,支持弹性伸缩,为海量数据而生的分布式大文件存储系统。它运行于通用廉价商用服务器集群上,具有自动容错功能,支持大量客户端的并发访问。GFS 是为大文件而生的,针对读多于写的场景。虽然支持对文件修改,但只对追加做了优化。同时不支持 POSIX 语义,但是实现了类似的文件操作的API。它是谷歌在 MapReduce 同时期,为了解决大规模索引等数据存储所实现的具有开创性的工业级的大规模存储系统。作者:青藤木鸟 Muniao's blog 转载请注明出处其主要设计细节如下:简化系统元信息:Master 中维持了两个重要的映射,分别是文件路径到逻辑数据块,逻辑块与其多副本之间的关系。较大的数据块:选择了当时看来相当大的 64M 作为数据存储的基本单位,以此来减少元信息。放宽的一致性:允许多副本间内容不一致来简化实现、提高性能,通过读校验来保证损坏数据对用户不可见。高效副本同步:在多副本同步时分离控制流和数据流,利用网络拓扑提高同步效率。租约分散压力:Master 通过租约将部分权力下放给某个 Chunkserver ,负责某个块的多副本间的读写控制。追加并发优化:多客户端对同一文件进行并发追加,保证数据原子性及At Least Once的语义。快速备份支持:使用 COW 策略实现快照操作,并通过块的引用计数来进行写时拷贝。逐节点锁控制:对于每个操作,需要沿着文件路径逐节点获取读锁,叶子节点获取读锁或者写锁,当然文件路径会进行前缀压缩。异步垃圾回收:将数据删除与其他一些主节点的维护操作(损坏块清除,过期数据块移除)统一起来,成为一个定期过程。版本号标记:帮助客户端识别过期数据。数据块校验和:针对每 64KB 的小块打上 32 bit 的校验和。
Python函数的默认参数的那些 “坑”
¥2
栽在 Python 的默认参数的“坑”中几次之后打算专门弄一篇博客来说一下这个事情。但是最近看到一篇很好地英文文章(Default Parameter Values in Python,Fredrik Lundh | July 17, 2008 | based on a comp.lang.python post),鞭辟入里。珠玉在前,就不舞文弄墨了。当然,也算是偷个懒,在这里简单翻译一下,希望更多的人能看到。作者:青藤木鸟 Muniao's blog 转载请注明出处以下是翻译,意译,加了一些私货,不严格跟原文保持一致,语法特性以 Python3 为准。
Spark 系统的理论基石:RDD
¥2
RDD,学名可伸缩的分布式数据集(Resilient Distributed Dataset)。是一种对数据集形态的抽象,基于此抽象,使用者可以在集群中执行一系列计算,而不用将中间结果落盘。而这正是之前 MR 抽象的一个重要痛点,每一个步骤都需要落盘,使得不必要的开销很高。对于分布式系统,容错支持是必不可少的。为了支持容错,RDD 只支持粗粒度的变换。即,输入数据集是 immutable (或者说只读)的,每次运算会产生新的输出。不支持对一个数据集中细粒度的更新操作。这种约束,大大简化了容错支持,并且能满足很大一类的计算需求。初次接触 RDD 的概念的时候,不大能够理解为什么要以数据集为中心做抽象。后来随着不断深入的了解,对数据集的一致性抽象正是计算流水线(pipeline)得以存在和优化的精髓所在。在定义了数据集的基本属性(不可变,分区,依赖关系,存放位置等)后,就可以在此基础上施加各种高阶算子,以构建 DAG 执行引擎,并做适当优化。从这个角度来说,RDD 实在是一种精妙设计。作者:青藤木鸟 Muniao's blog 转载请注明出处例行总结一下 RDD 论文的主要设计点有:显式抽象。将运算中的数据集进行显式抽象,定义了其接口和属性。由于数据集抽象的统一,从而可以将不同的计算过程组合起来进行统一的 DAG 调度。基于内存。相较于 MapReduce 中间结果必须落盘,RDD 通过将结果保存在内存中,从而大大降低了单个算子计算延迟以及不同算子之间的加载延迟。宽窄依赖。在进行 DAG 调度时,定义了宽窄依赖的概念,并以此进行阶段划分,优化调度计算。谱系容错。主要依赖谱系图计算来进行错误恢复,而非进行冗余备份,因为内存实在是有限,只能以计算换存储了。交互查询。修改了 Scala 的解释器,使得可以交互式的查询基于多机内存的大型数据集。进而支持类 SQL 等高阶查询语言。
Facebook 小文件热存储:Haystack
¥2
Haystack 的基本思想就是将索引信息放在内存中,避免额外的IO。为了做到这一点,主要进行了两方面的设计:将小文件集合成大文件,减少文件数,从而减少了元信息的数目。精简文件元信息,去掉一切在 Facebook 场景中不需要的 POSIX 语义中元信息。这样就可以将数据元信息减小到一个内存可以放的下的量级,基本上每次每次数据访问同一个一次 IO 就可以完成,而非以前的好几次。作者:青藤木鸟 Muniao's blog 转载请注明出处
Facebook 大规模图片存储:f4:Facebook’s Warm BLOB Storage System
¥2
首先说下 BLOB 的意思, 英文全称是 Binary Large OBjects,可以理解为任意二进制格式的大对象;在 Facebook 的语境下,也就是用户在账户里上传的的图片,视频以及文档等数据,这些数据具有一次创建,多次读取,不会修改,偶尔删除 的特点。之前简单翻译了 Facebook 的前驱之作 —— Haystack,随着业务量发展,数据量进一步增大,过去玩法又不转了,如果所有 BLOG 都用 Haystack 存,由于其三备份的实现,在这个量级下,性价比很低。但是完全用网络挂载+传统磁盘+Unix-like(POSIX)文件系统等冷存储,读取跟不上。于是计算机科学中最常用的分而治之的思想登场了。他们首先统计了 BLOBs 的访问频次与创建时间的关系,然后提出了随着时间推移 BLOB 访问出现的冷热分布概念(和长尾效应差不多)。并据此提出了热、温分开的访问策略:用 HayStack 当做热存储去应对那些频繁访问的流量,然后用 F4 去响应剩下的不那么频繁访问的 BLOB流量,在此假设(F4只存储那些基本不怎么变动,访问量相对不大的数据)前提下,可以大大简化 F4 的设计。当然有个专门的路由层于两者之上进行了屏蔽,并进行决策和路由。对于 Haystack 来说,从其论文出来时,已经过去了七年(07~14)。相对于当时,做了少许更新,比如说去掉了 Flag 位,在 data file,Index file 之外,增加了 journal file,专门用来记录被删除的 BLOB 条目。对于 F4 来说,主要设计目的在于保证容错的前提下尽可能的减小有效冗余倍数(effective-replication-factor),以应对日益增长的温数据 存取需求。此外更加模块化,可扩展性更好,即能以加机器方式平滑扩展应对数据的不断增长。作者:青藤木鸟 Muniao's blog 转载请注明出处我总结一下,本论文主要高光点就是温热分开,冗余编码,异地取或。
继 Spark 之后,UC Berkeley AMP 的高性能AI计算引擎——Ray
¥2
继 Spark 之后,UC Berkeley AMP 实验室又推出一重磅高性能AI计算引擎——Ray,号称支持每秒数百万次任务调度。那么它是怎么做到的呢?在试用之后,简单总结一下:极简 Python API 接口:在函数或者类定义时加上 ray.remote 的装饰器并做一些微小改变,就能将单机代码变为分布式代码。这意味着不仅可以远程执行纯函数,还可以远程注册一个类(Actor模型),在其中维护大量context(成员变量),并远程调用其成员方法来改变这些上下文。高效数据存储和传输:每个节点上通过共享内存(多进程访问无需拷贝)维护了一块局部的对象存储,然后利用专门优化过的 Apache Arrow格式来进行不同节点间的数据交换。动态图计算模型:这一点得益于前两点,将远程调用返回的 future 句柄传给其他的远程函数或者角色方法,即通过远程函数的嵌套调用构建复杂的计算拓扑,并基于对象存储的发布订阅模式来进行动态触发执行。全局状态维护:将全局的控制状态(而非数据)利用 Redis 分片来维护,使得其他组件可以方便的进行平滑扩展和错误恢复。当然,每个 redis 分片通过 chain-replica 来避免单点。去中心化的调度:调度器分散在各个节点上;根据 GCS 拉取全局负载状态信息,然后随机选择一个合乎资源约束的可用节点。当然,还有一些需要优化的地方,比如 Job 级别的封装(以进行多租户资源配给),待优化的垃圾回收算法(针对对象存储,现在只是粗暴的 LRU),多语言支持(最近支持了Java,但不知道好不好用)等等。但是瑕不掩瑜,其架构设计和实现思路还是有很多可以借鉴的地方。下面行文主要是依据论文翻译而来,有些部分根据代码文档做了补充和注释。
Python 混入类(Mix-Ins)
¥2
某次在用到 Python 的 socketserver 时,看到了 ForkingMixIn 和 ThreadingMixIn。当时就对这种插件式语法糖感觉很神奇。最近自己写代码,也想写一些这种即插即用的插件代码,于是对 python 的 mix-in 机制探究了一番。简单来说它是利用多继承的特性,通过插拔额外代码片段,对原类进行花样式增强的一种技术。
一只叫做一一的英国长毛猫
¥12
记录了一只叫做一一的猫的百态。唯一的一一,小耳朵,长毛毛,大眼睛,只会做一脸震惊的表情。
壮丽西北,雄浑华夏
¥10
西北一行,不禁感慨祖国地大物博。寻觅到了“单车欲问边,属国过居延”的古居延泽,沙漠中湖眼星布,绿的梦幻。见识到了“千年不死,千年不倒”的胡杨林,守卫沙漠边缘,蓝天金叶,黄的亮眼。领略到了“高原上的眼睛”青海湖,那平静而深幽的湛蓝之色,难以忘怀。该视频是用 DJI Mavic Pro2 拍摄的三地的视频,进行剪辑而成。涉及到的场景图片如下:
故宫冬日高清美图
¥2
自己拍的在冬天的故宫几个场景高清图片
Python3 生成器剖析
¥2
引子某次面试问候选人:Python 中生成器是什么?答曰:有 yield 关键字的函数。而在我印象中此种函数返回的值是生成器,而函数本身不是。如下:In [1]: def get_nums(n): ...: for i in range(n): ...: yield i ...: In [2]: type(get_nums) Out[2]: function In [3]: nums = get_nums(10) In [4]: type(nums) Out[4]: generator 作者:青藤木鸟 Muniao's blog 转载请注明出处但看候选人那么笃定,隐隐然感觉哪里不对,于是有了以下探究。
乌兰布统+塞罕坝高清草原图
¥8
乌兰布统塞罕坝背景草原林原人工林
  • 0

    关注了

  • 5

    关注者

  • 14

    获得赞