zoukankan      html  css  js  c++  java
  • Linux Cache Mechanism Summary(undone)

    目录

    1. 缓存机制简介
    2. 内核缓存机制
    3. 内存缓存机制
    4. 文件缓存机制
    5. 数据库缓存机制 

    1. 缓存机制简介

    0x1: 什么是缓存cache

    在计算机整个领域中,缓存(cache)这个词是一个庞大的概念,总体上来说,缓存是一种处理方式的统称,缓存通过预取将经常要用到的东西(常常是多人公用)通过一个集中公用的地方进行临时保存,并通过一定的算法对其进行管理,从而显著提高资源使用方的运行效率

    0x2: 缓存的分类

    缓存的分类有很多,根据所处层次、存储位置的不同,我们可以如下分类

    1. 内核缓存机制
    这是Linux系统在内核态实现的高速缓存机制,内核缓存机制是在linux的内核代码中实现的
    http://www.penglixun.com/tech/system/linux_cache_discovery.html
        1) ./fs/fscache/cache.c: Cache实现的代码
        2) ./mm/slab.c: SLAB管理器代码
        3) ./mm/swap.c: 缓存替换算法代码
        4) ./mm/mmap.c: 内存管理器代码
        5) ./mm/mempool.c: 内存池实现代码
    
    2. 内存缓存机制
    通过将热点数据临时保存在系统的一段连续空间中,并使用相应的数据结构和API进行操作管理
        1) C言语实现的哈希表: uthash: http://troydhanson.github.io/uthash/
        2) Java、C#实现的缓存库函数(本质也是框架自己在内存中实现了一套缓存数据结构、API)
    
    3. 文件缓存机制
        1) 文件虚拟映射技术: 将磁盘上的文件映射到内存中,此后就可以想读写内存一样读写文件
        2) 缓存数据序列化保存技术: 典型的像PHP Session会将会话数据通过serialize后缓存在文件中,在任何需要的时候进行IO读写
        3) 将待缓存数据直接保存到磁盘文件中: 典型的像Discuz、dedeCMS会将配置文件、session信息、公用数据通过文件的方式缓存到磁盘上,在需要的时候再通过inlcude方式包含进来
    
    4. 数据库缓存机制
    当需要保存的缓存数据较大时,就需要使用到数据库缓存机制,现有的数据库缓存方案主要可以分为2大类
        4.1 基于内存cache的数据库缓存,定时写文件
            1) libmemcached: libmemcached
            2) Alternative PHP Cache (APC): http://pecl.php.net/package/APC 
        4.2 基于关系型数据库数据缓存
            1) FastDHT: http://sourceforge.net/projects/fastdht/ 
        4.3 基于非关系型(NoSQL)数据库缓存(key-value)
            1) Tokyo Cabinet: http://fallabs.com/tokyocabinet/
            2) Flare: http://labs.gree.jp/blog/
            3) ThruDB: https://code.google.com/p/thrudb/ 
            4) 淘宝tair: http://www.infoq.com/cn/articles/taobao-tair/
            5) redis: http://www.redis.io/

    0x3: 缓存Cache的应用场景

    除了缓解CPU密集型计算带来的时间损耗,而将计算结果缓存在cache中这种应用场景之外,在很多情况下,Cache机制(或者说Cache思想)会被应用在跨系统、跨模块通信中,两边的通信速度不匹配,即消费能力和生产能力不匹配,而cache就是有效缓解和平衡这个速度差异的一个很好的技术思想,通过cache将原本因为速度差异导致的串行阻塞转化为了异步的非等待通信方式。根据两边的速度差异,cache有不同的调控策略

    1. A_Speed < B_Speed
    
    2. A_Data_Amount(单次发送的数据量) < B_Data_Amount
    这种情况下,A系统会向B系统发送大量的"零碎包",如果B系统是Hadoop系统,则会造成分析效率地下。为了解决这个问题,需要在A系统的流量出口部署Cache模块,进行"组包操作"
        1) 组包(增大单包容量)
        if(sizeof(cache_array[]) < max_value)
        {
            继续cache;
        }
        else
        {
            立即发送
            reset 计时器;
        }
        2) 延时自动发送
        if(本次cache计时器时间 < max_time)
        {
            continue;
        }
        else
        {
            立即发送
            reset 计时器;    
        }
    
    3. A_Speed > B_Speed
    这种情况下,A系统的数据产生和发送速度远大于B系统,很容易造成DDOS攻击现象,为了解决这个问题,需要在A系统的流量出口部署"阈值流量控制模块",防止突然出现的大量数据造成峰值流量
    在实施方案的时候,需要考虑是否存在小包现象,如果存在则需要引入组包机制
        1) 切包(控制发包速度)
        if(sizeof(JSON_CACHE) > cli_json_cache_maxvalue)
        {
            发送 JSON_CACHE[0~cli_json_cache_maxvalue];
            清空 JSON_CACHE[0~cli_json_cache_maxvalue];
        }
        else
        {
            直接发送
        } 
    
    4. A_Data_Amount(单次发送的数据量) > B_Data_Amount

    2. 内核缓存机制

    待梳理

    Relevant Link:


    3. 内存缓存机制

    0x1: C uthash

    uthash是一款基于C语言实现的内存Hash缓存类库,它的核心思想是HASH表技术,通过将值与其存储位置相关联,来实现快速的随机存储

    uthash是一个C语言的hash表实现。它以宏定义的方式实现hash表,可以让程序员非常方便的使用待缓存功能的HASH表
    1. uthash支持的操作

    1. 增加
    2. 查找
    3. 删除
    4. 计数
    5. 迭代
    6. 排序
    7. 选择等操作

    2. uthash支持的hash函数

    1. OAT One-at-a-time
    2. Symbol Name
    3. JEN Jenkins (default)
    4. BER Bernstein
    5. SAX Shift-Add-Xor
    6. FNV Fowler/Noll/Vo
    7. SFH Paul Hsieh
    8. MUR MurmurHash 
    //编译代码时,可以选择不同的hash函数,只要在编译时指定就可以了 
    cc -DHASH_FUNCTION=HASH_BER -o program program.c  

    3. uthash进行缓存开发的大致步骤

    1. 包含头文件
    #include "uthash.h"  
    
    2. 自定义数据结构
        1) 每个结构代表一个键-值对
        2) 每个结构中要有一个UT_hash_handle成员(类似内核中在结构中加入list_head使之成为双链表的原理)
    struct my_struct 
    {
        int id; /* key */
        char name[10];
        UT_hash_handle hh; /* makes this structure hashable */
    };
    
    3. 定义hash表指针。这个指针为前面自定义数据结构的指针,并初始化为NULL
    /* important! initialize to NULL */  
    struct my_struct *users = NULL; 
     
    4. 建立hash表(插入新元素)
    int add_user(int user_id, char *name) 
    {
        struct my_struct *s;
        s = malloc(sizeof(struct my_struct));
        s->id = user_id;
        strcpy(s->name, name);
        /*
        users: the hash table pointer that you will insert
        id: name of key field 
        s: the value of key that you will insert
        */
        HASH_ADD_INT( users, id, s ); 
    }
    
    5. 查找
    struct my_struct *find_user(int user_id) 
    {
        struct my_struct *s;
        HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
        return s;
    }
    
    6. 删除
    void delete_user(struct my_struct *user) 
    {
        HASH_DEL( users, user); /* user: pointer of hash item to deletee */
        free(user); /* optional; it’s up to you! */
    }
    
    7. 计数
    unsigned int num_users;
    num_users = HASH_COUNT(users);
    printf("there are %u users/n", num_users);
    
    8. 迭代
    void print_users() 
    {
        struct my_struct *s;
        for(s = users; s != NULL; s=s->hh.next) 
        {
            printf("user id %d: name %s/n", s->id, s->name
        }
    }
    
    9. 排序
    int name_sort(struct my_struct *a, struct my_struct *b) 
    {
        return strcmp(a->name,b->name);
    }
    int id_sort(struct my_struct *a, struct my_struct *b) 
    {
        return (a->id - b->id);
    }
    void sort_by_name() 
    {
        HASH_SORT(users, name_sort);
    }
    void sort_by_id() 
    {
        HASH_SORT(users, id_sort);
    }

    4. uthash编程实例

    #include "uthash.h"
    #include <stdlib.h>   /* malloc */
    #include <stdio.h>    /* printf */
    
    typedef struct example_user_t 
    {
        int id;
        int cookie;
        UT_hash_handle hh;
    } example_user_t;
    
    int main(int argc,char *argv[]) 
    {
        int i;
        example_user_t *user, *users=NULL;
    
        /* create elements */
        for(i=0;i<10;i++) 
        {
            if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1);
            user->id = i;
            user->cookie = i*i;
            HASH_ADD_INT(users,id,user);
        }
    
        for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) 
        {
            printf("user %d, cookie %d
    ", user->id, user->cookie);
        }
       return 0;
    }

    更多example,请参阅

    https://github.com/troydhanson/uthash/archive/master.zip

    Relevant Link:

    http://www.cnblogs.com/haippy/archive/2012/01/12/2315532.html
    http://shentar.me/%E5%9F%BA%E4%BA%8Ec%E8%AF%AD%E8%A8%80%E7%9A%84hash-table%E5%AE%9E%E7%8E%B0%E8%BF%9B%E7%A8%8B%E5%86%85%E7%BC%93%E5%AD%98/
    http://troydhanson.github.io/uthash/
    http://blog.csdn.net/hongqun/article/details/6103275
    http://zh.wikipedia.org/zh-cn/%E5%93%88%E5%B8%8C%E8%A1%A8
    http://en.wikipedia.org/wiki/Hash_table


    4. 文件缓存机制

    待梳理

    Relevant Link:


    5. 数据库缓存机制

    待梳理

    Relevant Link:

    Copyright (c) 2014 LittleHann All rights reserved 

  • 相关阅读:
    @try { } @catch (NSException *exception) {} @finally {}
    键盘点出来就退不掉了,你可以把这几句加到有键盘的控制器里
    测试最新的微信iOS SDK 报错误
    堆、栈知识小结
    PV操作
    continue & break
    dll的def文件与__declspec(dllexport)导出函数方式比较
    setupapi.h和setupapi.lib該如何使用
    批量缺少头文件的解决办法(添加包含目录)
    易犯错误总结:
  • 原文地址:https://www.cnblogs.com/LittleHann/p/3904909.html
Copyright © 2011-2022 走看看