memcached的工作原理
Memcached的高性能源于两阶段哈希(two-stage hash)结构。Memcached就像一个巨大的、存储了很多<key,value>对的哈希表。通过key,可以存储或查询任意的数据。客户端可以把数据存储在多台memcached上。当查询数据时,客户端首先参考节点列表计算出key的哈希值(阶段一哈希),进而选中一个节点;客户端将请求发送给选中的节点,然后memcached节点通过一个内部的哈希算法(阶段二哈希),查找真正的数据(item)并返回给客户端。从实现的角度看,memcached是一个非阻塞的、基于事件的服务器程序。
memcached的cache机制
Memcached主要的cache机制是LRU(最近最少用)算法+超时失效。当您存数据到memcached中,可以指定该数据在缓存中可以呆多久。如果memcached的内存不够用了,过期的slabs会优先被替换,接着就轮到最老的未被使用的slabs。
适用memcached的业务场景
-
如果网站包含了访问量很大的动态网页,因而数据库的负载将会很高。由于大部分数据库请求都是读操作,那么memcached可以显著地减小数据库负载。
-
如果数据库服务器的负载比较低但CPU使用率很高,这时可以缓存计算好的结果( computed objects )和渲染后的网页模板(enderred templates)。
-
利用memcached可以缓存session数据、临时数据以减少对他们的数据库写操作。
-
缓存一些很小但是被频繁访问的文件。
-
缓存Web ‘services’(非IBM宣扬的Web Services,译者注)或RSS feeds的结果。
不适用memcached的业务场景
- 缓存对象的大小大于1MB
Memcached本身就不是为了处理庞大的多媒体(large media)和巨大的二进制块(streaming huge blobs)而设计的。
-
key的长度大于250字符
-
虚拟主机不让运行memcached服务
如果应用本身托管在低端的虚拟私有服务器上,像vmware, xen这类虚拟化技术并不适合运行memcached。Memcached需要接管和控制大块的内存,如果memcached管理的内存被OS或 hypervisor交换出去,memcached的性能将大打折扣。
- 应用运行在不安全的环境中
Memcached为提供任何安全策略,仅仅通过telnet就可以访问到memcached。如果应用运行在共享的系统上,需要着重考虑安全问题。
- 业务本身需要的是持久化数据或者说需要的应该是database
memcached的最佳实践
-
不能够遍历memcached中所有的item,任何遍历所有item的命令执行所消耗的时间,将随着memcached中数据量的增加而增加。当其他命令因为等待(遍历所 有item的命令执行完毕)而不能得到执行,因而阻塞将发生。
-
由于客户端自己做了一次哈希,那么我们很容易增加大量memcached到集群中。memcached之间没有相互通信,因此不会增加memcached的负载;没有多播协议,不会网络通信量爆炸(implode)。
-
利用memcached,我们可以搭建出各种高效的缓存。比如,可以执行多个独立的查询,构建出一个用户对象(user object),然后将用户对象缓存到memcached中。而数据库的query cache是SQL语句级别的,不可能做到这一点。另外当写操作很频繁时,数据库的query cache会经常让所有缓存数据都失效,影响性能。
-
local cache(本地缓存)适合缓存数据量少且访问频繁的数据(如产品分类,连接信息,服务器状态变量,应用配置变量等),当删除或更新一个缓存数据时,local cache需要通知所有的服务器刷新cache(很慢,不具扩展性)或者仅仅依赖缓存超时失效机制来完成。但在memcached集群中,删除或更新一个key会让所有的观察者觉察到。
-
memcached 1.2及更高版本拥有了多线程模式。多线程模式允许memcached能够充分利用多个CPU,并在CPU之间共享所有的缓存数据。memcached使用一种简单的锁机制来保证数据更新操作的互斥。相比在同一个物理机器上运行多个memcached实例,这种方式能够更有效地处理multi gets。如果系统的负载并不重,那么不需要启用多线程工作模式。如果您在运行一个拥有大规模硬件的、庞大的网站,将体验到看到多线程的好处。
-
Memcache客户端仅根据哈希算法来决定将某个key存储在哪个节点上,而不考虑节点的内存大小。因此,可以在不同的节点上使用大小不等的内存作为缓存空间。但是一般可以这样做:拥有较多内存的节点上可以运行多个memcached实例,每个实例使用的内存跟其他节点上的实例相同。
-
memcached 1.2.5以及更高版本,提供了gets和cas命令,保证写操作同一时间只有一个线程执行,如果使用gets命令查询某个key的item,memcached会返回该item当前值的唯一标识。如果客户端程序覆写了这个item并想把它写回到memcached中,可以通过cas命令把那个唯一标识一起发送给memcached。如果该item存放在memcached中的唯一标识与您提供的一致,写操作将会成功。如果另一个进程在这期间也修改了这个item,那么该item存放在memcached中的唯一标识将会改变,写操作就会失败。
-
Memcached的目标是可伸缩性。当连接和请求增加的时候,memcached的性能将比大多数数据库查询好。可以先在高负载的环境(并发的连接和请求)中测试您的代码,然后再决定memcached是否适合您。
-
如果您要存储复杂的数据并且想被多种客户端库读取,需要满足以下:各个客户端以简单的string格式来存储;各个客户端都对数据进行压缩,要么都不压缩;各个客户端需要使用相同的哈希算法
-
适合缓存的内容:
-
缓存简单的查询结果:查询缓存存储了给定查询语句对应的整个结果集,最合适缓存那些经常被用到,但不会改变的 SQL 语句对查询到的结果集,比如载入特定的过滤内容。但如果查询语句对应的结果集改变,该结果集不会展现出来。
-
缓存简单的基于行的查询结果:基于行的缓存会检查缓存数据key的列表,那些在缓存中的行可以直接被取出,不在缓存中的行将会从数据库中取出并以唯一的键为标识缓存起来,最后加入到最终的数据集中返回。随着时间的推移,大多数数据都会被缓存,这也意味着相比与数据库,查询语句会更多地从 memcached 中得到数据行。如果数据是相当静态的,我们可以设置一个较长的缓存时间。
-
缓存的不只是 SQL 数据,可以缓存经过渲染的Html数据块,那时你就可以简单地取出被预处理后的 HTML 直接填充在页面中,以节省CPU计算时间
-
根据系统的情况考虑是否使用多层的缓存结构,如:可以通过memcached缓存和本地缓存(如ehcache、oscache等)建立起多级缓存。本地缓存更加接近处理器, 这样可以帮助减少生成页面的时间,并且在 memcached 失效的情况下可以增加可靠性。
-
当数据更新时需要更新缓存
-
预热你的缓存:可以写一些脚本来缓存通用的页面;也可以写一个命令行工具来填充缓存;你可以在高峰时刻在缓存里填充一些内容。
-
ehcache直接在jvm虚拟机中缓存,速度快,效率高;但是缓存共享麻烦,集群分布式应用不方便。ehcache的缓存共享方案是通过RMI或者Jgroup多播方式进行广播缓存通知更新,缓存共享复杂,维护不方便;简单的共享可以,但是涉及到缓存恢复,大数据缓存,则不合适。
memcached通过socket访问到缓存服务,效率比ecache低,比数据库要快很多,处理集群和分布式缓存方便,有成熟的方案