首页 » Web前端 » phpmemcached集群技巧_Memcached与Redis在内存机制和集群等方面的比较 Kablamo

phpmemcached集群技巧_Memcached与Redis在内存机制和集群等方面的比较 Kablamo

访客 2024-11-07 0

扫一扫用手机浏览

文章目录 [+]

其最初的设计目标是利用 Web 做事器上未利用的 RAM,将它们集中在一起以供应大型高速内存缓存。
它对 PHP 网站特殊有用,许可您将状态存储在无状态编程环境中,而无需写入数据库。

Redis 于 2009 年创建,在 TCL 中进行原型设计,然后也用 C 重写。
最初编写它是为了加速 Salvatore(创建者)的启动。
它也被包括 GitHub、Instagram、Stackoverflow 和 Craigslist 在内的大型网络资产所利用。

phpmemcached集群技巧_Memcached与Redis在内存机制和集群等方面的比较  Kablamo

它的原始设计目标是办理 Salvatores 问题并成为一个持久的内存数据构造存储,因此它支持这么多其他数据类型。
它成为 Ruby on Rails 堆栈的一个特殊受欢迎的补充,可能是由于出色的库支持和集成。

phpmemcached集群技巧_Memcached与Redis在内存机制和集群等方面的比较  Kablamo
(图片来自网络侵删)

MEMCACHED 如何组织内存

Memcached 将内存组织成页面、slabs块和chunks块。
当您启动做事时,您可以定义许可 memcached 利用多少MB内存。
Memcached 在启动时酒会分配那么多内存,然后(默认情形下)将其分成 1 MB 的页面。
这些页面首次分配时是空的,称为空闲页面。

一旦您向 memcached 添加一个项目,它就会查看您添加的内容的大小(以字节为单位),然后为一个空闲页面分配一个 Slab 类。
slab 类确定块的数量,包含进入slab 的项目。
默认情形下,最小块大小为 80 字节。

假设您将一个 80 字节的项目添加到新启动的 memcached 实例中。
它会选择第一个空闲页面,将其slab类设置为支持80字节的块,然后将您的项目放入该slab的第一个块中。
因此,给定默认的 1 MB 页面大小,通过分配其 Slab 类以支持 80 字节块,memcached 将能够将 13,107 个 80 字节项目存储到个中。
如果您随后添加另一个 80 字节的项目,它将与之前添加的项目进入同一块。

但是,如果您随后添加了一个 500 字节的项目,memcached 将找到一个新的空闲页面,分配一个新的 Slab 大小并将该项目存储在那里。
相同大小的其他项目将添补相同的平板页面直至其限定。

在实行此操作时,memcached 会进行权衡,这会摧残浪费蹂躏缓存空间。

假设您想在 memcached 中存储一个 70 字节的项目。
鉴于 80 字节是最小的块大小,当 memcached 存储该项目时,80 字节中有 10 字节的开销仍旧未利用。
内存仍旧会被占用,但是添加一个 10 字节的项目将不会分配给该空间,而是会利用一个新的块,个中有 70 个未利用的字节。

它是 memcached 为确保内存永久不会碎片而进行的设计权衡。

1 MB 页面/slab 大小确实意味着默认情形下您可以存储在 memcached 中的最大项目大小为 1 MB。
虽然你可以改变这一点..

如果您安装了 memcached 并按如下办法访问命令行,您实际上可以查看slab/chunk 分配。

slab class 1: chunk size 80 perslab 13107slab class 2: chunk size 100 perslab 10485slab class 3: chunk size 128 perslab 8192slab class 4: chunk size 160 perslab 6553slab class 5: chunk size 200 perslab 5242slab class 6: chunk size 252 perslab 4161slab class 7: chunk size 316 perslab 3318slab class 8: chunk size 396 perslab 2647slab class 9: chunk size 496 perslab 2114

这样,内存永久不会在 memcached 中碎片化。
因此不须要压缩它,因此不须要重新排列项目存储的后台进程。
此外,无需清理内存,您只需覆盖即可。

有一些负面影响。
第一个是摧残浪费蹂躏可用空间的内存开销。
这统统都归结为 memcached 利用的速率/内存权衡。
Memcached 可以并且确实重新分配了slab 类。
如果slab被清空,它可以重新分配一个新的类。

REDIS 如何组织内存

比较之下,Redis 以存储的每个项目为根本分配内存。
当一个 item 进入 Redis 时,它通过 malloc 调用分配内存并将 item 存储在空间中。
一段韶光后,您终极会在内存中涌现“漏洞”。
这是一个问题,由于这些孔会占用空间,并且可能无法被 Redis 或操作系统利用,详细取决于您考试测验存储的项目的大小。

虽然 Redis 在某些时候确实利用了 malloc ,但现在 Redis 实际利用的是jemalloc。
这样做的缘故原由是 jemalloc 虽然峰值性能较低,但内存碎片较少,有助于办理 Redis 碰着的框架内请安题。

但是内存碎片还是会发生,以是Redis也有一个内存碎片整理程序叫做defrag 2,它在后台运行,清理内存并关闭内存漏洞。
那些老到记得在 DOS 中运行碎片整理的人会明白这里发生了什么,但简而言之,它移动内存中的项目以考试测验创建连续的已用内存块。
这许可高效添加,由于它们可以附加在末了,并许可 Redis 将内存开释回操作系统。

你可以自己不雅观察Redis中的碎片情形。

内存组织意义

因此,理解 Redis 和 memcached 内存利用之间的差异,让我们看看这意味着什么。

Memcached Slab 一旦分配就永久不会改变它们的大小。
这意味着有可能毒害您的 memcached 集群并真正摧残浪费蹂躏内存。
如果您利用大量 1 MB 的项目加载空的 memcached 集群,则所有平板都将分配到该大小。
一旦发生这种情形,添加一个 80 KB 的项目终极会使您的 80 KB 项目位于 1 MB 块中,摧残浪费蹂躏大部分内存。
如果 Slab 被清空,则可以重新分配它们,

Memcached 也无法向其运行的操作系统开释内存。
Redis 可以,如果您打消所有键,或者如果有足够的项目过期,它将开始开释操作系统可以再次利用的内存。
这样做的好处取决于您是否正在运行多租户,这在 2021 年不太可能发生。

Memcached 永久不会利用比分配更多的内存,而 Redis 可能会利用,特殊是如果您滥用 TTL 值(将不才面的过期中先容)。
Memcached 永久不会碎片化内存,而 Redis 会,只管它在一定程度上得到了缓解。
通过某些奇怪的利用模式,可能会涌现高度碎片化的内存,从而导致原来可以保留的密钥过期。

末了,memcached 每个项目限定为 1 MB(这是可配置的但不建议),而 Redis 限定为每个项目存储 512 MB,但也不建议这样做。

缓存过期

因此,让我们简要先容一些更广为人知的缓存过期技能,即最少利用 (LFU) 和最近最少利用 (LRU)。
这很主要,由于 Redis 和 memcached 都利用缓存过期算法,以便知道在缓存已满时须要从缓存中删除哪些数据。

Memcached 利用 LRU。
Redis 实际上是可配置的,因此您可以利用 LRU、LFU、随机勉励、TTL……您在这里有一些选择,但根据我的履历,大多数人方向于利用 LRU 或 LFU。

LRU 作为算法的问题可以很大略地阐明。
考虑一个检讨缓存的做事,如果该值不存在,则访问后端以获取该值。

MEMCACHED 如何使项目过期

memcached 利用 LRU,并用于实现完美的 LRU 实现,实现本身是一个双向链表,个中的项目在访问、添加或更新时会被撞到头部。

当添加新的东西时,或者如果提取并且它的 TTL(生存韶光)年事表明它该当过期,项目就会被删除。
链表本身具有用于任何修正的互斥锁,这意味着当 memcached 是多线程的时,由于互斥争用,它可以有效利用的 CPU 内核数量存在上限。
在 memcached 中进行的第一个优化之一是,当要求或更新时,每 60 秒才会触发一次。
这可以防止热(常常要求或更新)项目导致大量互斥量争用。

通过这种设计,规模上限约为 8 个事情线程。
当您可以为台式机购买 128 线程 CPU 时,这有点问题。

同样,正如我们之前创造的,LRU 不是过期问题的最佳办理方案。
因此在 2020 年,memcached 开拓职员改变了它的事情办法。

Memcached 现在利用当代 LRU 实现,他们在他们的博客中详细描述了该实现。
它实际上类似于Varnish 海量存储引擎方法。

Memcached 现在有多个双向链表,个中一些被认为是热点,这会使它们“安全”不被驱逐,由于这些列表中的项目不会过期。
当它们移动到列表的末端时,它们会降到暖列表,终极会降到冷列表。
到达末端的冷列表中的项目被驱逐并可能被杀去世。
当发生这种情形时,冷或暖列表顶部的项目可以被碰撞到一个更暖的列表,所有东西都会向下流动。

由于这样的项目在利用时高下移动缓存层变得更安全或更可能被驱逐。
得到突发活动的项目在缓存中向上移动,在一段韶光内变得安全,并且常日足够长,以便它们再次得到突发要求仍旧在缓存中。
不常访问的项目退出。

这也意味着 memcached 须要一个称为 LRU 爬虫的后台线程,它正在扫描列表,使 TTL 结束的项目过期并适当地重新调度缓存。
由于列表拆分,它还改进了互斥量争用问题,并且 memcached 开拓职员声明它现在该当扩展到 48 个线程。

REDIS 如何过期 LRU?

在 LRU 模式下利用 Redis 时,须要把稳的最主要的一点是它不是 LRU 的教科书完美实现。
相反,Redis 实现了一个近似的 LRU 算法。
Redis 这样做的缘故原由是为了节省内存利用量。

它的事情办法是 Redis 选择随机数量的键(默认为 5)并驱逐最旧的。
从 Redis 3.0 开始,它通过保留来自先前运行的一组良好候选者并将其稠浊到随机选择中来改进该算法。
虽然是近似值,但通过保留一个池并选择 5 个键,它实际上能够实现靠近理论上完美的 LRU 驱逐。

您可以通过变动 Redis 配置maxmemory-samples 5值来配置样本数,个中较高的值将利用更多的 CPU,但会产生更靠近完美的结果。

对付那些想知道选择随机值是否是一个好主张的人,我建议您阅读Dan Luu 博客上的 Caches: LRU v. random 一文。

REDIS 如何使LRU过期? 它只是在访问条款时增加一个值,并通过可配置的衰减韶光随着韶光的推移降落该值。

您可以调度的可配置值是:

lfu-log-factor 10lfu-decay-time 1

我不会在这里详细先容 Redis LFU。
LRU 常日不如 LFU 有效。

那么哪种到期算法更好呢?

从技能上讲,Redis 仍旧可以使活动元素过期。
概率定律表明这可能会发生,但也不太可能发生。

比较之下,Memcached 只会随着韶光的推移使未利用的项目过期。
它仍旧是 LRU,但减轻了 LRU 的紧张毛病。
Memcached 可以使具有长 TTL 的项目过期,以支持利用短 TTL 保留更频繁访问的项目,只管实际上这对其当代 LRU 实现来说不是问题。

在实践中,两者都事情得很好,并且由于它们添加了一些调度,它们的实际性能与经典 LRU 或 LFU 算法所建议的不符。

内存缓存扩展

Memcached 是多线程的,用于后台进程和事宜处理。
这意味着您可以扩展您的 memcached 实例,为其供应更多 CPU 内核以提高性能。
如前所述,2020 年 8 核是 memcached 的有效扩展限定,但由于新的 LRU 设计,现在是 48 核。

Memcached 从创建的那一刻起就可以通过设计扩展到集群中。
memcached 中的集群是一种有趣的野兽,由于它们可以根据您的喜好进行扩展,只管您终极可能不得不编写自己的客户端库来这样做。

Redis 紧张是单线程的,有一些后台任务,例如在后台运行的碎片整理程序,但是对付添加/更新/删除事宜会碰着核心事宜循环。
因此,扩展 Redis 的唯一有效方法是在同一台机器上运行多个实例,只管这会影响内存效率。

然而,Memcached 可以扩展到集群。
集群模式可扩展到 16,384 个节点,但建议坚持少于 1,000。

MEMCACHED 集群

Memcached 集群利用无共享方法。
Memcached 集群实际上只是多个独立的 memcached 做事,它们乃至可以具有个性化的配置设置或缓存大小!
为了利用集群,您须要配置客户端库以理解集群中的每个实例,有一些中间件集群管理工具可以为您实现这一点。

大多数 memcached 客户端都内置了集群功能。
那么它们是如何做到的呢?客户端如何知道一个键该当驻留在哪个实例上?

常日的第一个答案是哈希键,然后根据集群中的实例数将模数运算符运用于结果。
结果是您该当查找或存储哈希键的实例。
请把稳,如果这成为 CPU 瓶颈,您可以避免利用模数运算符进行一些操作。

Memcached 通过同等性哈希办理了这个问题:您不必担心实例数量增加或减少。

REDIS集群

具有多个领导节点的 Redis 集群,这些节点有一些追随者。
节点不会代理发送给它们的命令,而是重定向到精确的节点。
客户端该当记住映射,以便他们下次可以精确命中节点。

集群本身是一个全网状集群,这意味着每个节点都知道其他每个节点。
由于全网状网络在与高节点数通信时会变得非常生动,它利用 gossip协议来使信息在网络上传播。
因此,一个新节点将向其他几个节点宣告自己,并且他们将通报信息,直到每个人都知道新来者。

Redis 集群实际上相称繁芜,值得写一篇博文。
在Redis的cluser规范页面给出了一个很好的概述,但并是值得看的,如果你想理解更多信息。

严明地说,如果您确实须要 Redis 集群,请利用托管做事。
它将为您节省大量站起来和掩护它的韶光和精力。

当项目被添加到 Redis 时,它须要键的 CRC16,然后利用 14 位的结果。
这供应了 16,384 个可能的值,Redis 可以利用这些值将项目存储到集群中。
这便是其最大集群值的缘故原由。
这也意味着节点数量存在硬性限定,只管官方推举的最大节点数为 1,000 个节点。
每个领导者处理值总数的一部分,称为哈希槽,集群在重新配置时知道每个值该当存储在哪里。
由于添加或删除了新节点而重新配置时,哈希槽及其值会在领导者之间移动。

REDIS 与 MEMCACHED。
我该当利用哪一种?

因此,鉴于已经谈论过的所有内容,我该当利用哪个键值缓存?Redis 还是 Memcached?答案是:视高下文情形而定。

不过,您可能可以遵照一些规则。

利用 memcached 的缘故原由,

如果您须要通过在问题上投入更多 CPU 来扩大规模如果你真的在锤击缓存如果你缓存了很多非常小的值,最好都是一样的大小如果您自己运行集群,memcached 更随意马虎设置和掩护

否则我会建议利用 Redis 并利用它带来的其他东西,比如它可爱的数据类型、流等等。

然而,关于 memcached 和 redis 有一个未提及的秘密。
即两者都是网络缓存。

网络缓存实际上很慢!

在我看来,Stack overflow通过利用 L1/L2 缓存策略精确实现了这一点,Stack overflow博客对此进行了深入先容。

简而言之,如果可以,您该当利用您的运用程序可以直接调用的内存作为 1 级 (L1) 缓存,如果该值不存在,请在返回之前访问您的 2 级 (L2) Redis/memcached 集群缓存你的原形来源。
如果该值在您的 L1 缓存中,则访问韶光的差异是 100 ns 与 1 ms,这要快一个数量级。

Memcached与Redis在内存机制和集群等方面的比较 - Kablamo

相关文章

QQ伪装黑客代码大全技术与风险警示

网络安全问题日益凸显。QQ作为一种流行的社交工具,成为了黑客攻击的主要目标之一。本文将针对QQ伪装黑客代码大全进行深入剖析,揭示其...

Web前端 2025-03-02 阅读1 评论0