现在很多公司都使用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文件系统技术分析相关推荐

  1. squid源码分析4—coss存储机制分析

    分类: 1. Coss 文件系统概述 1.1 概述 循环目标存储机制(Cyclic Object Storage Scheme,coss)尝试为squid定制一个新的文件系统.在ufs基础的机制下,主 ...

  2. 什么是OpenMAX技术分析OpenMAX

    什么是OpenMAX技术分析OpenMAX OpenMAX是统一的抽象层,它允许访问否则需要供应商特定API的硬件. Broadcom的MMAL(多媒体抽象层API). 因此,OpenMAX允许使用此 ...

  3. Linux内存技术分析(上)

    Linux内存技术分析(上) 一.Linux存储器 限于存储介质的存取速率和成本,现代计算机的存储结构呈现为金字塔型.越往塔顶,存取效率越高.但成本也越高,所以容量也就越小.得益于程序访问的局部性原理 ...

  4. WaterfallTree(瀑布树) 详细技术分析系列

    前言 WaterfallTree(瀑布树) 是最强纯C#开源NoSQL和虚拟文件系统-STSdb专有的(版权所有/专利)算法/存储结构. 参考 关于STSdb,我之前写过几篇文章,譬如: STSdb, ...

  5. Linux文件系统:minix文件系统二进制分析3(硬链接与软链接)

    文章目录 系列博文 硬链接 当前minix文件系统目录结构 创建filelevel2.txt的硬链接文件 创建filelevel2.txt的软链接文件 当前minix文件系统目录结构 hexdump文 ...

  6. 基于ARM9的车载导航系统的技术分析

    基于ARM9的车载导航系统的技术分 目 次 摘要 ------------------------------------ 3 1 嵌入式系统简介 -------------------------- ...

  7. 勒索病毒WannaCry深度技术分析——详解传播、感染和危害细节

    一.综述 5月12日,全球爆发的勒索病毒WannaCry借助高危漏洞"永恒之蓝"(EternalBlue)在世界范围内爆发,据报道包括美国.英国.中国.俄罗斯.西班牙.意大利.越南 ...

  8. 【转】嵌入式系统关键技术分析与开发应用

    嵌入式系统关键技术分析与开发应用 来自http://www.chinavideo.org/index.php?option=com_content&task=view&sectioni ...

  9. Linux文件系统:minix文件系统二进制分析1(格式化)

    文章目录 系列博文 1. minix文件系统二进制分析1:刚刚格式化后的文件系统 1.1 创建硬盘 1.1.1 添加一个16M的块设备 1.1.2 格式化块设备 1.2 minix文件系统的存储结构 ...

最新文章

  1. Android APK加壳技术方案----代码实现
  2. 小程序在canvas上层做图片滚动
  3. Javascript模块化编程:AMD规范
  4. boost::contract模块实现public的测试程序
  5. deepin编译Linux内核,为Deepin编译Linux 5.10内核的悲伤故事经历:从入门到卸载
  6. go利用反射实现任意类型切片删除元素
  7. 信息学奥赛C++语言: 不与最大数相同的数字之和
  8. Linux学习笔记(9)
  9. 线性反馈移位寄存器 LFSR
  10. ChinaITLab-Linux工程师培训课程笔记5
  11. SpringBoot集成Beetl
  12. HTML---网络编程基础知识(2)
  13. SPDK/NVMe存储技术分析之用户态ibv_post_send()源码分析(一)
  14. 计算机无法启动无法修复工具,windows资源保护无法启动修复服务的解决方法
  15. 三个灭点来衡量一个立方体
  16. ToggleButton的学习与使用
  17. 【生活】解决广州社保无法查询的问题,2020年3月起,广州社保/医保/养老无法在微信/支付宝查询到的解决办法
  18. HTML实体字符、ASCII码、URLEncoder、Base64、MD5
  19. 键入一个整数,判断是否是质数(两种方法)
  20. C语言中对结构体赋初值

热门文章

  1. 有道云更改默认字体大小
  2. Nessus扫描系统漏洞及MSF初级
  3. Java并发工具类-循环屏障CyclicBarrier
  4. 工程伦理 清华大学 MOOC 期末答案 2020冬
  5. 大家一定要小心,招行的保险推销,电话同意了也会扣你钱,够狠!!!
  6. 2291: 编程求解2+4+6+...+n
  7. 微信公众号开发过程整理
  8. npm install的时候报错 npm err code 1
  9. 计算机多媒体的应用 毕业论文,《计算机多媒体技术的应用》-毕业论文.doc
  10. 移动互联网时代的杀手级应用是什么?