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://xiahunao.cn/news/2805743.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

程序媛的mac修炼手册-- 小白入门Java篇

最近因为要用CiteSpace做文献综述,间接接触Java了。所以,继Python、C之后,又要涉猎Java了。刺激!! 由于CiteSpace与Java要求版本高度匹配,有个匹配详情明天为大家讲解。总之,我的Java之旅开始于…

冲击大厂算法面试=>链表专题【链表删除】

冲击大厂算法面试>链表专题【链表删除】 本文学习目标或者巩固的知识点 学习如何删除链表中的某个节点 如何删除valk的节点如何删除倒数第n个节点 学习如何删除链表中的某些节点 涉及头节点问题如何解决 提前说明:算法题目来自力扣、牛客等等途径 &#x1f7e…

java课设之简易版客房管理系统(mvc三层架构)

(一)、系统概述: 客房管理系统是一个用于管理酒店客房信息的程序,主要功能包括客房信息录入、客房状态查询、客房订单管理,客房的预定功能。 (二)、功能说明: 1.登录:管理…

【Pytorch】从MoCo看无监督对比学习;从SupCon看有监督对比学习

目录 无监督对比学习:Moco文章内容理解代码解释 有监督对比学习:Supervised Contrastive Learning文章内容理解 无监督对比学习:Moco 文章内容理解 以下内容全部来自于:自监督学习-MoCo-论文笔记. 侵删 论文:Momentu…

一种基于javax.max注解的能力增强技术

目录 现有框架的不足之处 我的改进内容 改进的成果 现有框架的不足之处 Max是javax.validation包中的一个常用注解,用于对传入参数进行最大值校验。但是其校验区间为闭区间,且不支持修改,如:Max(2),表示表示传入参…

【解决(几乎)任何机器学习问题】:特征选择

当你创建了成千上万个特征后,就该从中挑选出⼏个了。但是,我们绝不应该创建成百上千个⽆⽤的特征。特征过多会带来⼀个众所周知的问题,即 "维度诅咒"。如果你有很多特征,你也必须有很多训练样本来捕捉所有特征。什么是 …

DC与DCT DCG的区别

先进工艺不再wire load model进行静态时序分析,否则综合结果与后端物理电路差距很大,因此DC综合工具也进行了多次迭代,DC工具有两种模式,包括wire load mode和Topographical Mode,也就是对应的DC Expert和DC Ultra。 …

JavaScript从零写网站《一瞬》开发日志20240223

产品介绍 一个无需注册能随时发布图片并配一段文字介绍的app,有时间线,用户在主页面向下滑动,可以看到被发布的若干图片,并且能够在每一个发布处做基本互动——评论,点赞 编程语言 本产品使用htmlcssJavaScript开发…

【数据结构】每天五分钟,快速入门数据结构(二)——链表

目录 一 构建一个单向链表 二 特点 三 时间复杂度 四 相关算法 1.判断链表是否成环及成环位置 2.链表反转 五 Java中的LinkedList 类 1.使用 2.LinkedList 方法 一 构建一个单向链表 // 设计链表结构class ListNode {int val;ListNode next;ListNode(){}ListNode(int…

《UE5_C++多人TPS完整教程》学习笔记24 ——《P25 完善菜单子系统(Polishing The Menu Subsystem)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P25 完善菜单子系统(Polishing The Menu Subsystem)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版,UP主&…

TongWEB(东方通),部署WEB前后端项目步骤

我的系统: 银河麒麟桌面系统V10(SP1)(兆芯) 环境需要搭建好,什么redis,数据库等 1.准备项目前端war包 (我后端项目本就是war部署,jar转war自行百度一下吧) 进入前端打包好的dist文件夹,创建一个文件夹 WEB-INF ,再在 WEB-INF 里创建一个 web.xml 文件,文件内容: <web-…

Linux——简单的Shell程序

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、Shell程序思路二、Shell代码展示 一、Shell程序思路 用下图的时间轴来表示事件的发生次序…

经典Go知识点总结

开篇推荐 来来来,老铁们,男人女人都需要的技术活 拿去不谢:远程调试,发布网站到公网演示,远程访问内网服务,游戏联机 推荐链接 1.无论sync.Mutex还是其衍生品都会提示不能复制,但是能够编译运行 加锁后复制变量&#xff0c;会将锁的状态也复制&#xff0c;所以 mu1 其实是已…

【JVM】Java中SPI机制

打破双亲委派模型中提到SPI和JDBC相关内容&#xff0c;那么是如何打破双亲委派模型呢?本文进行一个讲解&#xff0c;在开始讲解之前&#xff0c;我们需要先了解Java中的SPI机制 是什么 SPI 全称Service Provider Interface&#xff0c;是 Java 提供的一套用来被第三方实现或…

python jupyter notebook打开页面方便使用

如果没安装jupyter, 请安装&#xff1a; pip install jupyter notebook 运行jupyter notebook jupyter notebook

“政务服务+AI交互数字人”,重新定义政务服务体验

随着AIGC发展&#xff0c;各地方政务部门纷纷通过AI交互数字人技术&#xff0c;提升企业和群众的办事效率、满意度&#xff0c;以数字人有效推动政务服务数字化、智能化发展。 *图片源于网络 如高新区将数字人海蓝作为政务服务大使&#xff0c;让数字人化身AI交互数字人可以面…

k8s-heml联动harbor 18

将打包的heml包上传到harbor仓库进行管理 创建一个公开的项目来接收传送的heml包 安装helm-push插件&#xff1a; helm plugin install https://github.com/chartmuseum/helm-push &#xff08;在线安装&#xff0c;要求网速要快或者提供科学上网&#xff09; 离线安装&…

Ansible 简介及部署 基础模块学习 ansible部署rsync 及时监控远程同步

Ansible介绍&#xff1a; Ansible 是一个配置管理系统&#xff0c;当下最流行的批量自动化运维工具之一&#xff0c;它是一款开源的自动化工具&#xff0c;基于Python开发的配置管理和应用部署的工具。 Ansible 是基于模块工作的&#xff0c;它只是提供了一种运行框架&#xff…

5G网络建设 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 现需要在某城市进行5G网络建设&#xff0c;已经选取N个地点设置5G基站&#xff0c;编号固定为1到N&#xff0c; 接下来需要各个基站之间使用光纤进行连接以确保基…

Stable Diffusion 绘画入门教程(webui)-ControlNet(IP2P)

上篇文章介绍了深度Depth&#xff0c;这篇文章介绍下IP2P&#xff08;InstructP2P&#xff09;, 通俗理解就是图生图&#xff0c;给原有图加一些效果,比如下图&#xff0c;左边为原图&#xff0c;右边为增加了效果的图&#xff1a; 文章目录 一、选大模型二、写提示词三、基础参…