memcached面试问题以及答案


memcached是什么?

Memcached是一种开源的、高性能的分布式内存对象缓存系统,用于加速动态Web应用程序的性能。它通常用于缓存数据库查询结果、API调用结果或任何经常被请求但计算成本高的数据。Memcached将这些数据存储在内存中,并提供简单而快速的访问机制,以减少对后端数据存储系统(如数据库)的访问次数,从而降低了系统的负载并提高了响应速度。

Memcached的特点包括:

  1. 内存存储:数据存储在内存中,以提供快速的读取和写入操作。
  2. 分布式架构:可以在多个节点上部署,以实现高可用性和横向扩展。
  3. 缓存逻辑简单:主要提供键值对的存储,易于使用和管理。
  4. 高性能:由于数据存储在内存中,因此能够提供非常低的访问延迟。
  5. 减轻后端负载:通过缓存频繁请求的数据,可以减少对后端数据存储系统的压力。

Memcached通常与后端数据存储系统(如数据库)配合使用,用于缓存频繁访问的数据,从而提高应用程序的性能和可伸缩性。

Memcached的工作原理

Memcached的神奇来自两阶段哈希(two-stage hash)。Memcached就像一个巨大的、存储了很多<key,value>对的哈希表。通过key,可以存储或查询任意的数据。

客户端可以把数据存储在多台memcached上。当查询数据时,客户端首先参考节点列表计算出key的哈希值(阶段一哈希),进而选中一个节点;客户端将请求发送给选中的节点,然后memcached节点通过一个内部的哈希算法(阶段二哈希),查找真正的数据(item)。

举个列子,假设有3个客户端1, 2, 3,3台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是一个非阻塞的、基于事件的服务器程序。

Memcached的最大优势

Memcached最大的好处是它带来了极佳的水平可扩展性,特别是在一个巨大的系统中。由于客户端自己做了一次哈希,那么我们很容易增加大量memcached到集群中。memcached之间没有相互通信,因此不会增加 memcached的负载;没有多播协议,不会网络通信量爆炸(implode)。memcached的集群很好用。内存不够了?增加几台 memcached吧;CPU不够用了?再增加几台吧;有多余的内存?在增加几台吧,不要浪费了。

基于memcached的基本原则,可以相当轻松地构建出不同类型的缓存架构。

Memcached与MySQL的Query Cache比较

在将Memcached引入应用中时,需要一定的工作量。MySQL提供了方便使用的query cache,可以自动缓存SQL查询的结果,从而实现对被缓存的查询的快速反复执行。与之相比,Memcached具有哪些优缺点呢?

  • 缓存更新效率:MySQL的query cache在修改表结构时会立即刷新(flush),而存储在memcached中的数据项更新时间较短。然而,当写操作频繁时,MySQL的query cache可能导致大量缓存数据失效。

  • 扩展性问题:MySQL的query cache在多核CPU上会遇到扩展性问题,因为它会引入一个全局锁,可能导致性能下降。相比之下,memcached不会因为多核CPU而受到这样的限制。

  • 数据存储灵活性:MySQL的query cache仅能存储SQL查询结果,而memcached可以存储各种类型的数据。通过memcached,可以执行多个独立的查询,构建出一个用户对象,并将其缓存起来。而query cache仅针对SQL语句级别的缓存,无法实现这种复杂的缓存结构。

  • 内存利用:MySQL的query cache受限于MySQL服务器的空闲内存空间,而memcached则可以根据需要动态扩展集群规模,利用更多的空闲内存来缓存更多的数据。

总的来说,对于小型网站,MySQL的query cache可能会有所帮助,但随着网站规模的增加,其弊端会逐渐显现。相比之下,Memcached提供了更灵活、更可扩展的缓存方案,特别适用于大规模和高并发的应用场景。

Memcached与服务器的Local Cache比较

与服务器的本地缓存(如PHP的APC、mmap文件等)相比,Memcached和Local Cache都有各自的优缺点。

优点:

  • 数据查询速度:Local Cache的数据查询速度更快,因为它们存储在服务器的本地内存中,没有网络存取的延迟。这使得将高频访问的数据放入Local Cache中成为一个不错的选择。

  • 存储任意数据类型:Local Cache可以存储任意类型的数据,而不仅仅是SQL查询结果。这使得它在需要缓存更复杂的数据结构时具有优势。

缺点:

  • 缺乏集体失效机制:在Memcached集群中,删除或更新一个键会导致所有观察者注意到这一变化。但在Local Cache中,我们只能通过通知所有服务器刷新缓存(速度慢、不具扩展性)或依赖缓存超时失效机制来实现。这导致了Local Cache在缓存失效管理方面的不足。

  • 严重的内存限制:Local Cache面临着严重的内存限制,受到服务器可用内存空间的限制。这使得在大规模、高并发的应用场景下,Local Cache的可用性受到较大影响。

综上所述,Memcached和Local Cache各有其适用场景。对于需要快速访问、数据结构较为简单且不需要频繁更新的情况,Local Cache可能更适合;而对于需要分布式、高度可扩展、复杂数据结构且需要频繁更新的场景,Memcached可能更合适。

Memcached的缓存机制

Memcached主要的缓存机制包括LRU(最近最少使用)算法和超时失效机制。

  • LRU算法:LRU算法是Memcached用来管理缓存空间的一种常用策略。当缓存空间不足时,Memcached会优先替换最近最少被使用的数据。这样做可以确保缓存中的数据是最有可能被访问的数据,提高了缓存命中率,从而提升了性能。

  • 超时失效机制:在存储数据到Memcached时,可以指定数据在缓存中的过期时间,可以是永久保存(forever),也可以是一段未来的时间。一旦数据过期,Memcached会自动将其从缓存中删除,从而释放空间给新的数据。这个机制确保了缓存中的数据不会永久存在,避免了缓存中存储过期或无效数据的问题。

如果Memcached的内存空间不足,会根据LRU算法和超时失效机制来进行替换。首先,过期的slabs(内存块)会被优先替换;接着,会依次替换最老的未被使用的slabs。这样的替换策略保证了在内存不足时,尽可能保留最有价值的数据,以提高缓存命中率和性能。

Memcached的冗余机制

Memcached本身并不提供冗余机制。它被设计为应用的缓存层,不具备数据冗余备份的功能。如果一个Memcached节点失去了所有数据,您应该可以通过数据源(例如数据库)重新获取数据。因此,在使用Memcached时,应该特别注意,应用程序需要能够容忍节点的失效。不应该依赖Memcached来保证数据的完整性和可靠性。

如果您担心节点失效会给数据库造成负担,可以采取一些措施来减轻影响。例如,增加更多的Memcached节点来降低丢失一个节点的影响,或者使用热备份节点来在其他节点失效时接管IP地址等。

综上所述,Memcached不提供数据冗余备份机制,因此在设计应用程序时应该考虑到节点失效的情况,并采取相应的措施来保证数据的可靠性和可用性。

Memcached的容错处理

Memcached本身不提供容错处理机制。在Memcached节点失效的情况下,集群不会自动进行任何容错处理。相反,处理节点失效的措施完全取决于用户。

以下是几种处理节点失效的常见方案:

  • 忽略节点失效:在节点失效期间,集群中的其他节点仍然可以继续工作。因此,可以选择忽略失效节点,直到它恢复或被替换。

  • 移除失效节点:可以将失效的节点从节点列表中移除。但需要小心,因为默认情况下(余数式哈希算法),添加或移除节点会导致缓存数据不可用。因为哈希参考的节点列表发生变化,大部分键会被映射到不同的节点上。

  • 启动热备节点:可以启动热备份节点,接管失效节点的IP地址。这样可以避免哈希算法混乱。

  • 一致性哈希算法:使用一致性哈希算法可以实现添加和移除节点而不影响原有的哈希结果。一致性哈希算法已经被广泛使用,并且有成熟的客户端库支持。

  • 两次哈希(reshing):当客户端访问数据时,如果发现一个节点失效,可以进行两次哈希,选择另一个节点。但这种方法存在一定的风险,因为好的节点和坏的节点上都可能存在过时数据。

综上所述,Memcached在节点失效时不提供自动容错处理,用户可以根据需求选择合适的处理方案来应对节点失效带来的影响。

Memcached中的批量导入导出

在Memcached中,不建议进行批量导入导出操作。Memcached是一个非阻塞的服务器,任何可能导致其暂停或瞬时拒绝服务的操作都应该慎重考虑。因此,向Memcached中批量导入数据往往不是一个理想的选择。

批量导入数据可能会导致以下问题:

  • 数据变化:如果在导入过程中缓存数据发生了变化,可能会导致脏数据的问题。
  • 数据过期:如果在导入过程中缓存数据过期了,可能会导致缓存数据的不一致性。

因此,批量导入导出数据并不像想象中的那么实用。不过,在某些特定场景下,批量导入数据可能会有所帮助。例如,如果有大量的静态数据且希望缓存快速热起来,批量导入缓存数据可能会提高性能。虽然这种情况并不常见,但确实存在。

Memcached中的批量导出导入

如果您需要批量导出导入数据,可能是因为重新生成缓存数据耗时较长,或者数据库出现问题,导致您处于困境。

如果一个Memcached节点的失效让您痛苦,那么您的系统可能存在其他潜在问题,需要进行优化。例如,您可能需要处理“惊群”问题,即当所有Memcached节点失效时,大量的查询压力会直接转移到数据库上,导致数据库不堪重负。请记住,Memcached并不是您逃避优化查询的借口。

如果您遇到的问题仅仅是重新生成缓存数据耗时较长(从15秒到超过5分钟),您可以考虑重新利用数据库。以下是一些提示:

  • 使用MogileFS或类似软件存储item:将生成的item dump到磁盘上,并使用MogileFS(或类似的软件)管理存储和访问。MogileFS可以方便地覆写item,并提供快速的访问。您甚至可以将MogileFS中的item缓存在Memcached中,以加快读取速度。这样的组合可以提高缓存不命中时的响应速度,提高网站的可用性。

  • 重新利用MySQL:MySQL的InnoDB引擎在主键查询方面性能非常出色。如果大部分缓存数据可以存储在VARCHAR字段中,那么主键查询的性能将更佳。您可以将key哈希到64位整数,然后存储到MySQL中。将原始key存储在普通字段中,然后建立二级索引以加快查询速度。通过这种方式,您可以利用Memcached提供的快速缓存访问,在重启Memcached时仍然能够保持良好的性能。

上述方法都可以在重启Memcached时提供良好的性能,并帮助解决缓存数据重新生成耗时较长的问题。由于不需要担心Memcached LRU算法突然淘汰“热点”数据,用户也不再需要等待数分钟来重新生成缓存数据,因此这些方法可以全面提高性能。

Memcached的身份验证机制

Memcached不提供身份验证机制。它是一个运行在应用程序下层的轻量级软件,因此没有实现身份验证机制。Memcached的客户端和服务器端之所以轻量级,部分原因就在于完全没有实现身份验证。

由于缺乏身份验证机制,Memcached可以快速创建新连接,而服务器端也无需进行任何身份验证配置。

如果您需要限制访问,可以考虑以下方法:

  • 使用防火墙:通过配置防火墙规则来限制对Memcached端口的访问,只允许来自特定IP地址或IP地址段的访问。

  • 使用Unix域套接字(Unix domain socket):让Memcached监听Unix域套接字而不是网络端口,这样只有本地应用程序才能与Memcached进行通信,从而实现访问限制。

综上所述,Memcached不提供身份验证机制,但可以通过其他方式来限制对其的访问。

Memcached的多线程模式

Memcached在1.2及更高版本引入了多线程模式,这使得它能够更好地利用多个CPU,并在CPU之间共享所有的缓存数据。多线程模式通过一种简单的锁机制来保证数据更新操作的互斥,使得Memcached能够更有效地处理多个请求。

多线程模式的主要优势在于能够更好地处理多个并发请求,特别是在大规模硬件和高负载的网站上能够体现出明显的性能优势。相比于在同一个物理机器上运行多个Memcached实例,多线程模式能够更有效地利用系统资源。

简单来说,多线程模式使得Memcached能够在命令解析阶段(Memcached在这个阶段花费大部分时间)运行在多个线程下。然而,Memcached内部的数据操作仍然基于一些全局锁,因此并非所有工作都是多线程的。未来,对多线程模式的改进可能会移除大量的全局锁,以提高Memcached在极高负载场景下的性能。

Memcached Key长度限制

Memcached服务器端对于key的最大长度限制是250个字符。需要注意的是,这个限制是Memcached服务器端内部的限制。如果您的客户端支持"key的前缀"或类似特性,那么key的最大长度可以超过250个字符。

建议您尽量使用较短的key,因为这样可以节省内存和带宽资源。较短的key不仅可以减少存储和传输的开销,还可以提高系统的效率和性能。

Memcached过期时间限制

Memcached对item的过期时间最大可以设置为30天。当您向Memcached存储数据时,可以指定一个过期时间(以时间段的形式)。Memcached将此过期时间解释为一个时间点,在达到该时间点后,Memcached将该item标记为失效状态。

虽然这是一个简单的机制,但有时也可能会被忽视,因此需要注意。确保您理解并正确设置item的过期时间,以避免数据过期或存储时间过长导致的不必要的资源浪费。

Memcached单个Item的最大存储容量

Memcached单个Item的最大存储容量为1MB。如果您要存储的数据超过1MB,建议考虑在客户端对数据进行压缩或拆分,并将其存储为多个key的形式。

拆分或压缩数据可以帮助您克服这个限制,并确保您能够有效地利用Memcached的存储空间。

单个Item大小限制为1MB的原因

简单地说,单个Item大小被限制在1MB之内是由于Memcached内存分配器的算法所决定的。

详细来说,Memcached的内存存储引擎使用slabs来管理内存。内存被分成大小不等的slabs chunks,每个slab被分成大小相等的chunks。不同slab的chunk大小依次增长,直到达到最大可能值。这个增长的因子通常是1.20。

因此,如果最小值为400字节,最大值是1MB,那么每个slab中chunk的大小会依次增长。然而,随着chunk大小的增加,不同slab之间的间隙也会增加。因此,较大的最大值会导致内存利用率下降,而Memcached必须为每个slab预先分配内存,从而需要更多的内存。

除此之外,还有其他原因不建议将超过1MB的数据存储在Memcached中。加载和解压这样大的数据结构会消耗大量时间,从而影响网站的性能。

如果确实需要存储大于1MB的数据,可以考虑修改Memcached的源代码重新编译,或者使用低效的malloc/free方法。另外,还可以考虑使用数据库或MogileFS等替代方案。

不同节点上使用大小不等的缓存空间

是的,您可以在不同的Memcached节点上使用大小不等的缓存空间。然而,Memcached客户端仅根据哈希算法来决定将某个key存储在哪个节点上,而不考虑节点的内存大小。因此,您需要手动管理每个节点上的内存使用情况,以确保较多内存的节点可以运行多个Memcached实例,并且每个实例使用的内存量相同。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XMYX-0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值