在互联网快速发展的背景下,特别是Web 2.0,网络上的数据内容呈几何级的增长,而其中增长最快并且最容易给技术架构带来挑战的就是数目庞大的小文件,如何来解决这种高并发,大流量,小文件,热点不集中的问题,经过我们大量研究,实践之后,总结出这种海量小文件,高并发所存在的关键问题和解决方案。
我们先对比一下在Web 1.0的解决方案和Web 2.0的我们碰到的困难。
Web 1.0解决方案:
1、源数据量小,单台squid即可达到很高的命中率。
2、请求量大,用lvs+squid或者dns轮询即可解决问题。
3、squid服务器磁盘IO压力大,用超大内存做Cache。
Web 2.0目前的瓶颈:
1、源数据数量很大,导致squid hash table索引效率不高,Cache命中率低。
为了提高对文件的访问效率,往往会在前端配置一个稍大容量的缓存。但由于小文件的数量极其庞大,应用对这些文件访问的随机性非常高,使得Cache命中率极低,缓存失去了应有的作用,导致应用需要直接到后端存储系统上读取数据,给存储系统带来了极大的压力。刚开始就是我们也采用了昂贵的高端存储系统NetApp,但是在用户高并发访问的情况下,存储系统经常出现长时间无响应的严重故障。
2、源数据容量巨大,海量文件检索效率低,从而也导致单台squid命中率很低。
有些频道数据容量会超过200T,单台squid只是杯水车薪,频繁的Cache置换更是加剧了Cache效率低下,再加上现有的存储系统无法有效管理海量小文件,并且在单个目录下存放文件的数量有一定的限制,一旦文件数到达了一定规模之后,文件的检索速度就急剧下降。我们只能通过多级目录来组织存放大量的小文件,随着目录深度的增加,文件的检索开销进一步增大,检索效率随之下降。
3、大量的cache导致的磁盘IO问题。
由于目前单台Cache容量已经达到上百G,文件系统瓶颈、磁盘IO问题也很快凸显。
4、压力过大导致的hit ratio抖动。
Cache删除,写操作达到一定的比例,同时如果压力较高,会导致hit ratio呈线性下降。即使Cache没down,但也因为命中率的下降而失去应有的作用。
5、特殊集群下的单台失效问题。
在类url hash的集群下,单台cache失效会导致hash rehash,那么整个集群的squid命中率都会被冲击。
如何来解决这些问题,思路如下:
1、优化squid hash table索引算法,需要修改源squid代码。
2、Cache集群,用类url hash的方法,以增加Cache容量。
◆wccp: cisco的路由器均有此功能
◆carp: ISA,squid自身的7层调度协议
◆url hash: nginx haproxy等7层代理
3、选择合适的文件系统
XFS使用更多的内存来作为自己的高速缓存,以尽可能的延迟零散的写操作,尽可能的执行批量写操作。
4、选择更合理的磁盘搭配策略,比如Raid策略或者单盘策略等
Raid 5,10带来了不错的安全性,但是会导致磁盘IO效率低下,不做Raid的单盘性能最高,更适合单台服务器多squid进程模式。
5、集群下的单台Cache失效的接管,以免单点故障,提高可用性。
针对以上分析,我们大量尝试了开源的一些产品,像LVS,Nginx,Squid,XFS等。具体的软件组合和架构如下:
(1)Web服务器的选择,目前,大多数Web服务器的处理能力有限,互联网广泛上使用的Web服务器如Apache,其并发能力往往在2000以下,这是由Web服务器自身的设计模式(如多进程,无IO缓存等)决定的。因此,在较大规模的访问情况下,通常会表现出用户访问网站慢,Web服务器负载高。为什么选择Nginx?use linux epoll, sendfile and aio to improve the performanc,我们主要利用的是Nginx的第三方模块ngx_http_upstream_hash_module做反向代理。部分代码如下:
- upstream img{
- server squid1:81;
- server squid2:81;
- hash $request_uri;
- hash_again 0; # default 0
- hash_method crc32; # default “simple”
- }
- server {
- listen 80;
- server_name images.gx.com;
- location / {
- proxy_pass http://img;
(3)负载均衡软件,我们选择了LVS+HA,用DR模式。目前我们运行环境中的LVS(2.6的内核),普通很稳定。我们主要用Heartbeat+ldirectord。
(4) 适合处理小文件的文件系统XFS。XFS最佳表现之一在于:象ReiserFS一样,它不产生不必要的磁盘活动。XFS设法在内存中缓存尽可能多的数据,并且,通常仅当内存不足时,才会命令将数据写到磁盘时。当它将数据清仓(flushing)到磁盘时,其它IO操作在很大程度上似乎不受影响。
(5)其它优化
在客户端和服务器做大量有效的缓存策略;用更小的并且可缓存的图片(单张图片尽量不要超过200K);尽量减少http请求;开起 keepalive减少tcp连接开销;优化tcp参数;起用多域名分域名策略;减少cookie影响等。
(6)关于优化题外:大配置和架构没有问题的前提下,有money的话应该首选硬件优化方案而不是软件细节优化。
整个架构如图
后端存储垂直分割的规则如下(按00-ff散列):
- location ~ ^/[0-1][0-f]/ {
- proxy_pass http://192.168.3.12;
- }
- location ~ ^/[2-3][0-f]/ {
- proxy_pass http://192.168.3.11;
- }
- ……..
以上这个架构的优化在于:
◆实现了高可用性,最大程度上防止单点,又保证架构的伸缩性。
◆在后端服务器中模拟url hash的算法来找到内容所在的squid,提高了命中率。
◆充分发挥机器的性能,架构可扩展性,层次分明。
最后,很重要的二点:
1)要通过性能分析和监控,来找到系统瓶颈的临界点和薄弱点。监控分析是一切优化的重点,要以数据事实来调整策略。
2)架构的负荷如果已经超过设计负荷的5~10倍,就要考虑重新设计系统的架构,我们这里仅仅讨论某一阶段的架构设计。