如何对memcache的数据(key-value)进行遍历操作
memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视 频、文件以及数据库检索的结果等。Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
为什么要遍历目前,用到memcache的公司和网站也越来越多。Memcache的客户端操作一般都只提供了get,set等简单的操作,这些操作都是非常高效的。 虽然memcache是个key-value存储的系统,但是在某些时候,我们可能需要遍历memcache的数据。
如何遍历memcache stats命令memcache的stats命令包括:
通过命令完成遍历
通过这些stats命令我们就可以完成memcache存储的内容的遍历,OK,下面我们通过telnet直接连接到memcache通过这些命令来完成相关的操作。
telnet到192.168.15.225(局域网测试机器)的memcache服务器
执行stats items命令,可以看到出现 很多的items行。
贴上一段php实现的遍历memcache数据的代码,其他语言可以参考代码自己实现。
$str=$mem- getExtendedStats ("cachedump",$number,0); $line=$str["$host:$port"]; if( is_array($line) count($line) 0){ foreach($line as $key= $value){ echo " pre ".$key.= ; print_r($mem- get($key)); echo " /pre br/ "; } }
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 算法清理低版本的垃圾数据,但是毕竟不是实时清理,所以必然浪费内存,所以内存不足的情况下,要仔细考虑采取此方案。
redis 删除大key集合的方法 redis大key,这里指的是大的集合数据类型,如(set/hash/list/sorted set),一个key包含很多元素。由于redis是单线程,在删除大key(千万级别的set集合)的时候,或者清理过期大key数据时,主线程忙于删除这个大key,会导致redis阻塞、崩溃,应用程序异常的情况。
相关文章
- 遍历数据时arraylist效率高于linkedlist_遍历问题种类
- js 实现二叉树前序遍历
- 【说站】python字典如何遍历数据
- 【说站】js深度优先遍历的介绍
- 【说站】python如何遍历文件夹
- 【说站】python循环遍历如何理解
- 【测开技能】Java语言系列(十七)数组操作--遍历与排序
- leetcode二叉树的层次遍历_完全二叉树的中序序列
- 你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。
- 二叉树的层序遍历
- 遍历获取指定时间区间修改过的文件
- 数据结构实验之二叉树五:层序遍历 (SDUT 3344)
- 【C 语言】文件操作 ( 配置文件读写 | 写出或更新配置文件 | 逐行遍历文件文本数据 | 获取文件中的文本行 | 查询文本行数据 | 追加文件数据 | 使用占位符方式拼接字符串 )
- java遍历Map时remove删除元素详解编程语言
- MySQL树形查询:分层遍历无穷深度数据(mysql树形查询)
- 加载PHP MySQL 遍历加载 快速、简单的数据查询方法!(phpmysql遍历)
- MySQL遍历表数据:实现快速扫描(mysql遍历表数据)
- csvSQL Server中借助CSV文件快速遍历数据(sqlserver中遍历)
- MySQL遍历数据表实现数据快速查询(mysql 遍历数据表)
- 使用MSSQL快速有效地遍历表数据(mssql 遍历表数据)
- 与Oracle中遍历数据的完美探索(oracle中数据的遍历)
- Redis中集合数据结构的遍历实现(redis 集合遍历)
- 利用Redis快速遍历数据(redis 遍历数据)
- Redis精准遍历哈希表(redis 遍历哈希表)
- Redis遍历命令快速轻松掌控大量数据(redis遍历命令)
- 深入浅出Redis遍历列表实现复杂数据存储(redis遍历列表)
- 直接在JS里创建JSON数据然后遍历使用