Scalable Web Architecture and Distributed Systems
Scalable Web Architecture and Distributed Systems
大规模分布式系统设计的原则
- Avaliablity
- Performance
- Reliability
- Scalability
- Manageability
- Cost
以下主要介绍了:
- Services:需要把不同service分开,比如图片上传和下载。这样对每个独立service更好优化。对图片读取可以使用更多服务器等。
- Redundancy:数据和服务都需要有多个备份。防止服务停止和数据丢失。
- Partitions:请求太多,数据存储在一个机器上不够,水平扩展,增加多个partition。存在问题有数据局部性问题,不一致问题。
- Cache:global cache, distributed cache
- Proxies:HAProxy,作为请求和转发给服务器的中间件
- Indexes:在使用更多空间,写变慢和读更快的权衡。inverted indexes.
- Load Balance
- Queue:RabbitMQ,etc.
Example:Image Hosting Application
需要提供的功能有:
- 用户可以上传图片
- 用户根据一个web link或者API获取图像
系统的其它重要方面包括:
- 没有限制图片存储数目,存储可伸缩性
- 对于下载请求的低延时
- 如果用户上传图片,图片需要一直在那里(图片数据的可靠性)
- 系统需要容易维护
- 图片主机没有高额利润,所以需要cost-effective
Services 分配不同服务在不同机器
web server比如apache或ligittpd有一个同时连接数据它可以维持的上限(默认是500,但可以高很多)。写操作可以很快消耗掉所有连接。由于读操作是异步的,可以有其它优化比如gzip压缩或chunk transfer encoding,web server可以提供更多读操作。写,趋向于维持这个连接在上传的持续时间中,因此上传1MB文件需要1s多。
考虑到这种类型的瓶颈,把read,write划分到它们各自的服务中。可以使用排队请求、缓存受欢迎图像提高读的性能。每个服务可以方便扩展,不用考虑影响另一个服务。
Flicker解决这个问题通过分布用户在不同shards,每个shard只能处理特定数目的用户。但是执行操作在所有数据库中变得复杂,比如更新写服务包含更多元数据,搜索所有图像metadata。Flicker的体系需要每个shard都被更新。
Redundancy
为了能优雅处理失败必须有服务和数据的多个备份。另一个关键因素是创建shared-nothing architecture。有这样的体系,每个节点能够独立操作,没有中心大脑管理状态或协调从其它节点的活动。这对于可扩展性很有用由于新的节点可以增加不需要特殊的条件和知识。最重要的是,没有失败的单独点,对于错误有更强的适应力。
Partitions
有很大的数据集合不能在一个单独的服务器上存储。或者一个操作需要太多的计算资源,降低性能,必须要增加容量。 当水平缩放,常见技术是划分服务成partitions,或shards。 会存在一些问题:
- Data locality。在分布式系统中,数据和操作或计算点越近,性能越好。如果数据不是local,强迫服务器采取一个昂贵的获取代价跨越网络。
- Inconsistency。 虽然划分数据有一些阻碍,但是考虑data,load,usage patterns,etc,可以将问题划分成可管理的块。
The building blocks of fast and scalable data access
最近请求的数据会被再次请求。每个request node上存储cache在内存或disk上,但当有多个request node,每个node缓存不一致,所以需要global cache。所有节点用相同的单独缓存空间。这包括增加一个服务器,或某种类型的文件仓库。可被所有请求层节点所获取。这种类型的策略可能变得有点复杂因为很容易打败一个单独缓存随着客户端和请求数目的增加。
有两种形式获取全局缓存的方式:
绝大多数使用global cache的使用第一种方式,cache本身管理驱逐和获取数据组织请求对于相同数据的洪泛。但是,有些例子第二种实现更合适,比如请求的文件很大很快可以塞满cache,或者cache里的数据是静态的不可以被驱逐。
Distributed Cache
缓存被划分用一个一致性hash函数。
分布式缓存的劣势在于挽救一个丢失的节点。一些分布式缓存解决这个通过存储数据在不同节点上。但是,这个逻辑变得很复杂,尤其当你增加或移除节点在请求层。
Proxies
一个代理服务器是接受请求和转发给服务器的中间件。
可以让cache和proxy在同一个机器上,一般最好把cache放在proxy之前。让快的服务在前面。cache从内存中读取很快,多次读取相同请求不合并不会受影响。
如果需要加proxy到系统中,可以使用Squid,Varnish。这些proxy提供了很多优化。
Indexes
索引在增加内存,写的速度减慢和更快读之间做出权衡。
也可以用Inverted indexes.
Load Balance
很很多算法可以用来处理请求,包括随机选择一个节点,round robin,甚至选择一个节点基于特定标准,比如内存和CPU最大使用化。Load balance可以实现作为软件或硬件应用。一个开源软件HAProxy得到广泛应用。
load balance的一个挑战是管理用户session相关数据。auto failure, auto removal bad nodes会导致诊断的复杂性。比如有很多请求,处理速度变慢了,如果移除了这个节点,会导致系统变得更慢。
Queues
写的有效管理。在更复杂时间中,写可能需要一个non-deterministically长的时间。比如,数据可能要写到若干个地方;系统当前处于高load下。
queue允许客户端在异步方式下工作。当客户端等待请求时,可以处理其他工作。queues也提供了服务断点和失败的保护。比如,很容易创建一个高鲁棒性队列可以重试失败的服务请求。更倾向于用一个队列强调服务质量保证而不是直接暴露客户端到中间服务失败,要求复杂的和经常不一致的错误处理。
queues是管理大规模分布式系统的基础。有一些开源队列比如**RabbitMQ,ActiveMQ,BeanstalkD",一些也用服务比如Zookeeper,甚至数据仓库Redis。