分布式系统设计策略
重试机制
一般情况下,写一段网络交互的代码,发起rpc或者http,都会遇到请求超时而失败情况。
可能是网络抖动(暂时的网络变更导致包不可达,比如拓扑变更)或者对端挂掉。
这时一般处理逻辑是将请求包在一个重试循环块里,如下:
[cpp] view plain copy print?
int retry = 3;
while(!request() && retry–)
sched_yield(); // or usleep(100)
. . .
一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力。当对象们连接在一起时,它们就可以相互提供服务和信息。
通常来说,当某个对象的状态发生改变时,你仍然需要对象之间能互相通信。但是出于各种原因,你也许并不愿意因为代码环境的改变而对代码做大的修改。也许,你只想根据你的具体应用环境而改进通信代码。或者,你只想简单的重新构造通信代码来避免类和类之间的相互依赖与相互从属。
当一个对象的状态发生改变时,你如何通知其他对象?是否需要一个动态方案――一个就像允许脚本的执行一样,允许自由连接的方案?
观察者模式 :定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
观察者模式允许一个对象关注其他对象的状态,并且,观察者模式还为被观测者提供了一种观测结构,或者说是一个主体和一个客体。主体,也就是被观测者,可以用来联系所有的观测它的观测者。客体,也就是观测者,用来接受主体状态的改变 观测就是一个可被观测的类(也就是主题)与一个或多个观测它的类(也就是客体)的协作。不论什么时候,当被观测对象的状态变化时,所有注册过的观测者都会得到通知。
观察者模式将被观测者(主体)从观测者(客体)种分离出来。这样,每个观测者都可以根据主体的变化分别采取各自的操作。(观察者模式和 Publish/Subscribe 模式一样,也是一种有效描述对象间相互作用的模式。)观察者模式灵活而且功能强大。对于被观测者来说,那些查询哪些类需要自己的状态信息和每次使用那些状态信息的额外资源开销已经不存在了。另外,一个观测者可以在任何合适的时候进行注册和取消注册。你也可以定义多个具体的观测类,以便在实际应用中执行不同的操作。
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。
在以下任一情况下可以使用观察者模式:
观察者模式包含如下角色:
Observer 模式允许你独立的改变目标和观察者。你可以单独复用目标对象而无需同时复用其观察者, 反之亦然。它也使你可以在不改动目标和其他的观察者的前提下增加观察者。
下面是观察者模式其它一些优点 :
观察者模式的缺点 :
简单的更新协议不提供具体细节说明目标中什么被改变了 , 这就使得上述问题更加严重。如果没有其他协议帮助观察者发现什么发生了改变,它们可能会被迫尽力减少改变。
在 php 的 SPL 支持观察者模式,SPL 提供了 SplSubject 和 SplObserver 接口。
SplSubject 接口提供了 attach()、detach()、notify() 三个方法。而 SplObserver 接口则提供了 update() 方法。
SplSubject 派生类维护了一个状态,当状态发生变化时 - 比如属性变化等,就会调用 notify() 方法,这时,之前在 attach() 方法中注册的所有 SplObserver 实例的 update() 方法就会被调用。接口定义如下:
<?php |
实现代码:
<?php |
我们扩展上面的例子,根据目标状态而更新不同的观察者:
<?php |
通过 Observer 模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放 - 封闭原则。
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式可以分为三类:
简单工厂模式 (Simple Factory, 简单工厂模式可看为工厂方法模式的一种特例,两者归为一类。 )
工厂方法模式 (Factory Method)
抽象工厂模式 (Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。
简单工厂模式 :
一个工厂类, 这个工厂类能创建多个具体产品类的实例。
一个抽象产品类,可以派生出多个具体产品类。
工厂方法模式 :
一个抽象工厂类,可以派生出多个具体工厂类。
一个抽象产品类,可以派生出多个具体产品类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式 :
一个抽象工厂类,可以派生出多个具体工厂类。
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
<?php |
/** |
/** |
<?php |
/** |
/** |
<?php |
/* |
/* |
CAP是分布式系统里最著名的理论,wiki百科如下
(摘自 :http://en.wikipedia.org/wiki/CAP_theorem)
. . .
分布式可繁也可以简,最简单的分布式就是大家最常用的,
在负载均衡服务器后加一堆web服务器,然后在上面搞一个缓存服务器来保存临时状态,
后面共享一个数据库,其实很多号称分布式专家的人也就停留于此,
大致结构如下图所示:
这种环境下真正进行分布式的只是web server而已,
并且web server之间没有任何联系,所以结构和实现都非常简单。
有些情况下,对分布式的需求就没这么简单,
在每个环节上都有分布式的需求,
比如Load Balance、DB、Cache和文件等等,
并且当分布式节点之间有关联时,
还得考虑之间的通讯,
另外,
节点非常多的时候,
得有监控和管理来支撑。这样看起来,
分布式是一个非常庞大的体系,
只不过你可以根据具体需求进行适当地裁剪。按照最完备的分布式体系来看,
可以由以下模块组成:
分布式任务处理服务:负责具体的业务逻辑处理
分布式节点注册和查询:负责管理所有分布式节点的命名和物理信息的注册与
询,是节点之间联系的桥梁
分布式DB:分布式结构化数据存取
分布式Cache:分布式缓存数据(非持久化)存取
分布式文件:分布式文件存取
网络通信:节点之间的网络数据通信
监控管理:搜集、监控和诊断所有节点运行状态
分布式编程语言:用于分布式环境下的专有编程语言,比如Elang、Scala
分布式算法:为解决分布式环境下一些特有问题的算法,比如解决一致性问题的Paxos算法
其实,分布式系统说白了,就是很多机器组成的集群,靠彼此之间的网络通信,担当的角色可能不同,共同完成同一个事情的系统。
. . .
只谈一下单链表, 链表实在是太重要, 是前面两篇说算法博客的基础, 了解了其应用和衍生, 再去了解其本身就有动力了
typedef struct Node |
头结点的优点:
include <stdio.h> |
运行结果:3 2 1
0 3 2 1
提示:没有 0 的为无头结点的头插法输出结果,有 0 的为有头结点的头插法的输出结果
. . .
使用SVN在管理代码的时候免不了进行代码的合并和还原,特别是当前版本的修改发现有重大问题的时候,还原是避免不了的,那么究竟应该怎样操作呢?
使用SVN查看文件或目录的日志的时候,右键单击日志记录会弹出下面这个界面,今天我们来着重了解一下被红圈标记的三个选项——“Update item to this version”,“Revert to this version”,“Revert changes from this version”,这三个选项对于刚接触SVN的人确实不太好区分,一开始我也搞不懂,直到亲自试验一下才搞清楚这三个选项的用法。
在讲解这三个选项的作用之前,我们还是先来假定一个使用情景,假设我们的项目文件一共有8个版本,它版本号分别是1,2,3,4,5,6,7,8。
这个选项的作用是将文件版本更新到对应所选的版本(当然内容也修改到了相应的版本)。如果我们是在版本4这里点击“Update item to this version”,表示5~8版本所作的修改全部作废,这个文件的历史回退到了版本4那个时代,但是需要注意的是,此时文件的版本是4,并不是最新的。我们知道SVN工具中如果文件不是最新版本就无法上传,所以说这个功能只是用来暂时还原一下版本,来查询某个问题的,不能将还原后的文件上传。这个特别是当你服务器启动不了了, 把版本退回一个可以启动版本的情况
这个选项的作用是将文件的内容更新到对应的版本,版本号没有发生变化。如果我们是在版本4这里点击“Revert to this version”,表示5~8版本所作的修改全部被还原,此时svn里会有5-8被还原的文件改动可以提交, 此时文件和版本4的文件一模一样,但需要注意的是这项操作相当于我们把版本4这个文件拷贝了一份赋值给了当前目录下的文件,此时的文件版本还是8,并且是可以提交的,提交以后文件的版本变成了9,增加了一个新的版本,虽然这个版本和版本4的内容是一样的。
这个选项的作用是将对应版本的修改还原,文件的版本号不发生变化,相当于在当前本版本上剔除某些版本所作的改变。如果我们是在版本4这里点击“Revert changes from this version”,表示版本4所作的修改被抹杀了,只剩下除版本4以外的7个修改了,但是此时文件是可以上传的,并且会生成新的版本9,只是版本9只包括除版本4以外的7次修改。这个选项是可以选择多个版本的,如果我们选择4,5,6,7这四个版本点击“Revert changes from this revision”,那么这几次修改都会被抹杀。如果我们选择5,6,7,8这四个版本点击“Revert changes from this revision”,表示取消这几个版本的修改,实际上和在版本4这里点击“Revert to this version”的作用是一样的。