• 1. Memcached 入门作者: 2009-01
  • 2. 2Memcache是什么 Memcache,ehcache的比较 Memcache原理分析 Memcache安装和基本配置 Memcache的在大型网站中的使用策略 Memcache的一些经验和技巧 Memcache一致性算法(consistent hasing) Tech Talk 目录索引
  • 3. 3Memcache是什么: Memcache是国外社区网站 LiveJournal 的开发团队开发的高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。 Memcache可以对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcache自管理这些 HashTable. Memcache的官方网站:http://www.danga.com/memcached/ 为什么会有Memcache和Memcached两种名称? 其实Memcache是这个项目的名称,而Memcached是它服务器端的主程序文件名。
  • 4. 4Memcache, EhCache的比较 项目MemcacheEhCache分布式不完全,集群默认不实现支持集群可通过客户端实现支持持久化可通过第三方应用实现,如sina研发的memcachedb,将cache的数据保存到Berkerly DB支持。持久化到本地硬盘,生成一个.data和.index文件。Cache初始化时会自动查找这两个文件,将数据放入cache效率高高于memcache容灾可通过客户端实现支持缓存数据方式缓存在memcached server向系统申请的内存中可以缓存在内存(jvm)中,也可以缓存在 硬盘。通过CacheManager管理cache.多个CacheManager可管理多个cache缓存过期移除策略LRULRU,FIFO,LFU缺点功能不完善,相对于ehcache效率低只适用于java体系,只能编写java客户端优点 简单,灵活,所有支持socket的语言都可以编写他的客户端 效率高,功能强大
  • 5. 5Memcache原理分析 Memcache工作方式?
  • 6. 6Memcache原理分析
  • 7. 7Memcache原理分析自主的内存存储处理 数据存储方式:Slab Allocation 数据过期方式:Lazy Expiration + LRU
  • 8. 8Memcache原理分析 数据存储方式:Slab Allocation Slab Alloction 构造图 Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。 Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)
  • 9. 9Memcache原理分析 数据存储方式:Slab Allocation Slab Classes 分配图 Page:分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。 Chunk:用于缓存记录的内存空间。 Slab Class:特定大小的chunk的组。 memcached根据收到的数据的大小,选择最适合数据大小的slab。 memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
  • 10. 10Memcache原理分析: 数据存储方式:Slab Allocation Slab Alloction 缺点 这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。
  • 11. 11Memcache原理分析: 数据过期方式 Lazy Expiration memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间。 LRU memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。
  • 12. 12Memcache原理分析: 基于客户端的Memcached分布式
  • 13. 13Memcache原理分析: 基于客户端的Memcached分布式//按照Key值,获取一个服务器ID int getServerId(char *key, int serverTotal) { int c, hash = 0; while (c = *key++) { hash += c; } return hash % serverTotal; } //服务器列表 node[0] => 192.168.0.1:11211 node[1] => 192.168.0.2:11211 node[2] => 192.168.0.3:11211 //获取key是tokyo的节点ID(服务器ID) int id = getServerId("test", 3); //得出的结果是1,那么对应的机器就是 node[id] == node[1]
  • 14. 14Memcache原理分析: 基于客户端的Memcached分布式 写入操作 读取操作
  • 15. 15Memcache原理分析: Memcache的理论参数计算方式 常量REALTIME_MAXDELTA 60*60*24*30 最大30天的过期时间 conn_init()中的freetotal(=200) 最大同时连接数 常量KEY_MAX_LENGTH 250 最大键长 settings.factor(=1.25) factor将影响chunk的步进大小 settings.maxconns(=1024) 最大软连接 settings.chunk_size(=48) 一个保守估计的key+value长度,用来生成id1中的chunk长度(1.2)。id1的chunk长度等于这个数值加上item结构体的长度(32),即默认的80字节。 常量POWER_SMALLEST 1 最小classid(1.2) 常量POWER_LARGEST 200 最大classid(1.2)
  • 16. 16Memcache原理分析: 常量POWER_BLOCK 1048576 默认slab大小 常量CHUNK_ALIGN_BYTES (sizeof(void *)) 保证chunk大小是这个数值的整数倍,防止越界(void *的长度在不同系统上不一样,在标准32位系统上是4) 常量ITEM_UPDATE_INTERVAL 60 队列刷新间隔 常量LARGEST_ID 255 最大item链表数(这个值不能比最大的classid小) 变量hashpower(在1.1中是常量HASHPOWER) 决定hashtable的大小 根据上面介绍的内容及参数设定,可以计算出的一些结果: 1、在memcached中可以保存的item个数是没有软件上限的,之前我的100万的说法是错误的。 2、假设NewHash算法碰撞均匀,查找item的循环次数是item总数除以hashtable大小(由hashpower决定),是线性的。 3、Memcached限制了可以接受的最大item是1MB,大于1MB的数据不予理会。 4、Memcached的空间利用率和数据特性有很大的关系,又与DONT_PREALLOC_SLABS常量有关。 在最差情况下,有198个slab会被浪费(所有item都集中在一个slab中,199个id全部分配满)。 
  • 17. 17Memcache原理分析: Memcache的定长优化 根据上面几节的描述,多少对memcached有了一个比较深入的认识。在深入认识的基础上才好对它进行优化。 Memcached本身是为变长数据设计的,根据数据特性,可以说它是“面向大众”的设计,但是很多时候,我们的数据并不是这样的“普遍”,典型的情况中,一种是非均匀分布,即数据长度集中在几个区域内(如保存用户 Session);另一种更极端的状态是等长数据(如定长键值,定长数据,多见于访问、在线统计或执行锁)。 这里主要研究一下定长数据的优化方案(1.2),集中分布的变长数据仅供参考,实现起来也很容易。 解决定长数据,首先需要解决的是slab的分配问题,第一个需要确认的是我们不需要那么多不同chunk长度的slab,为了最大限度地利用资源,最好chunk和item等长,所以首先要计算item长度。 在之前已经有了计算item长度的算法,需要注意的是,除了字符串长度外,还要加上item结构的长度32字节。 假设我们已经计算出需要保存200字节的等长数据。 接下来是要修改slab的classid和chunk长度的关系。在原始版本中,chunk长度和classid是有对应关系的,现在如果把所有的chunk都定为200个字节,那么这个关系就不存在了,我们需要重新确定这二者的关系。一种方法是,整个存储结构只使用一个固定的id,即只使用199个槽中的1个,在这种条件下,就一定
  • 18. 18Memcache原理分析: 要定义DONT_PREALLOC_SLABS来避免另外的预分配浪费。另一种方法是建立一个hash关系,来从item确定classid,不能使用长度来做键,可以使用key的NewHash结果等不定数据,或者直接根据key来做hash(定长数据的key也一定等长)。这里简单起见,选择第一种方法,这种方法的不足之处在于只使用一个id,在数据量非常大的情况下,slab链会很长(因为所有数据都挤在一条链上了),遍历起来的代价比较高。 前面介绍了三种空间冗余,设置chunk长度等于item长度,解决了第一种空间浪费问题,不预申请空间解决了第二种空间浪费问题,那么对于第一种问题(slab内剩余)如何解决呢,这就需要修改POWER_BLOCK常量,使得每一个slab大小正好等于chunk长度的整数倍,这样一个slab就可以正好划分成n个chunk。这个数值应该比较接近1MB,过大的话同样会造成冗余,过小的话会造成次数过多的alloc,根据chunk长度为200,选择1000000作为POWER_BLOCK的值,这样一个slab就是100万字节,不是1048576。三个冗余问题都解决了,空间利用率会大大提升。 修改 slabs_clsid 函数,让它直接返回一个定值(比如 1 ) unsigned int slabs_clsid(size_t size) {return 1;} 修改slabs_init函数,去掉循环创建所有classid属性的部分,直接添加slabclass[1]: CODE: slabclass[1].size = 200;                //每chunk200字节 slabclass[1].perslab = 5000;        //1000000/200
  • 19. 19Memcache安装、配置和使用: Memcache 安装 Memcache 配置 Memcache 结合java客户端的使用
  • 20. 20Memcache安装和使用: Memcache windows安装1.下载Memcache的window稳定版,解压到某个盘下面。 2.Cmd找到解压目录,输入memcached.exe –d insatll安装为windows服务.(如果是win7,要以administrator方式启动cmd). 3.再输入memcached.exe –d start启动。
  • 21. 21Memcached安装和使用: Memcached linux安装安装步骤: 先安装 libevent 再安装 Memcached 主程序 源码下载:(最新版) libevent官网:http://monkey.org/~provos/libevent/ libevent下载:http://monkey.org/~provos/libevent-1.4.9-stable.tar.gz Memcached官网:http://www.danga.com/memcached Memcached下载:http://www.danga.com/memcached/dist/memcached-1.2.6.tar.gz
  • 22. 22Memcached安装和使用: Memcached 安装 安装 libevent # tar zxvf libevent-1.4.9-stable.tar.gz # cd libevent-1.4.9-stable # ./configure --prefix=/usr # make # make install 安装 Memcached # tar zxvf memcached-1.2.6.tar.gz # cd memcached-1.2.6 # ./configure --prefix=/usr/local # make # make install
  • 23. 23Memcached安装和使用: Memcached 运行 试运行 Memcached # /usr/local/bin/memcached -u hualiangxie
  • 24. 24Memcached安装和使用: Memcached 运行查看Memcached 帮助信息 # /usr/local/bin/memcached -h
  • 25. 25Memcached安装和使用: Memcached 运行关注基本选项 -p 监听的TCP端口 (缺省: 11211) -d 以守护进程方式运行Memcached -u 运行Memcached的账户,非root用户 -m 最大的内存使用, 单位是MB,缺省是 64 MB -c 软连接数量, 缺省是 1024 -v 输出警告和错误信息 -vv 打印客户端的请求和返回信息 -h 打印帮助信息 -i 打印memcached和libevent的版权信息 运行 Memcached 目标:使用11211端口、hualiangxie用户、最大占用512M内存、1024个软连接,输出客户端请求,以守护进程方式运行 # /usr/local/bin/memcached -p 11211 -d -u hualiangxie -m 512 -c 1024 -vvv
  • 26. 26Memcached安装和使用: Memcached 运行检查是否正常启动 # pa auxxww | grep memcached 1001 4402 0.0 0.0 2296 900 pts/0 S+ 19:24 0:00 /usr/local/bin/memcached -u hualiangxie root 4547 0.0 0.0 1892 668 pts/3 S+ 19:42 0:00 grep memcached # telnet localhost 11211 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. stats STAT pid 4402 STAT uptime 1032 STAT time 1231155683 STAT version 1.2.6 STAT pointer_size 32 ... END
  • 27. 27pidmemcache服务器的进程IDuptime服务器已经运行的秒数time服务器当前的unix时间戳versionmemcache版本pointer_size当前操作系统的指针大小(32位系统一般是32bit)rusage_user进程的累计用户时间rusage_system进程的累计系统时间curr_items服务器当前存储的items数量total_items从服务器启动以后存储的items总数量bytes当前服务器存储items占用的字节数curr_connections当前打开着的连接数total_connections从服务器启动以后曾经打开过的连接数connection_structures服务器分配的连接构造数cmd_getget命令(获取)总请求次数cmd_setset命令(保存)总请求次数get_hits总命中次数get_misses总未命中次数evictions为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items)bytes_read总读取字节数(请求字节数)bytes_written总发送字节数(结果字节数)limit_maxbytes分配给memcache的内存大小(字节)threads当前线程数
  • 28. 28 stats命令  memcache的stats命令包括: 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  示某个slab中的前limit_num个key列表 9.        stats detail [on|off|dump]    设置或显示详细操作信息
  • 29. 29Memcached安装和使用: Memcached 命令数据存取 set key1 0 180 3 abc STORED add key1 0 180 3 xyz NOT_STORED get key1 VALUE key1 0 3 abc END replace key1 0 180 3 xyz STORED get key1 VALUE key1 0 3 xyz END delete key1 DELETED数字加减 set key2 0 180 4 1234 STORED incr key2 3 1237 get key2 VALUE key2 0 4 1237 END decr key2 1 1236 get key2 VALUE key2 0 4 1236 END
  • 30. 30 memcached 的客户端使用TCP链接 与 服务器通讯。 (UDP接口也同样有效)一个运行中的memcached服务器监视一些(可设置)端口。客户端连接这些端口,发送命令到服务器,读取回应,最后关闭连接。 结束会话不需要发送任何命令。当不再需memcached服务时,要客户端可以在任何时候关闭连接。需要注意的是,鼓励客户端缓存这些连接,而不是每次需要存取数据时都重新打开连接。这是因为memcached 被特意设计成及时开启很多连接也能够高效的工作(数百个,上千个如果需要的话)。缓存这些连接,可以消除建立连接所带来的开销(/*/相对而言,在服务器端建立一个新连接的准备工作所带来的开销,可以忽略不计。)。 在memcache协议中发送的数据分两种:文本行 和 自由数据。 文本行被用于来自客户端的命令和服务器的回应。自由数据用于客户端从服务器端存取数据时。同样服务器会以字节流的方式传回自由数据。/*/服务器不用关心自由数据的字节顺序。自由数据的特征没有任何限制;但是通过前文提到的文本行,这项数据的接受者(服务器或客户端),便能够精确地获知所发送的数据库的长度。 文本行固定以“\r\n”(回车符紧跟一个换行符)结束。 自由数据也是同样会以“\r\n”结束,但是 \r(回车符)、\n(换行符),以及任何其他8位字符,均可出现在数据中。因此,当客户端从服务器取回数据时,必须使用数据区块的长度来确定数据区块的结束位置,而不要依据数据区块末尾的“\r\n”,即使它们固定存在于此Memcached安装和使用: Memcached 基本协议
  • 31. 31Memcached安装和使用: Memcached 和 java 结合使用下载memcached java client:http://www.whalin.com/memcached/#download 解压后将java_memcached-release_2.0.1.jar jar包添加到工程的classpath中/*Memcache服务器默认端口是11211*/ String[] servers = { "127.0.0.1:11211" }; SockIOPool pool = SockIOPool.getInstance(); pool.setServers(servers); pool.setFailover(true); pool.setInitConn(10); pool.setMinConn(5); pool.setMaxConn(250); pool.setMaintSleep(30); pool.setNagle(false); pool.setSocketTO(3000); pool.setAliveCheck(true); pool.initialize();MemCachedClient memCachedClient = new MemCachedClient(); for (int i = 0; i < 10; i++) { /*将对象加入到memcached缓存*/ boolean success = memCachedClient.set("" + i, "Hello!"); /*从memcached缓存中按key值取对象*/ String result = (String) memCachedClient.get("" + i); System.out.println(String.format("set( %d ): %s", i, success)); System.out.println(String.format("get( %d ): %s", i, result)); }
  • 32. 32Memcache三种java客户端的比较 Memcache client for java:较早推出的memcache java客户端API,应用广泛,运行比较稳定。 spymemcached:A simple, asynchronous, single-threaded memcached client written in java. 支持异步,单线程的memcached客户端,用到了java1.5版本的concurrent和nio,存取速度会高于前者,但是稳定性不好,测试中常 报timeOut等相关异常 Xmemcached是基于java nio实现的高性能可扩展的memcached客户端。实际上是基于我实现的一个nio框架 http://code.google.com/p/yanf4j/的基础上实现的(目前1.1.3是基于yanf4j 0.7.0,而1.2.0-RC1版本基于1.0-SNAPSHOT)。 另外我们也可以自己写soket,实现memcache客户端。 Memcached安装和使用:
  • 33. 33Memcache在大型网站中的使用策略: Memcache在大型网站中的部署策略 基于memcached的slab和dump的内存管理方式,它产生的内存碎片比较少,不需要OS去做繁 杂的内存回收,所以它对CPU的占用率那是相 当的低。所以建议将它跟占用CPU较高的WEB服 务器一起使用来节省成本。当然如果你有大量的廉价PC,那用来专门做memcached服务器也 不错。由 于32位操作系统中,每个进程最多只能使用2GB内存,所以如果你有大内存的话, 可以以daemon的方式启动两个以上的memcached服务,或者干 脆用64位的CPU和OS。
  • 34. 34Memcache缓存使用策略: memcached主要的作用是为减轻大访问量对数据库的冲击,所以一般的逻辑是首先从memcached中读取数据,如果没有就从数据库中读取数据 写入到memcache中,等下一次读取的时候就可以从memcached中读取了。但在项目中的具体应用策略(也就是哪些数据应该缓存?怎么样缓存?过 期策略?)就是个问题了。它的一个总原则是将经常需要从数据库读取的数据缓存在memcached中。这些数据也分为几类: 一、经常被读取并且实时性要求不强可以等到自动过期的数据。例如网站首页最新文章列表、某某排行等数据。也就是虽然新数据产生了,但对用户体验不会产生任何影响的场景。 这类数据就使用典型的缓存策略,设置一过合理的过期时间,当数据过期以后再从数据库中读取。当然你得制定一个缓存清除策略,便于编辑或者其它人员能马上看到效果。 二、经常被读取并且实时性要求强的数据。比如用户的好友列表,用户文章列表,用户阅读记录等。 这类数据首先被载入到memcached中,当发生更改(添加、修改、删除)时就清除缓存。在缓存的时候,我将查询的SQL语句md5()得到它的 hash值作为key,结果数组作为值写入memcached,并且将该SQL涉及的table_name以及hash值配对存入memcached中。 当更改了这个表时,我就将与此表相配对的key的缓存全部删除。
  • 35. 35Memcache缓存使用策略: 三、统计类缓存,比如文章浏览数、网站PV等 此类缓存是将在数据库的中来累加的数据放在memcached来累加。获取也通过memcached来获取。但这样就产生了一个问题,如果 memcached服务器down掉的话这些数据就有可能丢失,所以一般使用memcached的永固性存储,这方面我们新浪使用memcachedb。 四、活跃用户的基本信息或者某篇热门文章。 此类数据的一个特点就是数据都是一行,也就是一个一维数组,当数据被update时(比如修改昵称、文章的评论数),在更改数据库数据的同时,使用Memcache::replace替换掉缓存里的数据。这样就有效了避免了再次查询数据库。 五、session数据 使用memcached来存储session的效率是最高的。memcached本身也是非常稳定的,不太用担心它会突然down掉引起session数据的丢失,即使丢失就重新登录了,也没啥。见[多服务器session共享之memcache共享]
  • 36. 36一些经验和技巧: Memcached一些特性和限制 在 Memcached 中可以保存的item数据量是没有限制的,只有内存足够 Memcached单进程最大使用内存为2G,要使用更多内存,可以分多个端口开启多个Memcached进程 最大30天的数据过期时间, 设置为永久的也会在这个时间过期,常量REALTIME_MAXDELTA 60*60*24*30 控制 最大键长为250字节,大于该长度无法存储,常量KEY_MAX_LENGTH 250 控制,客户端可以加上自己 的前缀,所以最大长度是可以超过50的。 单个item最大数据是1MB,超过1MB数据不予存储,常量POWER_BLOCK 1048576 进行控制, 它是默认的slab大小 最大同时连接数是200,通过 conn_init()中的freetotal 进行控制,最大软连接数是1024,通过 settings.maxconns=1024 进行控制,这跟操作系统有关,linux好像最大就是200。 跟空间占用相关的参数:settings.factor=1.25, settings.chunk_size=48, 影响slab的数据占用和步进方式
  • 37. 37一些经验和技巧: 查看Memcached内部工作状态访问Memcached:telnet 主机名 端口号 查看总状态:stats 查看某项状态:stats curr_connections 禁止LRU有些情况下LRU机制反倒会造成麻烦。memcached启动时通过“-M”参数可以禁止LRU,如下所示: $ memcached -M -m 1024 启动时必须注意的是,小写的“-m”选项是用来指定最大内存大小的。不指定具体数值则使用默认值64MB。 指定“-M”参数启动后,内存用尽时memcached会返回错误。话说回来,memcached毕竟不是存储器,而是缓存,所以推荐使用LRU。
  • 38. 38一些经验和技巧: Memcached使用线程模式工作在安装的时候必须打开:./configure --enable-threads 安装完之后,启动的时候看看帮助信息有没有这条: -t number of threads to use, default 4 如果存在该选项,说明已经支持了线程,就可以在启动的时候使用 -t 选项来启动多线程 然后启动的时候必须加上你需要支持的线程数量: /usr/local/memcache/bin/memcached -t 1024
  • 39. 39一些经验和技巧: 调优Slab和内存分配1memcached在启动时指定 Growth Factor因子(通过-f选项),就可以在某种程度上控制slab之间的差异。默认值为1.25。但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of 2”策略。 让我们用以前的设置,以verbose模式启动memcached试试看: $ memcached -f 2 -vv slab class 1: chunk size 128 perslab 8192 slab class 2: chunk size 256 perslab 4096 slab class 3: chunk size 512 perslab 2048 slab class 4: chunk size 1024 perslab 1024 slab class 5: chunk size 2048 perslab 512 slab class 6: chunk size 4096 perslab 256 slab class 7: chunk size 8192 perslab 128 slab class 8: chunk size 16384 perslab 64 slab class 9: chunk size 32768 perslab 32 slab class 10: chunk size 65536 perslab 16 slab class 11: chunk size 131072 perslab 8 slab class 12: chunk size 262144 perslab 4 slab class 13: chunk size 524288 perslab 2
  • 40. 40一些经验和技巧: 调优Slab和内存分配2可见,从128字节的组开始,组的大小依次增大为原来的2倍。这样设置的问题是,slab之间的差别比较大,有些情况下就相当浪费内存。因此,为尽量减少内存浪费,两年前追加了growth factor这个选项。 来看看现在的默认设置(f=1.25)时的输出(篇幅所限,这里只写到第10组): slab class 1: chunk size 88 perslab 11915 slab class 2: chunk size 112 perslab 9362 slab class 3: chunk size 144 perslab 7281 slab class 4: chunk size 184 perslab 5698 slab class 5: chunk size 232 perslab 4519 slab class 6: chunk size 296 perslab 3542 slab class 7: chunk size 376 perslab 2788 slab class 8: chunk size 472 perslab 2221 slab class 9: chunk size 592 perslab 1771 slab class 10: chunk size 744 perslab 1409 可见,组间差距比因子为2时小得多,更适合缓存几百字节的记录。从上面的输出结果来看,可能会觉得有些计算误差,这些误差是为了保持字节数的对齐而故意设置的。 将memcached引入产品,或是直接使用默认值进行部署时,最好是重新计算一下数据的预期平均长度,调整growth factor,以获得最恰当的设置。内存是珍贵的资源,浪费就太可惜了。
  • 41. 41一些经验和技巧: memcached得LRU不是全局的,而是针对slab的,可以说是区域性的。 要提高memcached的命中率,预估我们的value大小并且适当的调整内存页大小和增长因子是必须的。 缓存的粒度越小,命中率就越高,对象缓存是目前缓存粒度最小的,因此被命中的几率更高。 缓存太小,造成频繁的LRU,也会降低命中率,缓存的有效期太短也会造成缓存命中率下降。 真正对数据库造成庞大压力的正是那些没有索引的大表查询,和造成了全表扫描的关联查询,这些一旦涉及到全表扫描的查询,才是性能的真正杀手。通过搜索引擎来解决,缓存解决不了。