Squid Coss文件系统技术分析
现在很多公司都使用Squid作为Cache,Alibaba也不例外,这已经不是什么秘密了。Squid的COSS文件系统特别适合小文件的Cache,是很多公司存放小图片Cache的主要手段。
今天翻电脑,找到早期写的一篇技术分析,供同学们参考,欢迎批评指正
Squid COSS技术分析
1. COSS机制分析
1.1. COSS文件结构分析
1.2. COSS的配置分析
1.3. COSS Relocation机制
2. COSS实现分析 3
2.1. Squid FileSystem架构分析
2.2. COSS所使用的核心数据结构
2.2.1. SwapDir
2.2.2. struct _cossinfo
2.2.3. cossstripe
2.3. 关键流程分析
2.3.1. rebuild
2.3.2. Cache HIT时访问Object:storeCossOpen
3. 案例分析
3.1. 案例1
4. 关于使用COSS的建议
1. COSS机制分析
1.1. COSS文件结构分析
COSS文件是Squid专门开发的用于高效存储与管理小文件的应用层File System,全称是Cyclic Object Storage System。逻辑上,COSS文件被分为M+N个Stripe。Stripe是逻辑上COSS所使用的存储单元。在物理上,COSS由多个Stripe无缝串连拼凑起来。其中M指Memory形式的Stripe在硬盘上的映射所占的个数(配置项membufs所设置,默认为10个,表示本COSS文件支持10个内存stripe),N表示COSS剩余部分(Disk stripe)所可划分的最大Stripe数目。
逻辑上,COSS文件被形象的比做是一个“6”的样子,N个Disk Stripe组成一个环形,像是“6”的下部分,M个映射到Mem Stripe,像是“6”上面部分。
一个Stripe可以存放一个或多个Object,但每个Object不能跨越两个Stripe。这就决定了Stripe一旦固定,就不能存放比Stripe大的Object;也决定了,Stripe中几乎不可避免的有空间浪费。
此外,COSS文件物理上,将Stripe再分成Block,因此block大小一定要被stripe大小整除。使用Block的作Squid层物理IO接口的原因我想可能主要是:a) 与系统匹配,使利用OS的FileSytem以及物理Disk块的得以优化 b)Squid使用stripe号,以及fileno号来寻址Object,而fileno只有24位,因此,使用的block越大,COSS支持的文件就越大。
1.2. COSS的配置分析
从squid.conf来看,coss文件的典型配置如下:
cache_dir coss /data/cache1/coss0 34500 max-size=1000000 block-size=4096 overwrite-percent=50 membufs=10
其中,34500表示该COSS文件的最大大小是34.5G,max-size表示支持存储的最大Object大小,本质上就是Stripe的大小。Block-size表示每个物理存储块是4k。overwrite-percent表示当前stripe游标与该object原来存放地方的游标(Offset)之前的距离大于50%的整个COSS文件长度时,进行Relocation(文件搬移,后面详细说明),这个overwrite-percent一定要好好理解。
1.3. COSS Relocation机制
其实上,大家从测试中可以看到,Squid使用COSS时,即使在全Cache HIT的情况下,也会有大量的IO write操作。其根本就在于COSS的relocation机制。
本质上,Relocation是解决COSS文件的老化淘汰问题而引入的。因为COSS没有LRU或其它老化算法的根本原因是COSS无法实现随意的删除。Relocation是老化的一种变相实现。为什么这么说呢,要先分析一个COSS文件的使用机制。
上面提到,COSS的Disk Stripe是一个环形的,为了说明方便,我们假设将一个COSS文件的stripe编号为1,2,3…..N。COSS文件新建起来时,Squid会记录当前使用的Stripe号为1。同时,在系统维护一个stripe大小的内存块stripe->membuf(默认是1M)。当有Object新建时,Squid将该Object的文件写到stripe->membuf,当stripe->membuf写满或不能容下新来的Object时,Squid会将该stripe交换(Swapout)到Disk上对应的stripe上。同时,将当前stripe指向2号stripe,并把新文件加到2号stripe->membuf。同理,当2号stripe->membuf满时,再swapout,并使用3号,依次类推。当整个COSS的Disk stripe写满,则循环使用1号(这就是所谓的成环)。当前游标所到之处的stripe,则会被重写(覆盖)。
从这么看,似乎COSS与生俱来就有老化功能,为什么还要费力开发Relocation呢?我的理解是,当COSS文件的Object被删除时,如果不使用relocation就会引起COSS内部碎片严重,影响服务效果。
Relocaton是如何工作的?
当Squid访问Object时,首先会依据用户的配置(overwrite-percent),判断该Object是否需要relocation。如果需要,则将该Object读出来之后,放到当前stripe->membuf,待membuf写满后swapout到当前disk stripe。从而该Object就可以在最长的时间内保存在COSS文件中了(只到游标绕COSS一个圈,再次到达时,才会覆盖),从而实现了LRU类似的作用。
可以看到,由于Relocation的原因,本身只有Read操作的IO却增加了write操作,这是COSS的一个缺点。但COSS毕竟利用大文件来存储小文件,从而避免了AUFS频繁的Open、Close系统调用操作。但可以看到,使用COSS会增加io操作的次数,从而占用过多IOPS(read/write)。
2. COSS实现分析
2.1. Squid FileSystem架构分析
<插图>
2.2. COSS所使用的核心数据结构
2.2.1. SwapDir
/*
* 对应cache_dir的一行配置
*/
struct _SwapDir {
const char *type;
int cur_size; //本目录所有Object的大小的总和,以k为单位
int low_size; //本目录由max_size及lowWaterMark算出来的low water字节数,kB
int max_size; //本目录支持的最大使用字节数, kB
char *path; //本目录的路径
int index; /* This entry’s index into the swapDirs array */
squid_off_t min_objsize; //本目录支持的最小Object
squid_off_t max_objsize; //本目录支持的最大Object
RemovalPolicy *repl; //本目录的老化策略handler
int removals; //FIXME:本参数没有使用
int scanned; //FIXME:本参数没有使用
struct {
//当前Object选择存放到本目录时,设置为1,仅用于cachemgr
unsigned int selected:1;
//本目录在cache_dir配置中设置为read only
unsigned int read_only:1;
} flags;
/* 以下为该FS对应的各操作函数指针 */
STINIT *init; /* Initialise the fs */
STCHECKCONFIG *checkconfig; /* Verify configuration */
STNEWFS *newfs; /* Create a new fs */
STDUMP *dump; /* Dump fs config snippet */
STFREE *freefs; /* Free the fs data */
STDBLCHECK *dblcheck; /* Double check the obj integrity */
STSTATFS *statfs; /* Dump fs statistics */
STMAINTAINFS *maintainfs; /* Replacement maintainence */
STCHECKOBJ *checkobj; /* Check if the fs will store an object */
STCHECKLOADAV *checkload; /* Check if the fs is getting overloaded .. */
/* These two are notifications */
STREFOBJ *refobj; /* Reference this object */
STUNREFOBJ *unrefobj; /* Unreference this object */
STCALLBACK *callback; /* Handle pending callbacks */
STSYNC *sync; /* Sync the directory */
/* 以上为对本类FS的Object的操作函数 */
struct {
STOBJCREATE *create;
STOBJOPEN *open;
STOBJCLOSE *close;
STOBJREAD *read;
STOBJWRITE *write;
STOBJUNLINK *unlink;
STOBJRECYCLE *recycle;
} obj;
/* 日志操作函数指针 */
struct {
STLOGOPEN *open;
STLOGCLOSE *close;
STLOGWRITE *write;
struct {
STLOGCLEANSTART *start;
STLOGCLEANNEXTENTRY *nextentry;
STLOGCLEANWRITE *write;
STLOGCLEANDONE *done;
void *state;
} clean;
int writes_since_clean;
} log;
struct {
int blksize; //本文件系统的块大小
} fs;
void *fsdata;
};
这是Squid FileSystem的一个抽象,对于每一个具体的实现,如COSS,则会利用利用自己的open, close, create等函数注册到这些API中。这种实现与Linux内核的Filesystem的实现方式一致。
某种意义上讲,我们可以基于这个抽象层自己开发适合自己业务的文件系统层。这就叫抽象层,叫接口层。是OS实现中重要的思想与技术。做过Linux内核开发的人应该很好理解。
2.2.2. struct _cossinfo
仅列出我们关心数据成员。
struct _cossinfo {
dlink_list membufs; //用link快速指向memory stripe
//一个快的指针,总是指向正在使用的Disk Stripe的membuf
struct _cossmembuf *current_membuf;
//指向整个COSS的当前offset,可能大于maxoffset
off_t current_offset; /* in bytes */
float minumum_overwrite_pct; //overwrite-percent的配置值
int minimum_stripe_distance; //由overwrite-percent计算的当前游标与Object原址所在施标大于distance时,就进行Object的搬迁,唯一用途在storeCossRelocateRequired的判断
//以下是Disk Stripes信息
int numstripes; //按COSS文件大小计算的,可以存的numstripes数
struct _cossstripe *stripes; //总大小是COSS文件支持的最大Disk stripe数,是一个以numstripes为下标的数组
int curstripe; //当前正在使用的stripe的号
int max_disk_nf; //等于coss文件的最大Block数
//以下是Memory Stripes信息
off_t current_memonly_offset;
struct _cossmembuf *current_memonly_membuf;
int nummemstripes; //默认是10个,内存stripe的大小
//指向内存stripe,是一个指针数组,大小是nummemstripes
struct _cossstripe *memstripes; //仅在storeCossMaybeFreeBuf时清除,是在writeMemBufDone时调用
int curmemstripe; //并不是内存stripe占用的数目,而是当前空闲使用的stripe
…………
}
Cossinfo是每一个COSS文件对应一个,总体上记录COSS的各Stripe分配与映射。
特别注意成员cossinfo->stripes,对于Disk Stripe,在程序初始化时,就将cossinfo->stripes分配成一个numstripes大小(最大disk stripe数目)的数组。Cossinfo->stripes[n]就分别对应这N个disk stripe。里面有足够的信息记录每一个disk stripe的使用情况。
另一个重要的成员是cossinfo-> memstripes。与Disk Stripe的实现与使用形式基本一致。
Squid就是利用这这个数据结构来管理整个COSS的,我们下面通过流程分析来理解。
2.2.3. cossstripe
struct _cossstripe {
int id;
int numdiskobjs; //本stripe的object数目
int pending_relocs;
struct _cossmembuf *membuf; //正在写的object{s!} mem_buf,写满后同步到disk?
dlink_list objlist; //本stripe中支持的objectslist,类型是StoreEntry。
};
2.3. 关键流程分析
2.3.1. rebuild
当rebuild时,Squid会依次打开每一个COSS文件,每读到一个stripe,不将该stripe的相关信息加入到cossinfo->stripes[n]中,n是coss文件中逻辑的stripe块号。将该stripe的object信息读出后,放到cossinfo->stripe[n]下,某个object信息则放到cossinfo->stripe[n]-> objlist中。由于类型是StoreEntry,其中的其中的storeentry->swap_filen与storeentry->swap_dirn通过COSS一定的映射关系就可以算了来,在COSS文件的Offset,利用fseek就可以读取了。
简单的说,rebuild过程通过依次分析每一个stripe,将其中存在object信息还原到storeEntry的hash,以及cossinfo->stripes[n]中,就完成了整个rebuild.
2.3.2. Cache HIT时访问Object:storeCossOpen
CossOpen的伪代码表示如下:
storeCossOpen()
{
//在CossInfo的Mem Stripe找,看要访问的Object是否在Memory Stripe中
storeCossMemPointerFromDiskOffset
if ( Mem stripe HIT) {
//将该mem stripe锁定,不允许被swapout到Disk
//即使在mem stripe都被占用的情况下
storeCossMemBufLock
} else {
If (storeCossRelocateRequired) {
//当满足relocation的要求时,object很久没有被访问过了
storeCossAllocate
} else {
//object刚被访问过,就存在后面不远的stripe处,不必马上relocation
storeCossMemOnlyAllocate
//这个函数内部,当mem stripe占用满了时,就会提醒
// storeCossCreateMemOnlyBuf: no free membufs.
//You may need to increase the value of membufs
If (mem stripe占满了) {
//内部会将已经写满的stripe写到Disk上,同relocation的情况
storeCossAllocate
………………
}
}
………………..
}
}
3. 案例分析
3.1. 案例1
案例描述:
对Squid服务器做了加压的尝试,使用COSS,但log里面出现了
2009/02/22 10:26:27| storeCossCreateMemOnlyBuf: no free membufs. You may need to increase the value of membufs on the /cache/coss13 cache_dir
然后导致cache hit service time达到了秒级的响应时间,正常的情况下一般在6ms左右
技术分析
从上面的分析可以看到,当提醒“storeCossCreateMemOnlyBuf: no free membufs. You may need to increase the value of membufs”时,是由于mem stripe被占满时才提醒的。正常情况下,当mem stripe的M个stripe都占满时,squid会将部分mem stripe swapout到COSS文件上。但当storeCossMemBufLock锁定了某个mem stripe的话,则不会执行swapout。而当某个mem stripe中的object正在被访问(Object Cache HIT)时,则mem stripe被Lock,服务完成后,即会Unlock。
这个信息是在storeCossOpen(Cache HIT)的内部执行过程中被输出的,因此分析这个函数是关键。
因此,本例的结论应该是:
提示信息是由于正在被访问的object在不久前被访问过(这里的不久是指,当overwrite-percent缺省为50%时,是指在整个COSS文件遍历一次的50%的时间内。如果不理解的话,看一下代码,minimum_stripe_distance的计算方法),因此COSS的relocation机制storeCossRelocateRequired认为该Object不应relocation,所以希望用mem stripe来存放。但找不到空闲的mem stripe来存放这个object,所以只能relocation(后果是relocation使得这个被访问的object应当前游标下的stripe,下次再访问时这个object时,这个stripe又足够新,以使得又不满足relocation条件,从而又希望用mem stripe来存放——形成恶性循环)。
之所以找不到空闲的mem stripe,极有可能是由于Squid负载过重,导致每一个Object服务时间长(Mem Stripe中的object的Lock周期也长),从而由于并发Lock的数目也增大,直接导致mem stripe被占光。
从之前没有出现这种现象来推测,应该通过降低响应时间来解决这个问题。当然,从之前的技术分析可以看到,修改overwrite-percent,加大membufs数目都可以解决这个问题。但根本的原因仍然是Lock与Unlock的周期过程,即热门的Object服务时间过长。
4. 关于使用COSS的建议
从我们对COSS的技术分析可以看到:
.COSS使用stripe与block来管理文件,不能充分利用硬盘空间
.COSS由于使用relocation,导致增加写操作
.COSS的rebuild过程需要分析整个COSS文件,因此费的时间非常长,而且在rebuild过程中不能服务
.由于fileno只有24位,因此,支持的COSS文件大小有上限
.当COSS文件有文件删除操作(Cache Purge)时,导致COSS内部大量空洞,每个stripe的object数目变少,读写效率下降
.COSS无法有效支持基于目录的刷新扩展,以及更深层的内容管理
.COSS支持的Object大小有一个上限值
COSS的优势:
.较AUFS、UFS来说,避免了大量(每个Object访问一次)open/close系统调用
.更加可能使用相对连续的空间来存放文件(操作系统优先使用连接空间的分配,在COSS创建时),可能能有效利用了OS的ReadAhead预读作用(预读的stripe中,可能包括后面将要访问的object)
上面的分析可能不够全面,但我们仍可以看到,对于普通硬盘来说,使用COSS可能会对小文件的服务性能有帮助(主要是通过减少open/close,代替的是使用大量的lseek),但当有以下情况下,COSS可能不是最佳选择:
.使用SSD硬盘的设备。SSD读能力非常强,但写能力较差,COSS会增加写操作,反而较AUFS差
.有频繁的文件更新或删除(Purge)操作
.当访问的热点文件比较集中,但大于mem stripe可以存放的大小时。可能引起mem stripes满后,频繁的relocation,而从陷入案例一类似的恶性循环。
.对于Squid启动速度有较高要求的
最后,是否使用多Squid架构,以及使用什么样的Filesystem,本质上,要依据业务来定。从计算机体系架构上来看,整个系统简单的看,主要由四个资源组成:计算资源CPU,存储资源(内存与外存储),IO(这里特指网卡,因为外存也是通过IO),以及连接他们的总线。
要对Squid做优化,首先要看看对于特点的业务来说,这四个资源什么是瓶颈,是CPU还是IO,充分利用多CPU可以使Squid充分利用多CPU的计算资源,减少“串行”操作的等待时间。但是,当多个Squid使用多个coss文件时,本身也会增加一些开销,其中一项就是增加IO的竞争开销。如果参数设置不合理,IO竞争的开销会使IO的等待时间更多(使用iostat –x的await、avgqu-sz可以分析)
Squid Coss文件系统技术分析相关推荐
- squid源码分析4—coss存储机制分析
分类: 1. Coss 文件系统概述 1.1 概述 循环目标存储机制(Cyclic Object Storage Scheme,coss)尝试为squid定制一个新的文件系统.在ufs基础的机制下,主 ...
- 什么是OpenMAX技术分析OpenMAX
什么是OpenMAX技术分析OpenMAX OpenMAX是统一的抽象层,它允许访问否则需要供应商特定API的硬件. Broadcom的MMAL(多媒体抽象层API). 因此,OpenMAX允许使用此 ...
- Linux内存技术分析(上)
Linux内存技术分析(上) 一.Linux存储器 限于存储介质的存取速率和成本,现代计算机的存储结构呈现为金字塔型.越往塔顶,存取效率越高.但成本也越高,所以容量也就越小.得益于程序访问的局部性原理 ...
- WaterfallTree(瀑布树) 详细技术分析系列
前言 WaterfallTree(瀑布树) 是最强纯C#开源NoSQL和虚拟文件系统-STSdb专有的(版权所有/专利)算法/存储结构. 参考 关于STSdb,我之前写过几篇文章,譬如: STSdb, ...
- Linux文件系统:minix文件系统二进制分析3(硬链接与软链接)
文章目录 系列博文 硬链接 当前minix文件系统目录结构 创建filelevel2.txt的硬链接文件 创建filelevel2.txt的软链接文件 当前minix文件系统目录结构 hexdump文 ...
- 基于ARM9的车载导航系统的技术分析
基于ARM9的车载导航系统的技术分 目 次 摘要 ------------------------------------ 3 1 嵌入式系统简介 -------------------------- ...
- 勒索病毒WannaCry深度技术分析——详解传播、感染和危害细节
一.综述 5月12日,全球爆发的勒索病毒WannaCry借助高危漏洞"永恒之蓝"(EternalBlue)在世界范围内爆发,据报道包括美国.英国.中国.俄罗斯.西班牙.意大利.越南 ...
- 【转】嵌入式系统关键技术分析与开发应用
嵌入式系统关键技术分析与开发应用 来自http://www.chinavideo.org/index.php?option=com_content&task=view§ioni ...
- Linux文件系统:minix文件系统二进制分析1(格式化)
文章目录 系列博文 1. minix文件系统二进制分析1:刚刚格式化后的文件系统 1.1 创建硬盘 1.1.1 添加一个16M的块设备 1.1.2 格式化块设备 1.2 minix文件系统的存储结构 ...
最新文章
- Android APK加壳技术方案----代码实现
- 小程序在canvas上层做图片滚动
- Javascript模块化编程:AMD规范
- boost::contract模块实现public的测试程序
- deepin编译Linux内核,为Deepin编译Linux 5.10内核的悲伤故事经历:从入门到卸载
- go利用反射实现任意类型切片删除元素
- 信息学奥赛C++语言: 不与最大数相同的数字之和
- Linux学习笔记(9)
- 线性反馈移位寄存器 LFSR
- ChinaITLab-Linux工程师培训课程笔记5
- SpringBoot集成Beetl
- HTML---网络编程基础知识(2)
- SPDK/NVMe存储技术分析之用户态ibv_post_send()源码分析(一)
- 计算机无法启动无法修复工具,windows资源保护无法启动修复服务的解决方法
- 三个灭点来衡量一个立方体
- ToggleButton的学习与使用
- 【生活】解决广州社保无法查询的问题,2020年3月起,广州社保/医保/养老无法在微信/支付宝查询到的解决办法
- HTML实体字符、ASCII码、URLEncoder、Base64、MD5
- 键入一个整数,判断是否是质数(两种方法)
- C语言中对结构体赋初值