缓存 sum

10 篇文章 0 订阅

memcache 原理

两个线程,两种算法,两种方案  两种监控(命令+工具)

 

memcache 用的是多路复用I/O模型,使用多线程,-t指定开启线程数,等于cpu个数就行,它只能存储不大于1MB数据,存储数据用slab算法,减少生成内存碎片。slab算法把美1MB大小内存块称为一个slab页,每次向系统申请一个slab页,然后通过分割算法把这个slab页分割成若干chunk块 P380,memcache不是过期自动删除,而是用到的时候删除,减小开销,用的是LRU算法,从尾部寻找,因为最新数据都放在头部,如果没有,就拉大时间间隔查找,还是没有就返回NULL(申请内存失败)

 

memcahe用多线程模型,主线程接收请求,然后将请求轮询发送给工作线程,工作线程把连接push到CQ队列中,l通知工作线程,工作线程把CQ队列上的客户端连接注册到libevent上,ibevent侦听客户端连接的读写事件操作数据

 

memcache分布方法:根据键值与排序后的服务器值比大小,逆向寻找和存入对应的服务器

普通hash:用hash函数把key转化成整数,然后和memcached服务器数量取模,但是增删服务器会导致取模结果不同,数据丢失

 

一致性hash:把服务器(server)和key都映射到hash上,然后让key顺时映射到相应的server上,添加服务器的时候,根据添加的服务器逆时寻找到和前一个服务器之间的数据并映射上,删除的时候,将下一个顺时服务器逆时寻找和前一个服务器之间的数据并映射上,

 

管理工具:

memcached stats  stats reset stats slabs stats items set|get gets

memcached-tool

memcached.php

nagios+cacti

UDFs+memcacheQ
 

redis

redis 支持多个数据类型,string--静态数据,访问次数  list--消息队列,头部和尾部  set--唯一事件,投票和昵称  sorted set--优先级队列,顶贴次数 hash,支持两种数据持久化,snapshoting(快照) append-only file(追加),支持主从复制

 

sort patter|limit|asc desc alpha | store dstkey

 

客户端:redis-cli redis-server redis-benchmark

 

配置文件 /etc/redis.conf

 

事务处理,只能保证一个客户端连续执行,中间不会插入其他客户端,exec执行,discard取消,失败后不能回滚

 

持 久化,save和bgsave命令执行,是阻塞操作,而且是把内存数据完整写入磁盘,save 900 1 经过900秒或数据更改1次就进行内存快照,建议不适用这种方法;另外一种是日志追加(aoef),写入日志尾部,redis重启时读 appendonly.aof文件,但操作系统I/O有缓存,日志追加不见得能立即写入文件,用fsync函数强制写入,具体有,appendonly yes appendfsync always appendfsync everysec  appendfsync no,但会有多余命令,比如incr 100,会有99条废命令,为了压缩日志,redis 的bgrewriteaof命令,把内存数据保存到临时文件替换原有的,也可以用其他持久化方式,比如Berkeley DB或Tokyo Cabinet

 

主从同步,slave连接上master,发送 fsync同步请求,master备 份db文件发给slave,这个动作是单线程的,slave清空数据库数据并读取,master把用户修改数据发给slave,主从配置用 slave of 192.168.1.1 6379,主从配置是一对多,slave不会阻塞master,master同时处理客户端请求,只在slave上进行数据持久化,

 

 

使用消息队列发微博,避免mysql的too many connections ,把消息存在redis中,然后转发给mysql和存session(session_set_save_handler),sessionid作为key,data当成value存取

 

//weibo list

$redis=new Redis('127.0.0.1',6379);

$redis->connect();

$weibo=new Weibo();

$redis->lpush('webo_list',json_encode($weboinfo));//插入

 

while(true){

 if($redis->lsize('weibo_list')>0){

     $info = $redis->rpop('weibo_list');//读取

     $info = json_encode($info);

     $weibo->post()

}

}

 

常用命令
http://redis.readthedocs.org/en/latest/
http://langgufu.iteye.com/blog/1434408
http://www.cnblogs.com/oubo/archive/2011/09/07/2394568.html
http://www.linuxidc.com/Linux/2012-03/57573.htm
http://blog.51yip.com/cache/1439.html
http://hi.baidu.com/aqia230/item/a8f07bdfaf028fe2b3f7777c

 

redis 进阶

kv位置,vm页数、配置和交换过程以及交换方式

内存淘汰、清楚数据、关闭连接的原理

 

redis 把value放在硬盘,key放在内存中,redis快速定位value的位置,找到磁盘上的value,redis会把很少访问且占用内存大的对象交换 到磁盘中,VM是基于页的概念,一个页上有多个object对象,redis对象类型存在于多个页上,它自己能控制换入的粒度,磁盘中压缩后的对象比内存 中小很多,所以比系统I/O次数要少

 

配置项P397

vm-enabled yes

vm-swap-file          存储位置

vm-max-memory   超过内存定量就刷道磁盘

vm-max-threads  0会阻塞其他用户,和CPU个数一致就行

vm-page-size redis在内存中保存一个bitmap映射这些页是否被占用,

vm-pages

 

持 久化方法是子进程创建rdb文件,其他客户端提交的请求由父进程提供,子进程仅把数据写入rdb,然后退出。子进程和父进程共享一个swap,因为父进程 会随时依照请求把对象换入内存,子进程也需要访问swap得到数据。后台子进程做快照时,父进程不允许把内存中对象保交换到swap文件,连个进程用只读 方式访问swap文件,问题是,子进程内存快照时,不能讲新对象换出,redis会申请更多内存,就算超过了vm-max-meory设置,由于执行速度 快一般不会出现。VM系统设计将redis中的object从内存中交换到硬盘,释放内存

 

交 换到磁 盘里,value对应的redis object将被替换成VM pointer来保存value的磁盘信息,它们都有一个storage字段用来标识存储位置,key在内存、value在磁盘、value在磁盘但正在 加载到内存,value在内存但正在刷写到磁盘

 

交换的过程是,计算占 用swap文件多少页,在 swap中找到一段连续页空间保存这个对象,把对象写入swap文件,redis会锁swap文件,防止其他线程读写,写入swap文件,object换 成vmpointer,storage字段改成已被刷写到磁盘。反过来加载到内存也一样,锁swap,把rdb写入内存

 

阻塞swap value  object->pointer,storage chagned,释放内存 和非阻塞 I/O排队和处理,redis能同时处理其他客户端请求,只有交换出来的数据延迟

 

内存淘汰方法有随机淘汰法、LRU淘汰算法(最近最少使用)和TTL淘汰算法(最快过期)

对象应用计数器,get +1 del-1 get后归0

自动关闭超时连接,如果使用连接池,timeout就设为0,关闭这个功能

清除数据一个是系统每次随机获取10个清掉,还有就是用户获取(get hget)不存在就删掉.先判断是否过期,过期就删了,del还会删掉过期时间信息,因为定时器只随机删除过期数据,不可能完全删除,所以要进行过期判断。

 

 

 

 

http 缓存

 

http:

不缓存或加密或不存在etag或last-modifeid则不缓存

 

新鲜度:完整过期时间 使用过缓存副本且足够新鲜,最后更新时间在上次使用过期之前,副本直接送出,太旧发出校验请求,是否继续使用缓存

 

避免post,不会被缓存

 

是否缓存->是否新鲜->是否再验证->返回数据

expires—通用

cache- control—通用+请求 max-age s-maxage public no-cache no-store must-revalidate  proxy-prevalidate  last-modify第一次请求   if-modified-since第二次请求 true 304

 

etag--响应 响应时给出,同if-none-match验证,false 304 true200

 

header(‘Cache-Control:no-cache,must-revalidate’);

header(‘Pragma:no-cache’)

header(‘Cache-control:max-age=86400,must-revalidate’)

header(‘Last-Modified:’.gmdate(‘D,d M Y H:i:s’).’GMT’)

header(‘Expires:’.gmdate(‘D d M Y H:i:s’,time()+86400’).’GMT')

 

//Memcache

<?php
/*********************************************************************************
 * InitPHP 2.0 国产PHP开发框架  Dao-memcached 内存缓存
 *-------------------------------------------------------------------------------
 * 版权所有: CopyRight By initphp.com
 * 您可以自由使用该源码,但是在使用过程中,请保留作者信息。尊重他人劳动成果就是尊重自己
 *-------------------------------------------------------------------------------
 * $Author:zhuli
 * $Dtime:2011-10-09  
***********************************************************************************/  
class memcachedInit {  
      
    private $memcache;  
          
    /**
     * Memcache缓存-设置缓存
     * 设置缓存key,value和缓存时间
     * @param  string $key   KEY值
     * @param  string $value 值
     * @param  string $time  缓存时间
     */  
    public function set_cache($key, $value, $time = 0) {   
        return $this->memcache->set($key, $value, false, $time);  
    }  
      
    /**
     * Memcache缓存-获取缓存
     * 通过KEY获取缓存数据
     * @param  string $key   KEY值
     */  
    public function get_cache($key) {  
        return $this->memcache->get($key);  
    }  
      
    /**
     * Memcache缓存-清除一个缓存
     * 从memcache中删除一条缓存
     * @param  string $key   KEY值
     */  
    public function clear($key) {  
        return $this->memcache->delete($key);  
    }  
      
    /**
     * Memcache缓存-清空所有缓存
     * 不建议使用该功能
     * @return
     */  
    public function clear_all() {  
        return $this->memcache->flush();  
    }  
      
    /**
     * 字段自增-用于记数
     * @param string $key  KEY值
     * @param int    $step 新增的step值
     */  
    public function  increment($key, $step = 1) {  
        return $this->memcache->increment($key, (int) $step);  
    }  
      
    /**
     * 字段自减-用于记数
     * @param string $key  KEY值
     * @param int    $step 新增的step值
     */  
    public function decrement($key, $step = 1) {  
        return $this->memcache->decrement($key, (int) $step);  
    }  
      
    /**
     * 关闭Memcache链接
     */  
    public function close() {  
        return $this->memcache->close();  
    }  
      
    /**
     * 替换数据
     * @param string $key 期望被替换的数据
     * @param string $value 替换后的值
     * @param int    $time  时间值
     * @param bool   $flag  是否进行压缩
     */  
    public function replace($key, $value, $time = 0, $flag = false) {  
        return $this->memcache->replace($key, $value, false, $time);  
    }  
      
    /**
     * 获取Memcache的版本号
     */  
    public function getVersion() {  
        return $this->memcache->getVersion();  
    }  
      
    /**
     * 获取Memcache的状态数据
     */  
    public function getStats() {  
        return $this->memcache->getStats();  
    }  
      
    /**
     * Memcache缓存-设置链接服务器
     * 支持多MEMCACHE服务器
     * 配置文件中配置Memcache缓存服务器:
     * $InitPHP_conf['memcache'][0]   = array('127.0.0.1', '11211');   
     * @param  array $servers 服务器数组-array(array('127.0.0.1', '11211'))
     */  
    public function add_server($servers) {  
        $this->memcache = new Memcache;  
   
        if (!is_array($servers) || empty($servers)) exit('memcache server is null!');
    
        foreach ($servers as $val) {  
   
            $this->memcache->addServer($val[0], $val[1]);  
        }     
    }

    //   public function __construct() {
 
    //     $this->_memcache = new Memcache($this->_memcached_conf);
    //     $this->_memcache->addserver('127.0.0.1', '11211');
    // }


}  
$conf = array(array('127.0.0.1','11211'));
$mem = new memcachedInit;
//var_dump($mem);
$conn = $mem->add_server($conf);
$stats = $mem->getStats();
$mem->getVersion();
$mem->set_cache('name','zy','1200');
$mem->get_cache('name');
$mem->clear('name');
$mem->get_cache('name');
$mem->set_cache('name','zy','1200');
$mem->get_cache('name');
$mem->replace('name','zhouy');
$mem->get_cache('name');
$mem->set_cache('num',1);
$mem->get_cache('num');
$mem->increment('num');
$mem->get_cache('num');
$mem->decrement('num',2);
echo $mem->get_cache('num');


 /usr/local/bin/memcached -d -m 10  -u root -l 172.28.5.2 -p 12000 -c 1024 –P /tmp/memcached.pid

####相关选项说明
7个
-d   表示启动一个守护进程

-m 是分配给memcached使用的内存

-u   运行memcached的用户

-l     是memcached监听的ip

-p    是memcached监听的端口

-c    memcache运行的最大并发连接数

-P    是设置memcache的pid文件

11个
add_server
$host服务器的地址

$port服务器端口

$persistent是否是一个持久连接

$weight这台服务器在所有服务器中所占的权重

$timeout连接的持续时间

$retry_interval连接重试的间隔时间,默认为15,设置为-1表示不进行重试

$status控制服务器的在线状态

$failure_callback允许设置一个回掉函数来处理错误信息。


set
get
delete
flush
flush_all
close
increment
decrement
getStats

1.  pid: memcached服务进程的进程ID
2.  uptime: memcached服务从启动到当前所经过的时间,单位是秒。
3.  time: memcached服务器所在主机当前系统的时间,单位是秒。memcache <wbr>getStats <wbr>参数详解
4.  version: memcached组件的版本。这里是我当前使用的1.2.6。
5.  pointer_size:服务器所在主机操作系统的指针大小,一般为32或64.
6.  curr_items:表示当前缓存中存放的所有缓存对象的数量。不包括目前已经从缓存中删除的对象。
7.  total_items:表示从memcached服务启动到当前时间,系统存储过的所有对象的数量,包括目前已经从缓存中删除的对象。
8.  bytes:表示系统存储缓存对象所使用的存储空间,单位为字节。
9.  curr_connections:表示当前系统打开的连接数。
10. total_connections:表示从memcached服务启动到当前时间,系统打开过的连接的总数。
11. connection_structures:表示从memcached服务启动到当前时间,被服务器分配的连接结构的数量,这个解释是协议文档给的,具体什么意思,我目前还没搞明白。
12. cmd_get:累积获取数据的数量,这里是3,因为我测试过3次,第一次因为没有序列化对象,所以获取数据失败,是null,后边有2次是我用不同对象测试了2次。
13. cmd_set:累积保存数据的树立数量,这里是2.虽然我存储了3次,但是第一次因为没有序列化,所以没有保存到缓存,也就没有记录。
14. get_hits:表示获取数据成功的次数。
15. get_misses:表示获取数据失败的次数。
16. evictions:为了给新的数据项目释放空间,从缓存移除的缓存对象的数目。比如超过缓存大小时根据LRU算法移除的对象,以及过期的对象。
17. bytes_read:memcached服务器从网络读取的总的字节数。
18. bytes_written:memcached服务器发送到网络的总的字节数。
19. limit_maxbytes:memcached服务缓存允许使用的最大字节数。这里为67108864字节,也就是是64M.与我们启动memcached服务设置的大小一致。
20. threads:被请求的工作线程的总数量。这个解释是协议文档给的,具体什么意思,我目前还没搞明白。
总结:stats命令总体来说很有用,通过这个命令我们很清楚当前memcached服务的各方面的信息。除此之外,我还没有其他方法可以知道这些状态信息。可能还有其他途径,可能我对memcached组件还不太熟悉吧。


gerVersion

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值