300分钟吃透分布式缓存-12讲:为何MC能长期维持高性能读写?

内存管理 slab 机制

讲完淘汰策略,我们接下来学习内存管理 slab 机制。

Mc 内存分配采用 slab 机制,slab 机制可以规避内存碎片,是 Mc 能持续高性能进行数据读写的关键。

slabclass

Mc 的 slab 机制是通过 slabclass 来进行运作的,如下图所示。Mc 在启动时,会构建长度为 64 的 slabclass 数组,其中 0 号 slabclass 用于 slab 的重新分配,1~63 号 slabclass 存储数据 Item。存储数据的每个 slabclass,都会记录本 slabclass 的 chunk size,同时不同 slabclass 的 chunk size 会按递增因子增加,最后一个 slabclass(即 63 号 slabclass)的 chunk size 会直接设为最大的 chunk size,默认是 0.5MB。每个 slabclass 在没有空闲的 chunk 时,Mc 就会为其分配一个默认大小为 1MB 的 slab,同时按照本 slabclass 的 chunk size 进行拆分,这些分拆出来的 chunk 会按 Item 结构体进行初始化,然后记录到 slabclass 的 freelist 链表中。当有 key/value 要存储在本 slabclass 时,就从 freelist 分配一个 Item,供其使用。同时,如果 Item 过期了,或被 flush_all 失效了,或在内存不够时被强项剔除了,也会在适当时刻,重新被回收到 freelist,以供后续分配使用。
在这里插入图片描述
存储 slab 分配

如下图所示,Mc 的存储空间分配是以 slab 为单位的,每个 slab 的默认大小时 1MB。因此在存数据时,Mc 的内存最小分配单位是 1MB,分配了这个 1MB 的 slab 后,才会进一步按所在 slabclass 的chunk size 进行细分,分拆出的相同 size 的 chunk。这个 chunk 用来存放 Item 数据,Item 数据包括 Item 结构体字段,以及 key/value。

一般来讲,Item 结构体及 key/value 不会填满 chunk,会存在少量字节的浪费,但这个浪费的字节很少,基本可以忽略。Mc 中,slab 一旦分配,就不会再被回收,但会根据运行状况,重新在不同 slabclass 之间进行分配。
在这里插入图片描述
当一个 slabclass 没有空闲 chunk,而新数据插入时,就会对其尝试增加一个新的 slab。slabclass 增加新 slab 时,首先会从 0 号全局 slabclass 中复用一个之前分配的 slab,如果 0 号 slabclass 没有 slab,则会尝试从内存堆空间直接分配一个 slab。如果 0 号全局 slabclass 没有空闲 slab,而且 Mc 内存分配已经达到 Mc 设定的上限值,就说明此时没有可重新分配的 slab,分配新 slab 失败,直接返回。

当然,虽然 slabclass 分配 slab 失败,但并不意味着 Item分配会失败,前面已经讲到,可以通过同步 LRU 淘汰,回收之前分配出去的 Item,供新的存储请求使用。

Item

Mc 中,slabclass 中的 chunk 会首先用 Item 结构体进行初始化,然后存到 freelist 链表中,待需要分配给数据存储时,再从 freelist 中取出,存入 key/value,以及各种辅助属性,然后再存到 LRU 链表及 Hashtable 中,如下图所示。Item 结构体,首先有两个 prev、next 指针,在分配给待存储数据之前,这两个指针用来串联 freelist 链表,在分配之后,则用来串联所在的 LRU 链表。接下来是一个 h_next 指针,用来在分配之后串联哈希表的桶单向链表。Item 结构体还存储了过期时间、所属 slabclass id,key 长度、cas 唯一 id 值等,最后在 Item 结构体尾部,存储了 key、flag、value 长度,以及 value block 数据。在 value 之后的 chunk 空间,就被浪费掉了。Item 在空闲期间,即初始分配时以及被回收后,都被 freelist 管理。在存储期间,被哈希表、LRU 管理。
在这里插入图片描述
存储 Item 分配

Mc 采用 slab 机制管理分配内存,采用 Item 结构存储 key/value,因此对存储 key/value 的内存分配,就转换为对 Item 的分配。分配 Item 空间时,会进行 10 次大循环,直到分配到 Item 空间才会提前返回。如果循环了 10 次,还没有分配到 Item 空间,则存储失败,返回一个 SERVER_ERROR 响应。

在分配过程中,首先,如果 slabclass 的 freelist 有空间,则直接分配。否则,尝试分配一个新的 slab,新 slab 依次尝试从全局 slab 池(即 0 号 slabclass)中复用一个空闲 slab,如果全局 slab 池没有 slab,则尝试从内存直接分配。分配新 slab 成功后,会按照 slabclass 记录的 chunk size 对 slab 进行分拆,并将分拆出来的 chunk 按 Item 结构初始化后记录到 freelist。如果全局 slab 池为空,且 Mc 内存分配已经达到设定的上限,则走新增 slab 的路径失败,转而进行 5 次小循环,尝试从 COLD LRU 回收过期 key,如果没有过期则直接强制剔除队尾的一个正常 key。如果该 slabclass 的 COLD LRU 没有 Item,则对其 HOT LRU 进行处理,对 HOT 链表队尾 Item 进行回收或者迁移,以方便在下次循环中找到一个可用的 Item 空间。

数据存储机理

讲完 Mc 的哈希表定位、LRU 淘汰、slab 内存分配,接下来我们来看看 Mc 中 key/value 数据的存储机理,通过对数据存储以及维护过程的分析,来把 Mc 的核心模块进行打通和关联。

首先来看 Mc 如何通过 slab 机制将数据写入预分配的存储空间。

如下图所示,当需要存储 key/value 数据时,首先根据 key/value size,以及 Item 结构体的 size,计算出存储这个 key/value 需要的字节数,然后根据这个字节数选择一个能存储的 chunk size 最小的 slabclass。再从这个 slabclass 的 freelist 分配一个空闲的 chunk 给这个 key/value 使用。如果 freelist 为空,首先尝试为该 slabclass 新分配一个 slab,如果 slab 分配成功,则将 slab 按 size 分拆出一些 chunk,通过 Item 结构初始化后填充到 freelist。如果 slab 分配失败,则通过 LRU 淘汰失效的 Item 或强行剔除一个正常的 Item,然后这些 Item 也会填充到 freelist。当 freelist 有 Item 时,即可分配给 key/value。这个过程会重试 10 次,直到分配到 Item 位置。一般情况下,Item 分配总会成功,极小概率情况下也会分配失败,如果分配失败,则会回复一个 SERVER_ERROR 响应,通知 client 存储失败。分配到一个空闲的 Item 后,就会往这个 Item 空间写入过期时间、flag、slabclass id、key,以及 value 等。对于 set 指令,如果这个 key 还有一个旧值,在存入新 value 之前,还会先将这个旧值删除掉。
在这里插入图片描述
当对 key/value 分配 Item 成功,并写入数据后,接下来就会将这个 Item 存入哈希表。因为Mc 哈希表存在迁移的情况,所以对于正常场景,直接存入主哈希表。在哈希表迁移期间,需要根据迁移位置,选择存入主哈希表还是旧哈希表。存入哈希表之后,这个 key 就可以快速定位了。然后这个 Item 还会被存入 LRU,Mc 会根据这个 key 的过期时间进行判断,如果过期时间小于 61s,则存入 TEMP LRU,否则存入 HOT LRU。

至此,这个 key/value 就被正确地存入 Mc 了,数据内容写入 slabclass 中某个 slab 的 chunk 位置,该 chunk 用 Item 结构填充,这个 Item 会被同时记录到 Hashtable 和 LRU,如下图所示。通过 Hashtable 可以快速定位查到这个 key,而 LRU 则用于 Item 生命周期的日常维护。
在这里插入图片描述
Mc 对 Item 生命周期的日常维护,包括异步维护和同步维护。异步维护是通过 LRU 维护线程来进行的,整个过程不影响 client 的正常请求,在 LRU 维护线程内,对过期、失效 key 进行回收,并对 4 个 LRU 进行链表内搬运和链表间迁移。这是 Item 生命周期管理的主要形式。同步维护,由工作线程在处理请求命令时进行。工作线程在处理 delete 指令时,会直接将 key/value 进行删除。在存储新 key/value 时,如果分配失败,会进行失效的 key 回收,或者强行剔除正常的 Item。这些 Item 被回收后,会进入到 slabclass 的 freelist 进行重复使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/488196.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

普中51单片机学习(DS1302)

DS1302时钟 DS1302实时时钟具有能计算2100年之前的秒、分、时、日、日期、星期、月、年的能力,还有闰年调整的能力。内部含有31个字节静态RAM,可提供用户访问。采用串行数据传送方式,使得管脚数量最少,简单SPI 3线接口。工作电压…

测试开源C#人脸识别模块DlibDotNet

百度“C# 换脸”找到参考文献4,发现其中使用DlibDotNet检测并识别人脸(之前主要用的是ViewFaceCore),DlibDotNet是Dlib的.net封装版本,后者为开源C工具包,支持机器学习算法、图像处理等算法以支撑各类高级应…

Ansible 常见模块

模块文档 官方模块列表:https://docs.ansible.com/ansible/latest/collections/index_module.html # 查看支持的模块(小写 l) ansible-doc -l # 查看支持的模块个数-> 3387 ansible-doc -l | wc -l # ansible-doc 模块名 或者 ansible-…

从零开始学IO_FILE的堆利用:理解IO_FILE之fread

要学习基于IO_FILE的堆利用就得了解它的本质,以下会介绍几个主要的IO函数,结合源码和动态调试去学习。 调试环境搭建可参考环境从零开始配置pwn环境:从零开始配置pwn环境:优化pwn虚拟机配置支持libc等指令-CSDN博客 前面分析了系统…

Servlet使用Cookie和Session

一、会话技术 当用户访问web应用时,在许多情况下,web服务器必须能够跟踪用户的状态。比如许多用户在购物网站上购物,Web服务器为每个用户配置了虚拟的购物车。当某个用户请求将一件商品放入购物车时,web服务器必须根据发出请求的…

链表和顺序表的优劣分析及其时间、空间复杂度分析

链表和顺序表的优劣分析及其时间、空间复杂度分析 一、链表和顺序表的优劣分析二、算法复杂度<font face "楷体" size 5 color blue>//上面算法的执行次数大致为&#xff1a;F&#xff08;N&#xff09; N^22*N10;   N 10,F(10) 1002010 130次   N 1…

「JavaSE」String类3:字符串常量池

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;快来卷Java啦 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 字符串常量池 &#x1f349;常量池&#x1f349;字符串常量池&#x1f349;intern 方法 &#x1f349;常量池 在Java程序中&…

dpdk环境搭建和工作原理

文章目录 1、DPDK环境搭建1.1、环境搭建1.2、编译DPDK 2、DPDK工作原理 1、DPDK环境搭建 1.1、环境搭建 工具准备&#xff1a;VMware、ubuntu16.04。 &#xff08;1&#xff09;VMware添加两个网卡。桥接网卡作为 DPDK 运行的网卡&#xff0c;NAT 网卡作为 ssh 连接的网卡。 …

Python算法题集_图论(课程表)

Python算法题集_课程表 题207&#xff1a;课程表1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【循环递归全算】2) 改进版一【循环递归缓存】3) 改进版二【循环递归缓存反向计算】4) 改进版三【迭代剥离计数器检测】 4. 最优算法5. 相关资源 本…

台式电脑电源功率越大越费电吗?装机选购多少W电源

要组装一台电脑&#xff0c;我们首先需要选择硬件。 硬件搭配最关键的一点就是CPU和主板的兼容性。 硬件、电源等之间的平衡都需要仔细考虑。 那么台式电脑电源多大功率合适呢&#xff1f; 下面分享组装电脑电源瓦数选购指南&#xff0c;教您正确选择合适的电源瓦数。 让我们来…

爬取m3u8视频

网址&#xff1a;https://www.bhlsm.com/cupfoxplay/609-3-1/ 相关代码&#xff1a; #采集网址&#xff1a;https://www.bhlsm.com/cupfoxplay/609-3-1/ #正常视频网站&#xff1a;完整视频内容 # pip install pycryptodomex #流媒体文件&#xff1a;M3U8&#xff08;把完整的…

Python is not set from command line or npm configuration 报错解决

问题 在 npm install 的过程中提示 Python is not set from command line or npm configuration 的报错&#xff0c;相信不少朋友都遇到过&#xff0c;出现这个问题的原因是缺少 python 环境所导致的。 解决方法 1、安装 python 官网&#xff1a;https://www.python.org/dow…