iSt0ne's Notes

分布式图库系统

现有图库系统通过rsync将图片同步到存储上。用户上传图片后,不能做到实时访问(图片要经过网络传输后才能落地)。另外老的系统为每张用户图片存储多种规格,网页改版后还需要重新裁切新规格,造成存储的浪费。多种规格的小图片占用系统大量inode,甚至inode先于磁盘空间被耗尽,剩余空间不能使用。

##一、系统设计目标

  • 实时:用户上传图片后能够立即显示;只存储原图,需要缩放时实时对图片进行裁切
  • 高可用:系统设计为高可用性集群,部分组件故障依然可以正常访问
  • 高效:通过对于热点图片进行缓存用户可高效访问图片服务
  • 可扩展:系统各个部分都能够轻松进行横向扩展;不用为每个项目部署一套系统
  • 廉价:使用HaProxy代替硬件负载均衡器调度用户请求;使用大硬盘服务器代替高端存储;只存储原图以节省存储成本

##二、系统设计
现有图库系统通过rsync将图片同步到存储上。用户上传图片后,不能做到实时访问(图片要经过网络传输后才能落地)。另外老的系统为每张用户图片存储多种规格,网页改版后还需要重新裁切新规格,造成存储的浪费。多种规格的小图片占用系统大量inode,甚至inode先于磁盘空间被耗尽,剩余空间不能使用。

distributed photo system

  1. 通过HaProxy对用户请求进行调度。两台HaProxy服务器通过心跳检查达到高可用,当一台宕机后请求自动切换到另一台上。
  2. 通过Squid或Varnish对图片进行缓存。通过HaProxy基于url的hash提高缓存系统的命中率。
  3. 通过Gearman对任务进行并行调度,将用户请求、响应与图片裁切、跨机房图片同步、流量统计分开,Gearman Client负责用户请求和响应,Gearman Worker负责图片裁切、跨机房图片同步、流量统计等,Gearman Server负责任务并行调度。通过这种设计可以减轻对用户访问的影响,当Gearman Worker任务繁重时,Gearman Client缓存的的图片和Squid/Varnish缓存的图片仍然能够被高效的访问;另外对跨机房图片同步、流量统计等功能可以异步完成,从而提升用户体验。另外Gearman Worker可以使用不同语言编写,如php不能满足图片裁切性能需求时可换用c语言。
  4. 采用大硬盘服务器作为图片存储,通过NFS协议挂载到Gearman Client上(用户上传图片完成后直接落地到图片存储上,用户立即可访问),当图片需要转换时直接由Gearman Client发送给Gearman Worker,完成转换后发回Gearman Client,减少NFS挂载点。在Squid/Varnish缓存服务器、Gearman Client、Gearman Worker上加装一块SSD硬盘做CacheCade,提高整个系统的I/O吞吐能力。
  5. 在Gearman Client上能够很容易的对存储进行配置,如根据项目对存储位置、目录结构、跨机房同步、成本分摊系统等进行配置。
  6. 异步对流量进行统计,这样很容易的实现图库系统费用的分摊。通过对错误日志的记录增强系统的可靠性,比如在跨机房同步图片失败后异步重新进行同步。
  7. 整个系统的各个组件都能轻松扩展,不必为每个项目进行一套图库系统部署,减少运维的工作量。Squid/Varnish缓存系统、Gearman Server、Gearman Client、Gearman Worker、存储都可以通过添加服务器进行横向扩展。

##三、为什么选择Gearman作为任务调度系统
Gearman是最早由LiveJournal内部开发并使用的一个通用并行任务调度框架,允许不同语言直接通过非常简单的方式进行互操作。前台提交工作任务(Task)和参数,由后台工作进程(Worker)完成实际工作。

gearman stack

例如前台提交用户需要进行渲染的图片,由Gearman调度到后台提供渲染服务的工作进程,在完成工作后返回结果给前台进行展示。提交工作和完成工作的代码只需要通过预先协商好的参数进行交互,具体任务的调度、负载均衡、可靠性等由Gearman服务器来确保。而针对大规模应用,可以很容易进行多路节点的集群部署。

gearman cluster

在正式对外发布后,Danga Interactive用C重写了整个服务器代码,支持PHP, Perl, Python等常见脚本客户端,支持用memcached, sqlite, postgresql, tokyocabinet等作为任务持久化队列,基本上来说是便宜又量足。