东莞网站设计出名 乐云践新,房山区网站建设,四川成都旅游必去景点,阿里云上怎么做网页网站1 概览 Memcached是一个免费开源#xff0c;高性能的#xff0c;分布式内存对象缓存系统#xff0c;为了加快动态web应用程序#xff0c;减轻数据库负载。 Memcached是一个内存中的基于键/值存储任意数据小片段#xff08;字符#xff0c;对象#xff09;#xff0c;存…1 概览 Memcached是一个免费开源高性能的分布式内存对象缓存系统为了加快动态web应用程序减轻数据库负载。 Memcached是一个内存中的基于键/值存储任意数据小片段字符对象存储的数据可以来源于数据库调用API调用或者页面呈现。 Memcached简单而强大其简单的设计促进快速部署易于开发解决了面临大量数据缓存的许多问题。针对主流语言都提供了API。 Memcached核心是一个简单的键/值存储。 Memcached本身服务器间不相互通讯不进行数据同步存在单点故障问题如果需要保证数据的高可用性则需要通过其他手段来实现。 2 服务器端 2.1 安装 2.1.1 包安装 Debian / Ubuntu # apt-get install memcached RedHat / Fedora # yum install memcached 2.1.2 源代码安装 # tar –zxvf memcached-1.x.x.tar.gz
# cd memcached-1.x.x
# ./configure
# make make test
# sudo make install 备注 1) 如果安装过程中出现依赖包比如libevent找不到的情况请安装相应的依赖包。 2) 如果出现找不到so的情况通过ln –s /xxx/xxx.so /usr/lib/xxx.so做一个软链接解决。 2.2 配置 2.2.1 服务器端 使用以下命令进行启动 # memcached –m 64 –l 10.11.11.33 –p 11211 –u xiajinxin 备注 1) 可以通过命令memcache –h来查看所有命令参数 2) 可以通过追加参数-vv来进行调试输出 3) 可以在同一台机器上启动多个memcached实例端口不同 具体可以参考http://code.google.com/p/memcached/wiki/NewConfiguringServer 2.2.2 集群配置 由于Memcached服务器与服务器之间没有任何通讯并且不进行任何数据复制备份所以当任何服务器节点出现故障时会出现单点故障如果需要实现HA则需要通过另外的方式来解决。 通过Magent缓存代理防止单点现象缓存代理也可以做备份通过客户端连接到缓存代理服务器缓存代理服务器连接缓存连接服务器缓存代理服务器可以连接多台Memcached机器可以将每台Memcached机器进行数据同步。如果其中一台缓存服务器down机系统依然可以继续工作如果其中一台Memcached机器down掉数据不会丢失并且可以保证数据的完整性系统架构如图 具体可以参考http://code.google.com/p/memagent/ 3 客户端 具体可以参考http://code.google.com/p/memcached/wiki/NewConfiguringClient 3.1 Java memcached client 网址https://github.com/gwhalin/Memcached-Java-Client/downloads 以下为示例代码需要slf4jcommon-pool以及memcache的依赖包 import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;public class TestMemcached { public static void main(String[] args) {// memcached should be running on port 11211 but NOT on 11212String[] servers { 10.11.11.28:11211, 10.11.11.33:11211 };Integer[] weights {5, 5};SockIOPool pool SockIOPool.getInstance();pool.setServers( servers );pool.setWeights( weights );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 mcc new MemCachedClient();for ( int i 0; i 10; i ) {boolean success mcc.set( i, Hello! );String result (String)mcc.get( i );System.out.println( String.format( set( %d ): %s, i, success ) );System.out.println( String.format( get( %d ): %s, i, result ) );}System.out.println( \n\t -- sleeping --\n );try { Thread.sleep( 1000 ); } catch ( Exception ex ) { }for ( int i 0; i 100000; i ) {boolean success mcc.set( i, Hello! );String result (String)mcc.get( i );System.out.println( String.format( set( %d ): %s, i, success ) );System.out.println( String.format( get( %d ): %s, i, result ) );}}
} 可以设置不同权重来观看不同server的输出。 3.2 spymemcached http://www.couchbase.org/code/couchbase/java 4 FAQ 4.1 memcached是怎么工作的 Memcached的神奇来自两阶段哈希two-stage hash。Memcached就像一个巨大的、存储了很多对的哈希表。通过key可以存储或查询任意的数据。 客户端可以把数据存储在多台memcached上。当查询数据时客户端首先参考节点列表计算出key的哈希值阶段一哈希进而选中一个节点 客户端将请求发送给选中的节点然后memcached节点通过一个内部的哈希算法阶段二哈希查找真正的数据item。 举个列子假设有3个客户端1, 2, 33台memcached A, B, C Client 1想把数据”barbaz”以key “foo”存储。Client 1首先参考节点列表A, B, C计算key “foo”的哈希值假设memcached B被选中。接着Client 1直接connect到memcached B通过key “foo”把数据”barbaz”存储进去。Client 2使用与Client 1相同的客户端库意味着阶段一的哈希算法相同也拥有同样的memcached列表A, B, C。 于是经过相同的哈希计算阶段一Client 2计算出key “foo”在memcached B上然后它直接请求memcached B得到数据”barbaz”。 各种客户端在memcached中数据的存储形式是不同的perl Storable, php serialize, java hibernate, JSON等。一些客户端实现的哈希算法也不一样。但是memcached服务器端的行为总是一致的。 最后从实现的角度看memcached是一个非阻塞的、基于事件的服务器程序。这种架构可以很好地解决C10K problem 并具有极佳的可扩展性。 可以参考A Story of Caching 这篇文章简单解释了客户端与memcached是如何交互的。 4.2 memcached最大的优势是什么 请仔细阅读上面的问题即memcached是如何工作的。Memcached最大的好处就是它带来了极佳的水平可扩展性特别是在一个巨大的系 统中。由于客户端自己做了一次哈希那么我们很容易增加大量memcached到集群中。memcached之间没有相互通信因此不会增加 memcached的负载没有多播协议不会网络通信量爆炸implode。memcached的集群很好用。内存不够了增加几台 memcached吧CPU不够用了再增加几台吧有多余的内存在增加几台吧不要浪费了。 基于memcached的基本原则可以相当轻松地构建出不同类型的缓存架构。除了这篇FAQ在其他地方很容易找到详细资料的。 看看下面的几个问题吧它们在memcached、服务器的local cache和MySQL的query cache之间做了比较。这几个问题会让您有更全面的认识。 4.3 memcached和MySQL的query cache相比有什么优缺点 把 memcached引入应用中还是需要不少工作量的。MySQL有个使用方便的query cache可以自动地缓存SQL查询的结果被缓存的SQL查询可以被反复地快速执行。Memcached与之相比怎么样呢MySQL的query cache是集中式的连接到该query cache的MySQL服务器都会受益。 * 当您修改表时MySQL的query cache会立刻被刷新flush。存储一个memcached item只需要很少的时间但是当写操作很频繁时MySQL的query cache会经常让所有缓存数据都失效。 * 在多核CPU上MySQL的query cache会遇到扩展问题scalability issues。在多核CPU上query cache会增加一个全局锁global lock, 由于需要刷新更多的缓存数据速度会变得更慢。 * 在MySQL的query cache中我们是不能存储任意的数据的只能是SQL查询结果。而利用memcached我们可以搭建出各种高效的缓存。比如可以执行多个独立 的查询构建出一个用户对象user object然后将用户对象缓存到memcached中。而query cache是SQL语句级别的不可能做到这一点。在小的网站中query cache会有所帮助但随着网站规模的增加query cache的弊将大于利。 * query cache能够利用的内存容量受到MySQL服务器空闲内存空间的限制。给数据库服务器增加更多的内存来缓存数据固然是很好的。但是有了 memcached只要您有空闲的内存都可以用来增加memcached集群的规模然后您就可以缓存更多的数据。 4.4 memcached和服务器的local cache比如PHP的APC、mmap文件等相比有什么优缺点 首先local cache有许多与上面(query cache)相同的问题。local cache能够利用的内存容量受到单台服务器空闲内存空间的限制。不过local cache有一点比memcached和query cache都要好那就是它不但可以存储任意的数据而且没有网络存取的延迟。 * local cache的数据查询更快。考虑把highly common的数据放在local cache中吧。如果每个页面都需要加载一些数量较少的数据考虑把它们放在local cached吧。 * local cache缺少集体失效group invalidation的特性。在memcached集群中删除或更新一个key会让所有的观察者觉察到。但是在local cache中, 我们只能通知所有的服务器刷新cache很慢不具扩展性或者仅仅依赖缓存超时失效机制。 * local cache面临着严重的内存限制这一点上面已经提到。 4.5 memcached的cache机制是怎样的 Memcached主要的cache机制是LRU最近最少用算法超时失效。当您存数据到memcached中可以指定该数据在缓存中可以呆 多久Which is forever, or some time in the future。如果memcached的内存不够用了过期的slabs会优先被替换接着就轮到最老的未被使用的slabs。 4.6 memcached如何实现冗余机制 不实现我们对这个问题感到很惊讶。Memcached应该是应用的缓存层。它的设计本身就不带有任何冗余机制。如果一个memcached节点失 去了所有数据您应该可以从数据源比如数据库再次获取到数据。您应该特别注意您的应用应该可以容忍节点的失效。不要写一些糟糕的查询代码寄希望于 memcached来保证一切如果您担心节点失效会大大加重数据库的负担那么您可以采取一些办法。比如您可以增加更多的节点来减少丢失一个节点的影 响热备节点在其他节点down了的时候接管IP等等。 4.7 memcached如何处理容错的 不处理:) 在memcached节点失效的情况下集群没有必要做任何容错处理。如果发生了节点失效应对的措施完全取决于用户。节点失效时下面列出几种方案供您选择 * 忽略它 在失效节点被恢复或替换之前还有很多其他节点可以应对节点失效带来的影响。 * 把失效的节点从节点列表中移除。做这个操作千万要小心在默认情况下余数式哈希算法客户端添加或移除节点会导致所有的缓存数据不可用因为哈希参照的节点列表变化了大部分key会因为哈希值的改变而被映射到与原来不同的节点上。 * 启动热备节点接管失效节点所占用的IP。这样可以防止哈希紊乱hashing chaos。 * 如果希望添加和移除节点而不影响原先的哈希结果可以使用一致性哈希算法consistent hashing。您可以百度一下一致性哈希算法。支持一致性哈希的客户端已经很成熟而且被广泛使用。去尝试一下吧 * 两次哈希reshing。当客户端存取数据时如果发现一个节点down了就再做一次哈希哈希算法与前一次不同重新选择另一个节点需要注意 的时客户端并没有把down的节点从节点列表中移除下次还是有可能先哈希到它。如果某个节点时好时坏两次哈希的方法就有风险了好的节点和坏的节 点上都可能存在脏数据stale data。 4.8 如何将memcached中item批量导入导出 您不应该这样做Memcached是一个非阻塞的服务器。任何可能导致memcached暂停或瞬时拒绝服务的操作都应该值得深思熟虑。向 memcached中批量导入数据往往不是您真正想要的想象看如果缓存数据在导出导入之间发生了变化您就需要处理脏数据了如果缓存数据在导出导入 之间过期了您又怎么处理这些数据呢 因此批量导出导入数据并不像您想象中的那么有用。不过在一个场景倒是很有用。如果您有大量的从不变化 的数据并且希望缓存很快热warm起来批量导入缓存数据是很有帮助的。虽然这个场景并不典型但却经常发生因此我们会考虑在将来实现批量导出导入的功能。 Steven Grimm一如既往地,在邮件列表中给出了另一个很好的例子http://lists.danga.com/pipermail/memcached/2007-July/004802.html 。 但是我确实需要把memcached中的item批量导出导入怎么办 好吧好吧。如果您需要批量导出导入最可能的原因一般是重新生成缓存数据需要消耗很长的时间或者数据库坏了让您饱受痛苦。 如果一个memcached节点down了让您很痛苦那么您还会陷入其他很多麻烦。您的系统太脆弱了。您需要做一些优化工作。比如处理”惊群”问 题比如 memcached节点都失效了反复的查询让您的数据库不堪重负…这个问题在FAQ的其他提到过或者优化不好的查询。记住Memcached 并不是您逃避优化查询的借口。 如果您的麻烦仅仅是重新生成缓存数据需要消耗很长时间15秒到超过5分钟您可以考虑重新使用数据库。这里给出一些提示 * 使用MogileFS或者CouchDB等类似的软件在存储item。把item计算出来并dump到磁盘上。 MogileFS可以很方便地覆写item并提供快速地访问。.您甚至可以把MogileFS中的item缓存在memcached中这样可以加快读 取速度。 MogileFSMemcached的组合可以加快缓存不命中时的响应速度提高网站的可用性。 * 重新使用MySQL。 MySQL的 InnoDB主键查询的速度非常快。如果大部分缓存数据都可以放到VARCHAR字段中那么主键查询的性能将更好。从memcached中按key查询 几乎等价于MySQL的主键查询将key 哈希到64-bit的整数然后将数据存储到MySQL中。您可以把原始不做哈希的key存储都普通的字段中然后建立二级索引来加快查询…key被 动地失效批量删除失效的key等等。 上面的方法都可以引入memcached在重启memcached的时候仍然提供很好的性能。由于您不需要当心”hot”的item被 memcached LRU算法突然淘汰用户再也不用花几分钟来等待重新生成缓存数据当缓存数据突然从内存中消失时因此上面的方法可以全面提高性能。 关于这些方法的细节详见博客http://dormando.livejournal.com/495593.html 。 4.9 memcached是如何做身份验证的 没有身份认证机制memcached是运行在应用下层的软件身份验证应该是应用上层的职责。memcached的客户端和服务器端之所以是轻量级的部分原因就是完全没有实现身份验证机制。这样memcached可以很快地创建新连接服务器端也无需任何配置。 如果您希望限制访问您可以使用防火墙或者让memcached监听unix domain socket。 4.10 如何使用memcached的多线程是什么如何使用它们 线程就是定律threads rule在Steven Grimm和Facebook的努力下memcached 1.2及更高版本拥有了多线程模式。多线程模式允许memcached能够充分利用多个CPU并在CPU之间共享所有的缓存数据。memcached使 用一种简单的锁机制来保证数据更新操作的互斥。相比在同一个物理机器上运行多个memcached实例这种方式能够更有效地处理multi gets。 如果您的系统负载并不重也许您不需要启用多线程工作模式。如果您在运行一个拥有大规模硬件的、庞大的网站您将会看到多线程的好处。 更多信息请参见http://code.sixapart.com/svn/memcached/trunk/server/doc/threads.txt 。 简单地总结一下命令解析memcached在这里花了大部分时间可以运行在多线程模式下。memcached内部对数据的操作是基于很多全局 锁的因此这部分工作不是多线程的。未来对多线程模式的改进将移除大量的全局锁提高memcached在负载极高的场景下的性能。 4.11 memcached能接受的key的最大长度是多少 key 的最大长度是250个字符。需要注意的是250是memcached服务器端内部的限制如果您使用的客户端支持”key的前缀”或类似特性那么 key前缀原始key的最大长度是可以超过250个字符的。我们推荐使用使用较短的key因为可以节省内存和带宽。 4.12 memcached对item的过期时间有什么限制 过期时间最大可以达到30天。memcached把传入的过期时间时间段解释成时间点后一旦到了这个时间点memcached就把item置为失效状态。这是一个简单但obscure的机制。 4.13 memcached最大能存储多大的单个item 1MB。如果你的数据大于1MB可以考虑在客户端压缩或拆分到多个key中。 4.14 为什么单个item的大小被限制在1Mbyte之内 啊…这是一个大家经常问的问题 简单的回答因为内存分配器的算法就是这样的。 详 细的回答Memcached的内存存储引擎引擎将来可插拔…,使用slabs来管理内存。内存被分成大小不等的slabs chunks先分成大小相等的slabs然后每个slab被分成大小相等chunks不同slab的chunk大小是不相等的。chunk的大小 依次从一个最小数开始按某个因子增长直到达到最大的可能值。 如果最小值为400B最大值是1MB因子是1.20各个slab的chunk的大小依次是slab1 – 400B slab2 – 480B slab3 – 576B … slab中chunk越大它和前面的slab之间的间隙就越大。因此最大值越大内存利用率越低。Memcached必须为每个slab预先分配内存因此如果设置了较小的因子和较大的最大值会需要更多的内存。 还有其他原因使得您不要这样向memcached中存取很大的数据…不要尝试把巨大的网页放到mencached中。把这样大的数据结构load和unpack到内存中需要花费很长的时间从而导致您的网站性能反而不好。 如果您确实需要存储大于1MB的数据你可以修改slabs.c:POWER_BLOCK的值然后重新编译memcached或者使用低效的malloc/free。其他的建议包括数据库、MogileFS等。 我可以在不同的memcached节点上使用大小不等的缓存空间吗这么做之后memcached能够更有效地使用内存吗 Memcache 客户端仅根据哈希算法来决定将某个key存储在哪个节点上而不考虑节点的内存大小。因此您可以在不同的节点上使用大小不等的缓存。但是一般都是这样做 的拥有较多内存的节点上可以运行多个memcached实例每个实例使用的内存跟其他节点上的实例相同。 4.15 什么是二进制协议我该关注吗 关于二进制最好的信息当然是二进制协议规范http://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol 。 二进制协议尝试为端提供一个更有效的、可靠的协议减少客户端/服务器端因处理协议而产生的CPU时间。 根据Facebook的测试解析ASCII协议是memcached中消耗CPU时间最多的环节。所以我们为什么不改进ASCII协议呢 在这个邮件列表的thread中可以找到一些旧的信息http://lists.danga.com/pipermail/memcached/2007-July/004636.html 。 memcached的内存分配器是如何工作的为什么不适用malloc/free为何要使用slabs 实际上这是一个编译时选项。默认会使用内部的slab分配器。您确实确实应该使用内建的slab分配器。最早的时候memcached只使用 malloc/free来管理内存。然而这种方式不能与OS的内存管理以前很好地工作。反复地malloc/free造成了内存碎片OS最终花费大量 的时间去查找连续的内存块来满足malloc的请求而不是运行memcached进程。如果您不同意当然可以使用malloc只是不要在邮件列表中 抱怨啊:) slab分配器就是为了解决这个问题而生的。内存被分配并划分成chunks一直被重复使用。因为内存被划分成大小不等的 slabs如果item的大小与被选择存放它的slab不是很合适的话就会浪费一些内存。Steven Grimm正在这方面已经做出了有效的改进。 邮件列表中有一些关于slab的改进power of n 还是 power of 2和权衡方案http://lists.danga.com/pipermail/memcached/2006-May/002163.html http://lists.danga.com/pipermail/memcached/2007-March/003753.html 。 如果您想使用malloc/free看看它们工作地怎么样您可以在构建过程中定义USE_SYSTEM_MALLOC。这个特性没有经过很好的测试所以太不可能得到开发者的支持。 更多信息http://code.sixapart.com/svn/memcached/trunk/server/doc/memory_management.txt 。 4.16 memcached是原子的吗 当然好吧让我们来明确一下 所有的被发送到memcached的单个命令是完全原子的。如果您针对同一份数据同时发送了一个set命令和一个get命令它们不会影响对方。它们将被串行化、先后执行。即使在多线程模式所有的命令都是原子的除非程序有bug:) 命令序列不是原子的。如果您通过get命令获取了一个item修改了它然后想把它set回memcached我们不保证这个item没有被其他进程process未必是操作系统中的进程操作过。在并发的情况下您也可能覆写了一个被其他进程set的item。 memcached1.2.5以及更高版本提供了gets和cas命令它们可以解决上面的问题。如果您使用gets命令查询某个key的itemmemcached会 给您返回该item当前值的唯一标识。如果您覆写了这个item并想把它写回到memcached中您可以通过cas命令把那个唯一标识一起发送给 memcached。如果该item存放在memcached中的唯一标识与您提供的一致您的写操作将会成功。如果另一个进程在这期间也修改了这个 item那么该item存放在memcached中的唯一标识将会改变您的写操作就会失败。 通常基于memcached中item的值来修改item是一件棘手的事情。除非您很清楚自己在做什么否则请不要做这样的事情。转载于:https://www.cnblogs.com/javapro/archive/2012/05/24/2516016.html