如何对memcache的数据(key-value)进行遍历操作

简介:

什么是memcache

        memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视 频、文件以及数据库检索的结果等。Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。

为什么要遍历

   目前,用到memcache的公司和网站也越来越多。Memcache的客户端操作一般都只提供了get,set等简单的操作,这些操作都是非常高效的。   虽然memcache是个key-value存储的系统,但是在某些时候,我们可能需要遍历memcache的数据。     

如何遍历memcache

stats命令

 memcache的stats命令包括:

Java代码   收藏代码
  1. stats    
  2. stats reset    
  3. stats malloc    
  4. stats maps    
  5. stats sizes    
  6. stats slabs    
  7. stats items    
  8. stats cachedump slab_id limit_num    
  9. stats detail [on|off|dump]  

 通过命令完成遍历

       通过这些stats命令我们就可以完成memcache存储的内容的遍历,OK,下面我们通过telnet直接连接到memcache通过这些命令来完成相关的操作。 
      telnet到192.168.15.225(局域网测试机器)的memcache服务器

执行stats items命令,可以看到出现 很多的items行。

 

贴上一段php实现的遍历memcache数据的代码,其他语言可以参考代码自己实现。

Java代码   收藏代码
  1. <?php  
  2. $host='localhost';  
  3. $port=11211;  
  4.   
  5. $mem=new Memcache();  
  6. $mem->connect($host,$port);  
  7.   
  8. $items=$mem->getExtendedStats ('items');  
  9. $items=$items["$host:$port"]['items'];  
  10.   
  11. foreach($items as $key=>$values){  
  12.     $number=$key;  
  13.     $str=$mem->getExtendedStats ("cachedump",$number,0);  
  14.     $line=$str["$host:$port"];  
  15.     if( is_array($line) && count($line)>0){  
  16.         foreach($line as $key=>$value){  
  17.             echo "<pre>".$key.'=>';  
  18.             print_r($mem->get($key));  
  19.             echo "</pre><br/>";  
  20.         }  
  21.     }  
  22. }  
  23. ?>  

Memcached如何实现高性能批量删除,插入

Memcached 的批量删除,向来是 Memcached 使用者很头疼的事情,因为 Memcached 采取的缓存方案是哈希表结构,所以没有办法实现 delete from tablename where key like ‘%XX%’ 类似这样的批量删除功能。所以不得不自己采取一些策略实现批量删除。常见的删除方案主要有以下两种:


第一种方案:通过记录 KEY 到 DB 然后循环删除。 
其实这也是最常规的删除方法,最容易想到,可能大部分人首先都会这么考虑。具体方法如下: 
1.  
添加业务数据时,在向 Memcached 缓存 set 数据的时候,将其 key 记录到数据库(或内存中,或文件中,由于数据量大,内存中基本不可行),也就是每 set 一条数据到 Memcached 缓存中,就向记录 key 的数据表(这类专门用于辅助删除缓存的表可以按业务分类建表,为了方便,我们下文简称 keytable, 因为不可能所有的 key 都用一张表,即使按业务分类建,数据量也是很庞大的) insert 一条记录。数据表结构可以设计为这两个字段: key( 对应缓存 key),   id( 对应业务实体 id) ,这里的存储 id 主要是方便批量查询出需要从缓存删除的 KEY 时方便 , 也可以根据实际业务设计。 
2.  
删除业务数据时,首先从数据库的业务数据表删除数据,然后从 keytable  中查询出 keyList. 查询语句类似, select key from keytable where  条件   ,再然后循环 keyList 从 Memcached 缓存中 remove 掉相应的记录,最后删除 keytable表中相应的记录,删除语句类似 delete key from keytable where  条件. 
这种方法的优点:方案设计思路简单,符合常规思维,而且能达到精确删除的目的。 
这种方法的缺点:删除代价比较高,需要数据库或其他存储介质辅助,而且实际应用中,缓存量是很大的,会导致大量频繁的对 keytable 表的 insert 操作,性能问题将会很严重,需要根据具体情况运用。


第二种方案 利用 Memcached 的 LRU 算法进行懒清理 
这种方案主要是利用 Memcached 缓存根据 LRU 算法进行定期自动清理不用或少用的缓存,通过对 key 增加版本管理来实现。 
该方案的具体方法如下(拿商品数据举例说明): 
1.   
对缓存中的每个 key 进行版本管理,比如缓存商品数据的 key 为 product_10001.0, 这里的 product 表示商品这类业务数据, product_10001 表示具体的商品对象 10001 , 0 表示版本号。
2.  在 Memcached 中维护一版本记录数据,这个很简单,比如整个系统只有商品,订单,用户这三类缓存数据,则在Memcached 中只维护三个 key ,类似 product_version,book_version,user_version. 他们的取值范围为 0-99 之间循环,之所有循环是防止数据版本多了无限增大,管理麻烦,而且数字大了占用空间大(要对应到每个 key 的值)。 
3.  
删除商品数据时,首先从数据库删除对应商品数据的记录。然后更新对应商品的版本: product_version = product_version+1 (记得当 product_version=99 时, product_version=0 )。 
4.  
从 Memcached 中 get 数据时,需要 get 两次,首次按 get 对应业务数据的版本号,如 product_version ,然后根据数据本身的 key+  最新的 product_version 作为真正的 key 去取数据。这样删除了的数据自动为过期数据, Memcached 会根据 LRU 算法清理。 
5.  
向 Memcached 中 set 数据时,也是先取最新的 product_version ,然后将数据本身的 key+product_version 作为 key保存数据到缓存。 
这种方案的优点:减少了批量删除从 Memcached 真正删除数据的麻烦。利用 Memcached 自身的特点解决删除问题,符合 Memcached 的设计思想。 
这种方案的缺点: a. 每次 set 数据都要,先 get 版本,然后 set, 性能上差不多降低了 1 倍,虽然性能方面还是不错。不过这个问题好像没有办法解决,原先考虑在客户端缓存版本,因为版本毕竟不是时时都变,但是考虑到版本数据时多进程间共享数据,所以不能这样做,每次必须从 Memcached 中取版本。否则难以保证是最新的。 b. 这种方案对内存上有点浪费,虽然 Memcached 会根据 LRU 算法清理低版本的垃圾数据,但是毕竟不是实时清理,所以必然浪费内存,所以内存不足的情况下,要仔细考虑采取此方案。

相关文章
|
6月前
|
存储 JSON NoSQL
Redis第五弹-HASH结构相关指令和介绍,计数功能Hash-哈希(Redis本来就是键值对结构,哈希,就相当于键值对嵌套了一个键值对)的多种指令Hset key field value-
Redis第五弹-HASH结构相关指令和介绍,计数功能Hash-哈希(Redis本来就是键值对结构,哈希,就相当于键值对嵌套了一个键值对)的多种指令Hset key field value-
|
6月前
|
存储 NoSQL 安全
Redis第六弹-List列表-(相当于数组/顺序表)Lpush key element-一次可以插入多个元素(假如key已经存在,并且key对应的value并非是list,则会报错)
Redis第六弹-List列表-(相当于数组/顺序表)Lpush key element-一次可以插入多个元素(假如key已经存在,并且key对应的value并非是list,则会报错)
|
6月前
|
缓存 NoSQL 关系型数据库
Redis第二课,1.set key value(设置对应的key和value)2.get key(得到value值)Redis全局命令(支持很多的数据结构)3.keys(用来查询当前
Redis第二课,1.set key value(设置对应的key和value)2.get key(得到value值)Redis全局命令(支持很多的数据结构)3.keys(用来查询当前
|
6月前
|
存储 NoSQL Redis
Redis第七弹-Set与ZSET基本操作,Set(集合特点)SADD key member(注意这个key,必须是你自定义名字,不能用key)​编辑SMEMBERS key-查询所有的key
Redis第七弹-Set与ZSET基本操作,Set(集合特点)SADD key member(注意这个key,必须是你自定义名字,不能用key)​编辑SMEMBERS key-查询所有的key
|
7月前
|
存储 消息中间件 缓存
Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
|
存储 NoSQL Redis
redisTemplate.opsForValue().get(KEY)从Redis中取出的值为null 的解决方法
redisTemplate.opsForValue().get(KEY)从Redis中取出的值为null 的解决方法
589 0
|
NoSQL Redis
有关模糊获取Redis所有key 之后遍历的问题
有关模糊获取Redis所有key 之后遍历的问题
145 0
|
存储 NoSQL 安全
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(三)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(三)
155 0
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(三)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(七)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(七)
142 0
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(七)
|
NoSQL Redis 网络架构
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(四)
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(四)
112 0
REDIS03_概述、安装、key、字符串String、列表List、集合Set、Hash哈希、Zset有序集合、持久化策略(四)