memcache集群方案,memcache

  memcache集群方案,memcache

  memcached是如何工作的?

  memcached最大的优势是什么?

  memcached和MySQL的查询缓存相比有什么优缺点?

  memcached相对于服务器的本地缓存(比如PHP的APC,mmap文件等)有什么优缺点?)?

  memcached的缓存机制是什么?

  memcached是如何实现冗余机制的?

  memcached是如何处理容错的?

  如何在memcached中批量导入和导出项目?

  但是我真的需要转储memcached中的所有条目,并且我真的需要将数据加载到memcached中。我该怎么办?

  memcached是怎么做认证的?

  如何使用memcached什么是多线程?如何使用它们?

  memcached可以接受的最大密钥长度是多少?(250字节)

  memcached对item的失效时间有什么限制?为什么有30天的限制?)

  memcached可以存储的单个项目的最大大小是多少?(1兆字节)

  为什么单个项目的大小限制为1M字节?

  为了让memcached更有效地使用服务器的内存,可以在每台服务器上配置不同大小的缓存空间吗?

  什么是二元协议?值得关注吗?

  memcached如何分配内存?为什么不用malloc/free!到底为什么要用石板?

  memcached能保证数据存储的原子性吗?

  集群架构中的问题

  memcached是如何工作的?

  Memcached的魔力来自于两级hash。Memcached就像一个巨大的哈希表,存储了许多键和值对。使用key,您可以存储或查询任意数据。

  客户端可以在多台memcached机器上存储数据。查询数据时,客户端首先通过查阅节点列表计算key的哈希值(stage one hash),然后选择一个节点;客户机请求被发送到选定的节点,然后memcached节点通过内部哈希算法(第二阶段哈希)搜索真实数据(项)。

  例如,假设有3个客户端1、2、3和3 memcached A、B和C:

  1客户端希望将数据“barbaz”存储为关键字“foo”。1客户端首先参考节点列表(A,B,C)并计算键 foo 的哈希值,假设选择了memcached B。然后,客户端1直接连接到memcached B,并通过键“foo”存储数据“barbaz”。客户端2使用与客户端1相同的客户端库(意味着阶段1中相同的哈希算法),并且具有相同的memcached列表(A,B,C)。

  然后,在相同的散列计算(阶段1)之后,客户机2计算出键‘foo’在memcached B上,然后它直接请求memcached B获取数据‘barbaz’。

  memcached中各种客户端的数据存储形式是不一样的(Perl Storable,PHP Serialize,Java Hibernate,JSON等。).一些客户端实现不同的哈希算法。但是,memcached服务器端的行为总是一致的。

  最后,从实现的角度来看,memcached是一个非阻塞的基于事件的服务器程序。该架构可以很好地解决C10K问题,并具有良好的可扩展性。

  可以参考一个缓存的故事。本文简要解释了客户机如何与memcached交互。

  memcached最大的优势是什么?

  请仔细阅读上面的问题(即memcached如何工作)。Memcached最大的优势是它带来了出色的水平可伸缩性,尤其是在一个庞大的系统中。因为客户机已经对自己进行了一次散列,所以很容易向集群添加大量的memcached。Memcached互不通信,所以不会增加memcached的负载;没有多播协议,网络流量不会爆炸。Memcached集群非常容易使用。内存不够?添加几个memcachedCPU不够用?再加几个;有多余的记忆?再补充几个,别浪费了。

  基于memcached的基本原理,构建不同类型的缓存架构是相当容易的。除了这个FAQ,在其他地方也很容易找到详细的信息。

  看看下面的问题,比较了memcached,服务器的本地缓存和MySQL的查询缓存。这些问题会让你有更全面的了解。

  Memcached和MySQL查询

  与cache相比,它的优缺点是什么?

  将memcached引入应用程序仍然需要做大量的工作。MySQL有便捷的查询缓存,可以自动缓存SQL查询的结果,缓存的SQL查询可以快速重复执行。Memcached跟它比怎么样?MySQL的查询缓存是集中式的,所有连接到查询缓存的MySQL服务器都会受益。

  当您修改一个表时,MySQL查询缓存会立即刷新。存储一个memcached项只需要一点时间,但是当写操作比较频繁的时候,MySQL的查询缓存往往会使所有缓存的数据失效。

  在多核CPU上,MySQL的查询缓存会遇到可扩展性问题。在多核CPU上,查询缓存会增加一个全局锁,会因为需要刷新更多的缓存数据而变慢。

  在MySQL的查询缓存中,我们不能存储任何数据(只能存储SQL查询结果)。使用memcached,我们可以构建各种高效的缓存。例如,您可以执行多个独立的查询,构建一个用户对象,然后将用户对象缓存到memcached中。虽然查询缓存是在SQL语句级别,但这是不可能的。在小网站中,查询缓存会有所帮助,但是随着网站规模的增大,查询缓存的缺点会大于优点。

  查询缓存可以利用的内存容量受到MySQL服务器的可用内存空间的限制。为数据库服务器增加更多内存来缓存数据当然是好的。但是有了memcached,只要你有空闲内存,就可以用来增加memcached集群的大小,然后就可以缓存更多的数据。

  服务器的Memcached和本地

  缓存的优缺点是什么(比如PHP的APC,mmap文件等。)?

  首先,本地缓存有很多和上面一样的问题(查询缓存)。本地缓存可以利用的内存容量受到(单个)服务器的可用内存空间的限制。然而,本地缓存优于memcached和查询缓存,因为它不仅可以存储任意数据,而且没有网络访问延迟。

  本地缓存的数据查询更快。考虑将高度常见的数据放在本地缓存中。如果每个页面需要加载少量数据,可以考虑将它们放在本地缓存中。

  本地缓存缺乏组失效的特性。在memcached集群中,删除或更新一个键会被所有观察者注意到。但是,在本地缓存中,我们只能通知所有服务器刷新缓存(速度慢且不可扩展),或者只能依靠缓存超时机制。

  memcached的缓存机制是什么?

  Memcached的主要缓存机制是LRU(最近最少使用)算法在超时后过期。在memcached中存储数据时,可以指定数据可以在缓存中保留多长时间,可以是永远,也可以是未来的某个时间。如果memcached的内存不足,将首先替换过期的片,然后替换最旧的未使用的片。

  memcached是如何实现冗余机制的?

  没有实现!这个问题让我们很惊讶。Memcached应该是应用程序的缓存层。它的设计本身没有任何冗余机制。如果memcached节点丢失了所有数据,您应该能够从数据源(比如数据库)重新获得数据。您应该特别注意,您的应用程序应该能够容忍节点故障。不要写一些不好的查询代码,希望memcached保证一切!如果担心节点故障会大大增加数据库的负担,那么可以采取一些措施。例如,您可以添加更多节点(以减少失去一个节点的影响)、热备用节点(在其他节点停机时接管IP)等等。

  memcached是如何处理容错的?

  不加工!)在memcached节点失效的情况下,集群不需要做任何容错处理。如果一个节点发生故障,将采取的措施完全取决于用户。当一个节点出现故障时,这里有几个选项供您选择:

  从节点列表中删除故障节点。做这个操作的时候一定要小心!默认情况下(余数哈希算法),客户端添加或删除节点,这将使所有缓存数据不可用!因为hash引用的节点列表发生了变化,所以大部分键会因为hash值的变化而映射到不同的节点。

  如果希望在不影响原始哈希结果的情况下添加和删除节点,可以使用一致哈希算法。可以检查一致性哈希算法。支持一致散列的客户机已经成熟并被广泛使用。去试试吧!

  两次散列(刷新)。客户端在访问数据时,如果发现某个节点down,会再做一次哈希(哈希算法和上一次不同),选择另一个节点(需要注意的是,客户端并没有将down节点从节点列表中删除,下次还是可以先哈希)。如果一个节点是好的或坏的,那么双重散列方法是有风险的,并且在好的和坏的节点上都可能有陈旧的数据。

  如何在memcached中批量导入和导出项目?

  你不应该这样做!Memcached是一个非阻塞服务器。应该仔细考虑任何可能导致memcached挂起或立即拒绝服务的操作。将数据批量导入memcached通常不是您真正想要的!想象一下,如果缓存的数据在导出和导入之间发生变化,需要处理脏数据;如果缓存的数据在导出和导入之间过期,您会怎么处理它?

  所以批量导出导入的数据并没有你想象的那么有用。但是在一个场景中很有用。如果您有大量从不更改的数据,并且希望缓存快速预热,那么批量导入缓存的数据会很有帮助。虽然这种场景并不典型,但是经常发生,所以以后我们会考虑实现批量导出导入的功能。

  史蒂文格里姆一如既往地在邮件列表中给出了另一个很好的例子:http://lists . danga . com/piper mail/memcached/2007-July/004802 . html。

  但是我确实需要在memcached中批量导出和导入该项。我该怎么办?

  好吧,好吧。如果需要批量导出和导入,最有可能的原因是重新生成缓存数据需要很长时间,或者数据库坏了让你很痛苦。

  如果一个memcached节点出现故障,让你很痛苦,你会陷入许多其他的麻烦。你的系统太脆弱了。你需要做一些优化工作。例如,处理“惊奇组”问题(例如,所有的memcached节点都失败了,您的数据库被重复的查询淹没了.这个问题在其他FAQ中也有提到),或者优化不佳的查询。请记住,Memcached不是您避免优化查询的借口。

  如果您的问题是重新生成缓存数据需要很长时间(15秒到5分钟以上),您可以考虑重用数据库。以下是一些建议:

  使用MogileFS(或类似的软件,如CouchDB)来存储项目。计算项目并将其转储到磁盘上。MogileFS可以轻松覆盖项目并提供快速访问。你甚至可以在memcached的MogileFS中缓存该项,这样可以加快读取速度。MogileFS Memcached的组合可以加快缓存未命中时的响应速度,提高网站的可用性。

  再次使用MySQL。MySQL InnoDB主键的查询速度很快。如果大部分缓存数据可以放在VARCHAR字段中,主键查询的性能会更好。从memcached按键查询几乎等同于MySQL的主键查询:将键散列为64位整数,然后将数据存储在MySQL中。您可以将原始的(非散列的)键存储在公共字段中,然后设置一个辅助索引来加速查询.密钥被动失效,无效密钥批量删除等等。

  以上方法都可以引入memcached,在重启memcached时仍然提供良好的性能。因为你不需要小心“热”项被memcached LRU算法突然消除,用户不再需要等待几分钟来重新生成缓存数据(当缓存数据突然从内存中消失时),所以上述方法可以全面提高性能。

  关于这些方法的细节,请看博客:http://dormando.livejournal.com/495593.html.

  memcached是怎么做认证的?

  没有认证机制!Memcached是运行在应用程序下层的软件(认证应该是应用程序上层的责任)。memcached的客户机和服务器之所以是轻量级的,部分原因是根本没有认证机制。这样memcached就可以快速创建新的连接,服务器端不需要任何配置。

  如果要限制访问,可以使用防火墙或者让memcached监听unix域套接字。

  memcached的多线程是什么?如何使用它们?

  是线程规则!多亏了史蒂文格里姆和脸书的努力,Memcached版和更高版本才有了多线程模式。多线程模式允许memcached充分利用多个CPU,并在CPU之间共享所有缓存的数据。Memcached使用简单的锁定机制来确保数据更新操作的互斥性。与在同一台物理机上运行多个memcached实例相比,这种方法可以更有效地处理多个get。

  如果你的系统负载不重,也许你不需要启用多线程模式。如果你正在运行一个拥有大规模硬件的大型网站,你会看到多线程的好处。

  详见:3358 code . six part . com/SVN/memcached/trunk/server/doc/threads . txt。

  简单总结一下:命令解析(memcached在这里花了大部分时间)可以在多线程模式下运行。Memcached对数据的内部操作是基于很多全局锁的(所以这部分工作不是多线程的)。未来多线程模式的改进将移除大量全局锁,提高memcached在极高负载场景下的性能。

  memcached可以接受的最大密钥长度是多少?

  密钥的最大长度为250个字符。需要注意的是,250是memcached服务器的内部限制。如果您使用的客户端支持“密钥前缀”或类似功能,则密钥(原始密钥前缀)的最大长度可以超过250个字符。我们建议使用较短的密钥,因为它可以节省内存和带宽。

  memcached对item的失效时间有什么限制?

  过期时间最长可达30天。Memcached将传入的过期时间(时间段)解释为一个时间点,一旦到达这个时间点,memcached就会将该项设置为无效状态。这是一个简单但晦涩的机制。

  memcached可以存储的单个项目的最大大小是多少?

  1MB .如果您的数据大于1MB,请考虑在客户端将其压缩或拆分为多个密钥。

  为什么单品尺寸限制在1M以内?

  字节内?

  啊.这是大家经常问的问题!

  简单回答:因为这是内存分配器的算法。

  详细回答:Memcached的内存存储引擎(该引擎以后是可插拔的.)使用片来管理内存。内存分为不同大小的slab块(先分成大小相等的slab,再将每个slab分成大小相等的chunk,不同slab的chunk大小不相等)。块的大小从一个最小值开始,以一定的倍数增加,直到达到可能的最大值。

  如果最小值为400B,最大值为1MB,因子为1.20,则每个slab1-400B slab2-480B slab3-576B的块大小。

  平板中的块越大,它与前一个平板之间的间隙就越大。因此,最大值越大,内存利用率越低。Memcached必须为每个slab预先分配内存,因此如果设置较小的因子和较大的最大值,将需要更多的内存。

  还有其他一些原因可以解释为什么不应该访问memcached中的大量数据.也不要试图把巨大的网页放在mencached中。将这么大的数据结构加载和解包到内存中需要很长时间,导致你的网站性能很差。

  如果真的需要存储大于1MB的数据,可以修改slaves.c: power _ block的值,然后重新编译memcached;或者使用低效的malloc/free。其他建议还有数据库,MogileFS等。

  我可以在不同的memcached节点上使用不同大小的缓存空间吗?这样做了之后,memcached能更有效地使用内存吗?

  Memcache客户端只根据哈希算法决定在哪个节点上存储一个键,而不考虑节点的内存大小。因此,您可以在不同的节点上使用不同大小的缓存。然而,这通常是这样做的:一个具有更多内存的节点可以运行多个memcached实例,并且每个实例与其他节点上的实例使用相同的内存。

  什么是二元协议,我应该关注吗?

  关于二进制的最佳信息当然是二进制协议规范:http://code . Google . com/p/memcached/wiki/memcachebinaryprotocol。

  二进制协议试图为客户端提供更高效、更可靠的协议,减少客户端/服务器处理协议造成的CPU时间。

  根据脸书的测试,解析ASCII协议是memcached中消耗CPU时间最多的环节。那么,我们为什么不改进ASCII协议呢?

  在这个邮件列表的线程中可以找到一些旧信息:http://lists . danga . com/piper mail/memcached/2007-July/004636 . html。

  memcached的内存分配器是如何工作的?为什么malloc/free不适用!为什么要用石板?

  实际上,这是一个编译时选项。默认情况下,将使用内部板分配器。你真的应该使用内置的板分配器。最早的时候,memcached只使用malloc/free来管理内存。但是,这种方法在以前操作系统的内存管理中并不奏效。反复的malloc/free造成了内存碎片,OS最后花了很多时间寻找连续的内存块来满足malloc的请求,而不是运行memcached进程。如果不同意,当然可以用malloc!不要在邮件列表里抱怨就好:)

  板坯分配器就是为了解决这个问题而诞生的。内存被分配并分成块,这些块一直被重复使用。因为内存被划分为不同大小的块,所以如果项目的大小不适合所选择的存储它的块,就会浪费一些内存。史蒂文格林在这方面做了有效的改进。

  邮件中有一些关于slab的改进(n的幂或2的幂)和权衡:http://lists . danga . com/piper mail/memcached/2006-May/002163 . html。

  lists . danga . com/piper mail/memcached/2007-March/003753 . html .

  如果您想使用malloc/free并看看它们是如何工作的,您可以在构建过程中定义USE_SYSTEM_MALLOC。这个功能还没有经过很好的测试,所以不太可能得到开发者的支持。

  更多信息:3358code.sixpart.com/svn/memcached/trunk/server/doc/memory _管理. txt。

  memcached是原子的吗?

  当然啦!好吧,让我们说清楚:

  发送给memcached的所有命令都是完全原子的。如果同时为相同的数据发送set命令和get命令,它们不会相互影响。它们将被连续序列化和执行。即使在多线程模式下,所有命令都是原子的,除非程序中有错误:)

  该序列不是原子的。如果你通过get命令得到一个项,修改它,然后想把它设置回memcached,我们不能保证这个项没有被其他进程操作过(进程,不一定是操作系统中的进程)。在并发的情况下,您也可以覆盖由另一个进程设置的项目。

  memcached 1 . 2 . 5及更高版本提供了gets和cas命令,可以解决上述问题。如果使用gets命令查询键的项,memcached将返回该项的当前值的唯一ID。如果您覆盖了这个条目,并希望将其写回到memcached中,那么您可以通过cas命令将这个惟一ID发送给memcached。如果memcached中存储的该项的惟一ID与您提供的一致,那么您的写操作将会成功。如果在此期间另一个进程也修改了该项,那么存储在memcached中的该项的惟一ID将会改变,您的写操作将会失败。

  通常,根据memcached中的值修改一个条目是一件棘手的事情。除非你很清楚自己在做什么,否则请不要做这样的事。

memcache集群方案,memcache