Memcache Key 设计技巧及注意事项

刚刚开始研究Memcache,觉得Memcache Key的设计其实是十分重要的,搜了搜,感觉资料不是很多,下面这些资料主要是从官网上获得的,有些地方可能不太精确,仅供参考。

初始化Memcache Client

# perl
my $memclient = Cache::Memcached->new({ servers => [ '10.0.0.10:11211', '10.0.0.11:11211' ]});
# pseudocode
memcli = new Memcache
memcli:add_server('10.0.0.10:11211')

     某些客户端的实现可能允许重复添加同一个Server,但最好每个Server是有一个实例,而且也要注意他们的顺序最好不要经常变化,防止key的重新映射;在初始化MemcacheClient的时候要注意实例化的次数,不要太过频繁的实例化,最好通过连接池来管理。

封装一个SQL作为key

     Memcache在减轻数据库负载方面发挥着重要的作用,我们最常使用的场景也是用它来减少数据库查询次数,下面这个例子就是通过Cache缓存查询数据库结果的场景,把sql+userId作为一个key,相同用户第二次查询时就可以从缓存中直接提取:

# Don't load little bobby tables
sql = "SELECT * FROM user WHERE user_id = ?"
key = 'SQL:' . user_id . ':' . md5sum(sql)
# We check if the value is 'defined', since '0' or 'FALSE' # can be
# legitimate values!
if (defined result = memcli:get(key)) {
        return result
} else {
        handler = run_sql(sql, user_id)
        # Often what you get back when executing SQL is a special handler
        # object. You can't directly cache this. Stick to strings, arrays,
        # and hashes/dictionaries/tables
        rows_array = handler:turn_into_an_array
        # Cache it for five minutes
        memcli:set(key, rows_array, 5 * 60)
        return rows_array
}

     注意:在通过set方法缓存数据时,我们可以指定数据过期时间,上面例子中设置的是5分钟,这样的话,五分钟内用户看到的都是同样的信息,即5分钟内的数据变化用户是感觉不到的,在开发时一定要注意根据实际情况对过期时间进行合理设置。

封装多个查询SQL作为Key

     有些处理过程是复杂的,可能会用到多个sql,如果我们能把这些复杂的处理最后封装成一个key,这是最理想的结果。比如下面这个例子,我们把sql1+sql2+userId作为一个key,这样,我们两次查询的结果便封装成了一个CacheItem:

sql1 = "SELECT * FROM user WHERE user_id = ?"
sql2 = "SELECT * FROM user_preferences WHERE user_id = ?"
key  = 'SQL:' . user_id . ':' . md5sum(sql1 . sql2)
if (defined result = memcli:get(key)) {
        return result
} else {
        # Remember to add error handling, kids ;)
        handler = run_sql(sql1, user_id)
        t[info] = handler:turn_into_an_array
        handler = run_sql(sql2, user_id)
        t[pref] = handler:turn_into_an_array
        # Client will magically take this hash/table/dict/etc
        # and serialize it for us.
        memcli:set(key, t, 5 * 60)
        return t
}

     

缓存Object类型的数据    

     某些语言比如Java可以把对象进行序列化,进行序列化的对象就可以像普通字符串数据一样进行缓存了,但要注意的是,序列化和反序列化会耗费cpu时间,在缓存时仅仅序列化需要缓存对象会提高系统效率。

缓存一个片段(网页)

     Memcache不仅仅可以用来减少数据库查询,任何可以提高我们应用速度的地方我们都可以用它来解决,比如下面这个例子,加载一个用户模板是非常耗时的,但是我们可以把一个封装好的模板(甚至是整个网页)缓存起来:     


key = 'FRAG-BIO:' . user_id 

if (result = memcli:get(key)) {
        return result
} else {
        user         = fetch_user_info(user_id)
        bio_template = fetch_biotheme_for(user_id)
        bio_fragment = apply_template(bio_template, user)
        memcli:set(key, bio_fragment, 5 * 15)
        return bio_fragment
}

Get-By-Group-Key

      在某些情况下,我们希望一系列的key只存储到一台服务器缓存中,比如我们在显示一个用户首页的时候,需要缓存他的姓名、年龄、简历、好友、日志等信息,而通常情况下客户端Hash算法会把它们的key映射到集群中的每一台机器的缓存中,如果这样的话,我们在查询一个人的主页时会从多台机器上取数据,会耗掉很多网络传输、Hash映射等时间,这是完全没有必要的,我们需要一种机制,在客户端内部把这些key组成一个group-key(可以是userId)。

其它需要注意的地方

  • 数据有效性:某些时候我们需要保证对Cache中的数据进行同步,不要让用户感觉到自己用到的是过期的脏数据。
  • 数据过期:我们可以设置缓存中的数据过期时间,最大过期时间是30天,如果参数值为0,则表示永不过期(LRU算法会自动删除需要删除的数据)。
  • 删除Cache中数据:最直接的让Cache数据过期的办法就是delete。
  • Key的值越短越好:key的大小被限制在250个字节(将来可能达到6K),key的长度会影响Hash算法寻找value值的效率,也会浪费更多内存空间(期间有对key的copy)。

使用伪命名空间

     

     Memcache并不支持命名空间(其设计哲学就是简单高效),但是我们可以模拟实现它。比如,我们可以把一个用户的所有key都归档在一个命名空间下,比如可以把前缀设计为:user_namespace+userId。

user_prefix = memcli:get('user_namespace:' . user_id)
bio_data    = memcli:get(user_prefix . user_id . 'bio')

缓存Set 或 List

     存储集合到缓存的意思是把一个集合的所有数据作为一个CacheItem保存到缓存中,当然,具体的实现方式有多种。不过需要注意一点的是,Memcache的每个Item有不能超过1MB的限制,那么,我们该如何存储一个超大数据量的集合呢?

方案一:分二个阶段把数据缓存到Cache

     第一个阶段存取的不是所有集合的数据,而是集合数据每一项的Id,然后第二阶段再把每个Id对应的数据对象存到缓存中。当然,当一个集合特别大的时候,所有的数据的Id有可能也会超过1MB的限制,那么我们在第一阶段存储时指定每个集合的数量即可。这么做还有个好处就是当我们在更新一个数据条目的时候仅更新指定Id的项目即可。

方案二:一个阶段分批次把数据存取到Cache

     比如有30000条数据,我们可以每批次100条分300批次缓存到Cache。

时间: 2024-12-23 03:34:07

Memcache Key 设计技巧及注意事项的相关文章

MySQL索引类型总结和使用技巧以及注意事项_Mysql

在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable表: 复制代码 代码如下: CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL  ); 我们随机向里面插入了10000条记录,其中有一条:5555, admin. 在查找username="admin"的记录 SELECT * FROM mytable WHERE username='admin';时,如果在

WPF界面设计技巧(1)—不规则窗体图文指南

原文:WPF界面设计技巧(1)-不规则窗体图文指南  初到园子,奉上第一篇入门级教程,请勿见笑. 以往WinForm编程中,实现不规则窗体是有一定难度的,更难的是不规则窗体的边缘抗锯齿及局部透明处理.而现在,WPF的出现使这个问题迎刃而解,使得我们可以轻松.灵活地美化用户界面. 下面就让我们来看看如何实现一个不规则窗体: 首先我们需要借助Microsoft Expression Design 2来进行图形设计.(这里使用Photoshop等传统软件也可以,但是只能利用PNG格式来实现透明,其缺点

WPF界面设计技巧(11)-认知流文档 & 小议WPF的野心

原文:WPF界面设计技巧(11)-认知流文档 & 小议WPF的野心     流文档是WPF中的一种独特的文档承载格式,它的书写和呈现方式都很像HTML,它也几乎具备了HTML的绝大多数优势,并提供了更强的编程支持及对WPF其他元素的兼容.   直接来看代码吧,需要讲解的地方比较多,我就直接注释在代码里了,看起来更方便些:     Code<Window x:Class="流文档.Window1"     xmlns="http://schemas.microso

WPF界面设计技巧(10)-样式的继承

原文:WPF界面设计技巧(10)-样式的继承     PS:现在我的MailMail完工了,进入内测阶段了,终于可以腾出手来写写教程了哈,关于MailMail的介绍及内测程序索取:http://www.cnblogs.com/SkyD/archive/2008/08/09/1264083.html  欢迎帮我捉虫,以及与我交流WPF技术   WPF的样式的继承属性极少被文章提及,以至于我在编写MailMail期间为此踌躇数日,最后终于在E文版的MS社区得到指点才得以解惑.   现将其分享出来,这

WPF界面设计技巧(5)—自定义列表项呈现内容

原文:WPF界面设计技巧(5)-自定义列表项呈现内容    接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能:     鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图及文件名.文件大小信息.   选中一个列表项,该列表项会扩大,并动态显示出一个小缩略图及文件的所在路径.   代码如下:   Code<Application x:Class="自定义列表项.App"    xmlns="http://schemas.micr

一分钟看懂测力传感器暗转使用技巧和注意事项

一分钟看懂测力传感器暗转使用技巧和注意事项!测力传感器在我们的生活中使用的非常广泛,尤其是在我们的工业中最常见,目前,测力传感器生产厂家也越来越多,那么,我们如何去选择测力传感器的国内生产厂家?. 我们知道,精准度对于测力传感器来说非常的重要,所以在工作使用过程中,保证传感器的精准度便成为了保养的第一要务.需要在日常养护上多下功夫,从最基础开始,努力做好每一个保养步骤.那么,要想保证传感器的顺利运行,都需要有哪些窍门技巧呢?在安装时特别要加强哪方面的注意呢? 首先来讲,在使用测力传感器时,需要对

.NET框架设计(常被忽视的C#设计技巧)

阅读目录: 1.开篇介绍 2.尽量使用Lambda匿名函数调用代替反射调用(走进声明式设计) 3.被忽视的特性(Attribute)设计方式 4.扩展方法让你的对象如虎添翼(要学会使用扩展方法的设计思想) 5.别怕Static属性(很多人都怕Static在Service模式下的设计,其实要学会使用线程本地存储(ThreadStatic)) 6.泛型的协变与逆变(设计架构接口(Interface)时要时刻注意对象的协变.逆变) 7.使用泛型的类型推断(还在为参数类型烦恼吗) 8.链式编程(设计符合

十个简单好用的设计技巧

[编者按]本文作者Mark Praschan是一位具有将近十年经验的http://www.aliyun.com/zixun/aggregation/7007.html">网页设计师,Web开发师,Web项目经理人. 文中强调复杂的高级效果能为设计增色不少,但如果用得不对,只会影响用户对重点内容的关注.高级效果可能正好是一项好的设计的冲击力所在,但即便如此,也还是需要一些更简单的效果与其配合. 简单的效果和技巧是建造当今设计的基石.比方说,如果你都不知道如何正确选择颜色和文字效果,灿烂的 星

CSS网页设计技巧:input按钮在IE浏览器的兼容问题

文章简介:CSS网页设计技巧:input按钮在IE浏览器的兼容问题. 这段时间在处理网页默认的input 按钮时,IE下常显现不一致的宽度问题,让人感到很纠结.所以今天请教了几位高手把这个问题解决了,现在贴出来和大家共享一下,当然这个方法在网上曾有人写过,大家可以一起来相互探讨一下. Html Code: <input type="submit"; class="form-submit" value="subscribe" name=&qu