可伸缩系统的架构经验||消息队列



  队列(Queue)又称先进先出表(First In First Out),即先进入队列的元素,先从队列中取出。加入元素的一头叫“队头”,取出元素的一头叫“队尾”。利用消息队列可以很好地异步处理数据传送和存储,当你频繁地向数据库中插入数据、频繁地向搜索引擎提交数据,就可采取消息队列来异步插入。另外,还可以将较慢的处理逻辑、有并发数量限制的处理逻辑,通过消息队列放在后台处理,例如FLV视频转换、发送手机短信、发送电子邮件等。


可伸缩系统的架构经验

FEB 27TH, 2013 | COMMENTS

最近,阅读了Will Larson的文章Introduction to Architecting System for Scale,感觉很有价值。作者分享了他在Yahoo!与Digg收获的设计可伸缩系统的架构经验。在我过往的架构经验中,由于主要参与开发企业软件系统,这种面向企业内部的软件系统通常不会有太大的负载量,太多的并发量,因而对于系统的可伸缩性考虑较少。大体而言,只要在系统部署上考虑集群以及负载均衡即可。本文给了我很多启发,现把本文的主要内容摘译出来,并结合自己对此的理解。

Larson首先认为,一个理想的系统,对于容量(Capacity)的增长应该与添加的硬件数是线性的关系。换言之,如果系统只有一台服务器,在增加了另一台同样的机器后,容量应该翻倍。以此类推。这种线性的容量伸缩方式,通常被称之为水平伸缩“Horizontal Scalability”。

在设计一个健壮的系统时,自然必须首要考虑失败的情况。Larson认为,一个理想的系统是当失去其中一台服务器的时候,系统不会崩溃。当然,对应而言,失去一台服务器也会导致容量的响应线性减少。这种情况通常被称为冗余“Redundancy”。

负载均衡

无论是水平伸缩还是冗余,都可以通过负载均衡来实现。负载均衡就好似一个协调请求的调停者,它会根据集群中机器的当前负载,合理的分配发往Web服务器的请求,以达到有效利用集群中各台机器资源的目的。显然,这种均衡器应该介于客户端与Web服务器之间,如下图所示:

本文提到了实现负载均衡的几种方法。其一是Smart Client,即将负载均衡的功能添加到数据库(以及缓存或服务)的客户端中。这是一种通过软件来实现负载均衡的方式,它的缺点是方案会比较复杂,不够健壮,也很难被重用(因为协调请求的逻辑会混杂在业务系统中)。对此,Larson在文章以排比的方式连续提出问题,以强化自己对此方案的不认可态度:

Is> "user.%s" % user_iduser_blob = memcache.get(key)if user_blob is None: user = mysql.query("SELECT * FROM>\"%s\"", user_id) if user: memcache.set(key, json.dumps(user)) return userelse: return json.loads(user_blob)

数据库缓存

数据库缓存对于应用代码没有污染,一些天才的DBA甚至可以在不修改任何代码的情况下,通过数据库调优来改进系统性能。例如通过配置Cassandra行缓存。

内存缓存

为了提高性能,缓存通常是存储在内存中。常见的内存缓存包括Memcached和Redis。不过采用这种方式仍然需要合理的权衡。我们不可能一股脑儿的将所有数据都存放在内存中,虽然这会极大地改善性能,但比较起磁盘存储而言,RAM的代价更昂贵,同时还会影响系统的健壮性,因为内存中的数据没有持久化,容易丢失。正如之前提到的,我们应该将需要的数据放入缓存,通常的算法是least recently used,即LRU。

CDN

提高性能,降低Web服务器负载的另一种常见做法是将静态媒体放入CDN(Content Distribution Network)中。如下图所示:

CDN可以有效地分担Web服务器的压力,使得应用服务器可以专心致志地处理动态页面;同时,CDN还可以通过地理分布来提高响应请求的性能。在设置了CDN后,当系统接收到请求时,首先会询问CDN以获得请求中需要的静态媒体(通常会通过HTTP Header来配置CDN能够缓存的内容)。如果请求的内容不可用,CDN会查询服务器以获得该文件,并在CDN本地进行缓存,最后再提供给请求者。如果当前网站并不大,引入CDN的效果不明显时,可以考虑暂不使用CDN,在将来可以通过使用一些轻量级的HTTP服务器如Nginx,为静态媒体分出专门的子域名如static.domain.com来提供服务。

缓存失效

引入缓存所带来的问题是如何保证真实数据与缓存数据之间的一致性。这一问题通常被称之为缓存失效(Cache Invalidation)。从高屋建瓴的角度来讲,解决这一问题的办法无非即使更新缓存中的数据。一种做法是直接将新值写入缓存中(通常被称为write-through cache);另一种做法是简单地删除缓存中的值,在等到下一次读缓存值的时候再生成。

整体而言,要避免缓存实效,可以依赖于数据库缓存,或者为缓存数据添加有效期,又或者在实现应用程序逻辑时,尽量考虑避免此问题。例如不直接使用DELETE FROM a WHERE…来删除数据,而是先查询符合条件的数据,再使得缓存中对应的数据失效,继而根据其主键显式地删除这些行。

Off-Line处理

这篇文章还提到了Off-Line的处理方式,即通过引入消息队列的方式来处理请求。事实上,在大多数企业软件系统中,这种方式也是较为常见的做法。在我撰写的文章《案例分析:基于消息的分布式架构》中,较为详细地介绍了这种架构。在引入消息队列后,Web服务器会充当消息的发布者,而在消息队列的另一端可以根据需要提供消费者Consumer。如下图所示。对于Off-Line的任务是否执行完毕,通常可以通过轮询或回调的方式来获知。

为了更好地提高代码可读性,可以在公开的接口定义中明确地标示该任务是On-Line还是Off-Line。

引入Message Queue,可以极大地缓解Web服务器的压力,因为它可以将耗时较长的任务转到专门的机器上去执行。

此外,通过引入定时任务,也可以有效地利用Web服务器的空闲时间来处理后台任务。例如,通过Spring Batch Job来执行每日、每周或者每月的定时任务。如果需要多台机器去执行这些定时任务,可以引入Spring提供的Puppet来管理这些服务器。Puppet提供了可读性强的声明性语言来完成对机器的配置。

Map-Reduce

对于大数据的处理,自然可以引入Map-Reduce。为整个系统专门引入一个Map-Reduce层来处理数据是有必要的。相对于使用SQL数据库作为数据中心的方式,Map-Reduce对可伸缩性的支持更好。Map-Reduce可以与任务的定时机制结合起来。如下图所示:

平台层

Larson认为,大多数系统都是Web应用直接与数据库通信,但如果能加入一个平台层(Platform Layer),或许会更好。

首先,将平台与Web应用分离,使得它们可以独立地进行伸缩。例如需要添加一个新的API,就可以添加新的平台服务器,而无需增加Web服务器。要知道,在这样一个独立的物理分层架构中,不同层次对服务器的要求是不一样的。例如,对于数据库服务器而言,由于需要频繁地对磁盘进行I/O操作,因此应保证数据库服务器的IO性能,如尽量使用固态硬盘。而对于Web服务器而言,则对CPU的要求比较高,尽可能采用多核CPU。

其次,增加一个额外的平台层,可以有效地提高系统的可重用性。例如我们可以将一些与系统共有特性以及横切关注点的内容(如对缓存的支持,对数据库的访问等功能)抽取到平台层中,作为整个系统的基础设施(Infrastructure)。尤其对于产品线系统而言,这种架构可以更好地为多产品提供服务。

最后,这种架构也可能对跨团队开发带来好处。平台可以抽离出一些与产品无关的接口,从而隐藏其具体实现的细节。如果划分合理,并能设计出相对稳定的接口,就可以使得各个团队可以并行开发。例如可以专门成立平台团队,致力于对平台的实现以及优化。

Posted by 张逸 Feb 27th, 2013  Architecture

Tags: Architecture, Reading, Scalability




消息队列的介绍  

有很多业务, 客户端和内网都要进行数据传输和交换, 现有架构中, 客户端不能直接访问内网, 

那么客户端只能: 先把数据保存到外网服务器, 然后内网服务器再拉回来处理. 这种方式可以保证数据
都能被处理, 但实效性不够.
 
通常, 外网服务器只起到一个暂时保存数据的作用, 保存客户端报上来的数据, 然后等待内网来拉走,
把客户端看做producer, 内网看做consumer, 这正是消息队列的用武之地.

客户端先把数据写入外网服务器的消息队列, 然后内网服务器再从消息队列取走数据, 消息队列须满足:

(1) 支持高并发的入队和出队操作, 允许很多客户端同时插入数据, 而且允许内网服务器高频率地取走

      数据

(2) 支持数据的持久化, 为保证速度, 消息队列缓存在内存中, 如果内存不够用了, 则写入磁盘.

(3) 支持一次性插入多条记录, 以及一次性取走多条数据, 这样可以提高传输效率

 
二 技术方案
1 存储方案: Tokyo Cabinet

Tokyo Cabinet数据库是日本最大的社交网站mixi开发的一款Key-Value数据库,读写速度非常快, 比MySQL快很多, 和Memcached差不多, 比Redis当然慢一截,
Tokyo Cabinet占用内存不大, 而且支持数据的持久化, 用户可以设定内存缓存的大小, 缓存不够用的时候, 就把数据持久化到磁盘

2 quickdb 内存文件系统

quickdb 是一款基于内存文件系统的 HashTable数据结构的Key-Value数据引擎,什么是内存文件系统了?就是操作系统把系统内存划出一部分当作硬盘使用。你可以像操作磁盘那样的操作内存。但效率远远比硬盘来的快多了。通俗叫做内存文件系统,只要服务器不重起数据将一直都在。
通俗的来讲>消息队列中间件的技术选型分析

http://blog.fity.cn/post/377/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值