读<<程序员>>2009精华本

一,产品经理所要做的事: 

1.市场定位

2.产品差异

3.功能特性

4.竞争状况

5.市场研究

二:生产者和消费者

为什么要有邮箱,如果寄信人直接把信交给邮递员会出现什么后果?这就造成寄信人和邮递员有直接的依赖。

在计算机编程中,很多生产者和消费者的模式,消费品就是数据。用什么来存储这些数据和操作这些数据呢:

1.用线程来操作队列

2.用进程来操作管道

3.使用Socket

双缓冲:

双缓冲就是有两个缓冲区A和B,开始的时候,生产者向A写入数据,消费者从B读取数据,生产者把A的数据填满后释放锁并等待消费者释放B的锁,消费者从B读取所有的数据后,消费者得到B的锁并向B写入数据,消费者也得到A的锁并从A读取数据.A和B由生产者和消费者交接使用。如果生产者和消费者同时处理完各自的缓冲区,同时去获取对方的锁,那就会出现死锁,生产者和消费者陷入万刧不复的境地.

三:大型Web2.0网站架构面临的问题:

A.海量数据处理:小站点的数据量并不大,select和update的成本也不大,针对查询最多建立个索引也就差不多了.但对于大型网站,用户在千万级别以上的,对一个表的select和update(还不说多表联合查询)的成本是非常高的,我们需要一个有效的数据处理方案.

B.数据并发处理:解决这个问题常用的策略就是缓存,然而在高并发的情况下有两个或者更多请求同时对缓存有更新要求时,虽然我们有lock机制,但有时还是遇到些问题,所以需要一个好的数据并发处理策略和缓存策略.

C.文件存储问题:我们考虑如何存储文件和有效的索引文件,如果一个500G的磁盘存储着零散的文件,磁盘的IO是一个巨大的问题,哪怕你的带宽足够,但是你的磁盘未必能响应过来,如果还让用户让传,那么磁盘很容易就over。也许用RAID和专用的存储服务器能解决这个问题,但这样的话存在异地访问的问题,如果服务器在云南或海外,访问速度如何解决?如果做分布式,那么文件索引和架构如何规划?文件存储这个问题没那么容易对付.

D.数据关系处理:我们很容易规划出一个符合第三范式的数据库,里面布满了多对多的关系,但在多对多关系充斥的2.0时代,第三范式首先应该被抛弃,因为我们必须有效地把多表联合查询的几率降到最低。

E.数据索引问题:众所周知,要想提高数据库查询效率,索引是最方便,最廉价的方案,但是在高update的情况下,update和delete的成本会高的无法想像,如果更新一个索引需要5分钟去完成,这对于web2.0来说是一个不可忍受的,所以索引和更新是一对冤家。

F.分布式处理:如何实现数据同步和更新,实现各地服务器的实时通信并保证各地的访问速度是分布式所要面对的问题.

G.Ajax利弊分析:成了ajax,败也ajax,但今天它在了主流。ajax可以将用户的体验做得很好,经过一些设置还可以使一些基于WebBrower的类似的组件的http攻击无效,但如果基于http数据包处理方面,ajax很容易受到攻击。由于基于js,我们可以很容易理解它的加密验证方法,对于一些计算量大的ajax请求,我们可以构造发包机,很容易就把一个服务器干掉.

H.数据安全性分析:http协议的数据包都是是明文传输的,也许你说我们可以加密啊,没用的,如我们知道的QQ,可以很容易知道它的加密方法并可以写出一个一样的加密和解密方法出来,当站点流量不是很大的时候没有人在乎,但是流量上来后所谓的外挂,所谓的群发就接踵而来了.也许你说可以用更高级别的判断和https来实现,但当你做这些处理的时候,付出的是海量的database,IO以及CPU的成本。

I.数据同步和集群处理:当数据库服务器不堪重负时,我们就需要做基于数据库的负载和集群了,这时的问题是基于网络传输时会发生数据延迟,这是很可怕但也是不可避免的问题,我们需要通过另外的手段保证在这延迟的几秒或更长的时间内实现有效的交互,比如数据散列,分割,异步处理等.

J.OpenAPI以及数据共享:openapi已经成了不可避免的趋势,从google,facebook到海内,校内都在考虑这个问题,它可以有效地留住用户,让更多人帮助你做最有效的开发,如何在开放接口的同时保证数据的安全和性能是需要认真思考的问题.

K.大量like,or,in以及多表查询带来的性能屏障:or,in,多表查询会造成全表遍历,如果涉及多个or查询的话会成为另外一个瓶颈,特别是在多对多关系漫天的sns站点来说更是需要一个有效的处理方案.

L.大量上传文件攻击:我们可以对上传作一些限制,如权限和上传的频率,但是当数据量很大的时候,我们需要更多考虑:如何建立一套更高效的性能更好的判断处理方案.

架构策略:

我们暂时先把用户量级别定为三种:百万级别(M),千万级别(S)和亿万级别(Q),如何最大化地保证查询和更新,在此涉及优化和索引,只讲架构初期的方案:

1.对于M级别的用户来说,现有的DBMS经过合理的布局完全可以满足需要。问题的关键其实是应对IO问题,处理的方案相对简单,对数据库文件分盘存储(不是分区,是不同的硬盘)。

2.对于S级别,我们需要对注册和入库的流程进行简单修改,解决方案是数据散列和分区视图,常用的方案有三种:

a.第一种是等容扩充法:在用户注册控制的基础上,保证每个库的用户容量不超过500万,超过后就入第二个库,以此类推,这个方案可以保证系统的有效扩充性,但不能保证数据有效地被索引.

b.第二种就是共区索引,和第一种有异曲同工之处,但是对第一种方案进行了合理的优化,按照用户名进行了分库存储,比如我们建立10个数据库,如果用户名是Crazy,那么存储在C表中,所以很容易根据用户名进行相应的数据查询,所以方案二有效地解决了数据索引问题.

c.方案三是一和二的结合,进行用户ID的编码,用序列化的一种方案将用户名以编码的形式存储,如用户名Crazy按照C,R,A...存储为数据索引,然后进行分区存储,数字类型的数据可以在数据库中更有效地被查询,更新和共享.

3.对于Q级别,数据量已经够海量了,无论用哪种方案都是头痛的问题.我们可以用一个临时的数据库,把最活跃的用户放到这个库中,查询的时候先查询临时库,如果没有再进行全库查询.

以上对M,S,Q三种级别进行了概述,下面介绍一个更高级的查询方案:数据缓存服务器,我们可以把它理解为缓冲服务器,数据作为只读使用.可以把最常用最直接的数据放到缓存服务器中,而这个缓存服务器定时从主服务器中获取并更新信息,更深入的还可以将缓存服务器再进行地次缓存.下面一点点介绍具体的解决方案:

(1)多对多优化处理

对于多对多关系,传统的处理方案有三种,第一种是通过search的方法来实现,第二种是通过建立一个索引表,存储对应的ID,第三种是通过二次归档缓冲来实现。对于第一种方案要用大量的like查询,性能不敢恭维,基于全文索引可能解决这个问题,但利用第三方的数据未必适合我们的胃口.第二种情况下,要维护索引表,并且要跨表查询,还要维护数据的唯一性,如果表里的数据大的话性能是相当低的.下面用标签和文章的例子来讲第三种方案:

在传统的数据设计中,当一篇博文发表的时候,一般是三步走:第一步插入文章数据库并获取文章ID;第二步插入标签数据库同时查询标签是否存在,如果存在就取出标签的ID,如果不存在就插入新标签并取出标签ID;第三步将文章ID和标签ID插入索引表建立关联,如果这个时候在索引表上建立了索引,那就是灾难性的,特别是数据量大的情况下,尽管它可以有效提高查询速度,但发布的速度可能会让人无法忍受...那么如何进行优化呢,请看优化四步曲:

第一步.数据冗余:使用标签时,用得最多的,就是查询标签下的文章和显示文章的标签,这样的话,为了避免跨表查询和innerjoin查询,可以对文章表做冗余,加上一个标签列,同样对于标签表,也可以作冗余,加上一个Article列。

第二步.异步存贮:平常编程中,我们会用到设计模式中的单例模式。。。在发表文章的时候,经常会因为要检查标签表造成线程拥堵,为了避免这种情况可以采用延迟加载方案。服务器应该维护一个进程,专门对标签和文章进行查询和索引。在发布文章时,我们还可以把标签同步这一工作托管给另外的进程或者服务器进行处理,并进行索引.

第三步.二次索引:对于一些需要频繁判断的热闹标签,我们还可以在内在里组织一套有效的索引,怎么样组织这样一个内存索引,可以用树来表示..

第四步.针对跨表查询的处理:处理的方法也很简单,把原来散列的,垂直分割的表现合并起来放到另外的吟诗服务器上,然后再作适当的结构优化和索引,剩下的就简单了.

(2)让并发来的更猛烈些吧

在数据高速增长和并发呈几何增长的情况下,制约我们的可能会是IO和Database方面的问题,头痛的是不管用哪种数据库都会出现超时,而且是频繁超时,频繁出现异常。一个好的缓存策略常常决定我们的成败,在大型网站架构中,最关键最核心的也就是缓存策略了。

传统的数据操作流程是这样的:用户在浏览器中发送一个web请求到Web服务器,Web服务器通过数据驱动直接到数据库进行操作。现在讲下基于高并发的数据库缓存方案,后面介绍常用的缓存策略,这个缓存方案实现的原理很简单,我们需要四类服务器:Web服务器(组)A,数据缓冲代理服务器B,Cache服务器C,数据库服务器D:(参考文件图片) 

架构就是关注点分离 

要设计良好的架构,必须做到关注点分离,这样可以产生高内聚,低耦合的系统,这就是美丽架构的终极原则。

架构就是系统的组成部件及其之间的关系。根据视角不同,架构可以分为业务架构和技术架构,一般来说,功能性需求会对业务架构产生影响,而非功能性需求会对技术架构产生影响.

例如:注册用户可以向自己的相册上传图片,并与好友分享。这是一个功能性需求,它告诉了我们在系统的业务架构中,会出现注册用户,相册,图片,好友等组成部件,它们之间存在相互关系。而系统可以支持10万并发用户,并在需要时可以方便地伸缩,扩展到支持100万到1000万的并发用户,这则是一项非功能性的需求,它告诉我们系统在性能,负载,吞吐量,可伸缩方面的特性。架构体现的是对复杂系统的分解设计,如何进行分解,则是软件设计的永恒话题。