分布式键值存储(Distributed Key-Value Store)
前言
分布式键值存储(Distributed Key-Value Store)并不是一个新鲜的玩意。
常见的Redis,Memcache等等都有很多人在用。
不过如果要是说其中的细节,如replicate,读写,一致性,retry等等的话,又是经常会遇到把自己绕的混淆不清的情况。。
恰巧我最近在看的一门网课《Programming Reactive Systems》中有一道作业题就是要自己实现一个Distributed Key-Value Store,那就正好借此机会详细写下其中的关键点。
组成系统的参与者
既然是分布式键值存储,那么肯定会有主从节点,每个结点又会有自己的持久化,而主从之间也需要协调,于是就得出了如下关键参与者:
- Primary: 主节点。接受来自client的更新(增/删/改)操作,并把更新后的数据扩散到其它节点。当然,也可以接受来自于client的读操作。
- Secondary: 从节点。接受来自主节点的更新操作。接受来自client的只读操作。
- Arbiter: 仲裁者。任何节点,无论主从,都要把自己注册到Arbiter上去。当有从节点加入或者离开集群的时候,Arbiter负责告知主节点。
- Persistence: 每个节点都拥有自己的独享的Persistence。用于把节点上的数据持久化。
- Clients: 客户端,可能与主或者从节点通信,进行各种读写操作。
[译] 类 vs 数据结构
原文作者:Robert C. Martin (Uncle Bob)
原文链接:https://blog.cleancoder.com/uncle-bob/2019/06/16/ObjectsAndDataStructures.html
类是什么?
类是一组相似对象的范本。
对象又是什么呢?
对象是对封装的数据进行操作的一组函数。
不如这么说:对象是对隐含数据进行操作的一组函数。
Desugar Scala 20 -- Self Type
Scala里有一个很有趣的语言特性叫做Self Type,可以用来限定一个trait可以被mixin到哪里去。
看个例子:
1 | trait User { |
User就仅仅相当于一个Interface,定义一个username。
Tweeter内的第一行是重点 self: User => 就限定了Tweeter只能被mixin到实现了User的类里面去。
由于可以确定Tweeter只能被mixin到实现了User的类里面去,这样Tweeter的tweet方法内就可以放心大胆地用 username 了。
VerifiedTweeter是一个很普通的class,别人new它的时候给什么字符串,它的username就是啥。
Desugar Scala(19) -- Partial Function
先看这么一段Scala代码:
1 | object PFBlog { |
声明一个usePF方法,接受一个PartialFunction作为参数,它的实现就是传一个 Some(11) 给pf。
pf的具体类型是 PartialFunction[Option[Int], Int] 所以传递给它一个Some(11)可以期待它会返回一个Int。
然后调用usePF,传递给usePF的是一个pattern match表达式。给Some加一,给None返回0。
这时问题就来了,这个pattern match表达式是怎么能够符合usePF需要的参数类型的呢?
这么单纯的一个pattern match表达式怎么变成PartialFunction[Option[Int], Int]的呢?
为了探寻答案,先把这几行Scala代码编译成class文件,然后把byte code反编译成Java来一探究竟吧。
Future-异步函数的两个视角
我们来一起看一下两个程序员之间的故事。
以下示例代码是用Scala写的,不过本文所讲的话题并不仅限于Scala,任何有Future/Promise支持的语言都是适用的。
下面这个wiki页面罗列了各个有Future/Promise支持的语言,已经涵盖了大多数的常用语言。
Future与promise实现列表
我是异步函数的编写者
我写了两个异步函数,来提供给其他程序员同事使用。
1 | type CallBack = Try[String] => Unit |
这两个异步函数: searchTB用来从淘宝搜索物品,另一个buyFromTB用来购买搜到的物品。
「译」大规模敏捷
原文地址: https://blog.cleancoder.com/uncle-bob/2018/04/02/InTheLarge.html
原作者:Robert C. Martin (Uncle Bob)
自敏捷之开端始,我们就思考大规模敏捷的问题。我们是否能够把轻量级,迭代,增量,快速反馈等软件开发的原理应用于规模巨大的项目呢?
最初我们想到的答案是Scrum of Scrums之类的东西。这个想法是在更高的层次上递归地应用敏捷开发的原理。如果一个项目需要超过5-12个开发人员,那么可以组织两个这样的团队,以及一个更高级别的团队来“监督?”他们。
请注意上面的问号。当我们开始考虑大型项目时,我们不可避免地要谈及层级化的组织。但是敏捷似乎是厌恶组织层级的。毕竟,敏捷就是关于平等主义的。敏捷是拒绝命令和控制的。敏捷是拒绝计划和时间表的,还有…
无稽之谈!并不是这样的!
[译] FP vs OO
原文地址:https://blog.cleancoder.com/uncle-bob/2018/04/13/FPvsOO.html
原作者:Robert C. Martin (Uncle Bob)
在过去的几年中,我通过与人结对来学习函数式编程,他们中的很多人表达了反对OO的偏见。他们经常会说:“啊,这太像对象了。”
他们会这样说是因为他们认为FP和OO在某种程度上是互斥的。许多人似乎认为程序FP的程度等同于其非OO的程度。我认为这种观点是学习新事物的自然结果。
当我们采用一种新技术时,我们通常倾向于避开以前使用的旧技术。这很自然,因为我们认为新技术“更好”,因此旧技术就一定是“更糟”的。
在此博客中,我将说明OO和FP是正交的,但它们并不互斥。一个好的函数式程序可以(并且应该)是面向对象的。而且一个好的面向对象程序可以(并且应该)是函数式的。在此之前,我们必须非常谨慎地给FP和OO这两个词语下个定义。
读屠龙术五卷,粗浅总结一下太祖的套路
小岛经济学
第一章一个好点子出炉了
基本的经济原则,这个原则可以提高人们的生活水平:消费不足,敢于冒险!
在经济学术语中,资本指的是一种设备,这种设备的建设和使用本身没有什么意义,其意义在于利用设备建设和制造其他需要的东西。艾伯想要的不是那张网,而是鱼。这张网或许可以给他带来更多的鱼。因此,这张网就是一种资本,是有价值的。
在艾伯孤注一掷去编织渔网之前,小岛上还没有什么储蓄之所。他决定冒险挨饿制造的这张网成了小岛上的第一件资本设备。这件设备接着会带来储蓄(为了让这个故事能够继续进行,我们假设这些鱼不会腐烂变质),而这种剩余产品就是健康经济的命脉。
工具改变了一切,使经济的出现成为可能。长矛帮助我们捕获猎物,铲子帮助我们种植庄稼,渔网帮助我们捕鱼。这些工具提高了我们的劳动效率。我们生产的东西越多,可以消费的东西就越多,我们的生活也就变得越美好。
努力使有限的资源(每种资源都是有限的)产生最大的效益以尽可能满足人类的需求,这就是经济这一概念最简单的定义。工具、资本以及创新是实现这一目标的关键。
让你的系统在上线之前就接受炮火的洗礼-影子流量
随着持续集成,持续交付等理念的传播,很多软件开发团队都搭建了自己的staging、UAT等类生产环境。这些环境的软硬件及网络配置会尽量贴近真实的生产环境,起到沙盘演练的作用。
类生产环境毕竟前面还有一个类字,沙盘毕竟不是真实的战场,尽量贴近毕竟还不是完全吻合。
类生产环境与真实生产环境的一个重要差异就是访问量。稍具规模的互联网应用每天几百万访问量是很正常的,而类生产环境的访问量一般都会相形见绌。
有各种工具可以弥合这个差异,比如Apache JMeter,Gatling。测试人员可以和开发人员一起设计测试用例,以自动化或者半自动化的方式对类生产环境进行压力测试。
不过即便是精心设计出来的用例也还是用例,不是真实请求。真实请求具有多样性,会随着昼夜交替而变化,会随着时事热点而波动,这是很难用工具模拟出来的。
这就引出了这篇文章的主角-影子流量(shadow traffic)。
今日简史
第一部分科技颠覆
20世纪,来自纽约、伦敦、柏林和莫斯科的全球精英讲述了三大故事,号称能够解释人类过去、预测全球未来。这三大故事是:法西斯主义故事、共产主义故事,以及自由主义故事。第二次世界大战打倒了法西斯主义故事,于是从20世纪40年代末到80年代末,世界成为共产主义故事和自由主义故事的战场。等到共产主义受挫,自由主义故事就成为人类了解过去的主要指南、未来无法取代的使用手册
1938年,人类有三种全球性的故事可以选择;1968年只剩下两个;1998年,似乎只有一个故事胜出;2018年,这个数字降到了0。
过去推动俄国、中国和古巴革命的,是一群对经济至关重要但缺乏政治权力的人;而2016年,支持英国脱欧和特朗普的,却是一群虽然还享有政治权力却担心失去经济价值的人。
自由主义分别学习了帝国主义、法西斯主义和共产主义某些最优秀的概念。
自由主义学习了共产主义,于是扩大了同理的范围,开始在重视自由之外也同时重视平等。
即使在第二次世界大战之后,西方自由主义者还是很少将他们所谓的共通价值应用到非西方人民的身上。所以,荷兰人在自己的国土被纳粹残酷占领5年,于1945年重新站起来之后做的第一件事,就是召集军队横跨半个地球,希望重新占领前殖民地印度尼西亚。尽管在1940年,荷兰人只战斗了4天就举手投降放弃独立地位,但为了压制印度尼西亚的独立,他们却鏖战了4年之久。这也就难怪全球许多民族解放运动所寄望的都是苏联和中国,而不是自诩为自由主义领导者的西方国家。
Desugar Scala(18) -- stackable traits
Stackable traits是一种怎样的特性呢?
来举一个🌰
1 | abstract class IntQueue { |
定义一个IntQueue,抽象类,定义了get和put,没有实现。
1 | class BasicIntQueue extends IntQueue { |
再定义一个BasicIntQueue,把上述IntQueue实现了。
它的实现没有什么花样,就是先进先出。
当锤子遇到钉子
此文标题党。更切题的标题应该叫做《如何用统计科学来黑星座》或者是《积极注册Facehub,促进统计科学蓬勃发展》
锤子 JS Promise
最近对JS社区里的Promises/A+规范产生了很浓的兴趣,感觉Promise这套东西确实蛮不错的,给异步算法的编写者和异步算法的消费者之间提供了一套统一的沟通手段,也为异步算法的消费者提供了更悦目易读的代码组织方式。
自己把它实现了一遍:https://www.npmjs.com/package/RWPromise
然后在武汉办公室run了3次workshop:http://cuipengfei.is-a.dev/blog/2016/05/15/promise/。
手里有了这么一把锤子就总想找个钉子敲一敲。总在想能去哪里找N多异步操作来让我来组织一下呢?
自己动手实现Promises/A+规范
Promise并不是一个新的概念,它已经有将近30年的历史.
其早期的雏形还有里氏替换原则的提出者Barbara Liskov的贡献在其中.
https://en.wikipedia.org/wiki/Futures_and_promises#History
而Promises/A+这个规范的出现,则为JavaScript世界中众多Promise实现库提供了一套统一的API和交互机制.
Promises/A+提供了配套的测试集:https://github.com/promises-aplus/promises-tests.
其中共有872个测试,如果你的实现能够让全部测试绿起来,则可以认为该实现符合了标准.
利用CouchBase为弱网环境构建云同步Android应用
2015
2015第二季度
模板方法模式:子类型多态和高阶函数
模板方法模式定义了一个算法的步骤,并允许次类别为一个或多个步骤提供其实践方式。让次类别在不改变算法架构的情况下,重新定义算法中的某些步骤。
以上是wiki对模板方法的定义。
比较容易理解,我们有一个算法,其中某些步骤是确定的不太会变的代码。而另外一些步骤则需要变化并且自由组合。
《Head First Design Patterns》里有一个🌰:
假设我们需要制作咖啡因饮品,其实就是咖啡和茶。制作步骤有些类似,分为四步:1烧水,2泡,3装杯,4加调料。
其中第一步和第三步是稳定的代码,变化可能性不大,而第二步和第四步则每种饮品有自己的风味。
访问者模式 in FP:Pattern Matching
访问者模式是一种将算法与对象结构分离的软件设计模式。
这个模式的基本想法如下:首先我们拥有一个由许多对象构成的对象结构,这些对象的类都拥有一个accept方法用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中回调访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。
以上是wiki对访问者模式的定义。
这个定义着实难读。我们来看wiki给出的例子:
假设我们要为汽车建模,汽车有不同的组成部件,轮胎,车身,和引擎。
在开车之前需要先检查车辆每个部件的状况,然后依次启动所有部件以启动汽车。
观察者模式 in FP:Mutation vs Transformation
观察者模式
观察者模式(有时又被称为发布/订阅模式)是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。
以上是wiki对观察者模式的解释。
举一个《Head first design pattern》中的例子:
比如说有一个气象站,每当气象有变化的时候就需要显示当前天气。
需要显示历史平均气温,最高气温和最低气温。
还需要根据气压预测晴雨。
这种情况就很适合使用观察者模式,每种需要显示气象的装置作为观察者,气象数据本身作为可以被观察的对象。
每当气象变化的时候,被观察的对象就会通知观察者来根据新的数据作出新的显示。
解释器模式:OOP versus Functional Decomposition
解释器模式
In computer programming, the interpreter pattern is a design pattern that specifies how to evaluate sentences in a language. The basic idea is to have a class for each symbol (terminal or nonterminal) in a specialized computer language. The syntax tree of a sentence in the language is an instance of the composite pattern and is used to evaluate (interpret) the sentence for a client.
以上是wiki对解释器模式的描述。
这是一个学术性稍强的模式,不太好找到生活化的比喻。
就直接上代码吧。

