300分钟吃透分布式缓存-10讲:MC是怎么定位key的?

我们在进行 Mc 架构剖析时,除了学习 Mc 的系统架构、网络模型、状态机外,还对 Mc 的 slab 分配、Hashtable、LRU 有了简单的了解。本节课,将进一步深入学习这些知识点。

接下来,进入 Memcached 进阶的学习。会讲解 Mc 是如何进行 key 定位,如何淘汰回收过期失效 key 的,还将分析 Mc 的内存管理 slab 机制,以及 Mc 进行数据存储维护的关键机理,最后还会对 Mc 进行完整的协议分析,并以 Java 语言为例,介绍 Mc 常用的 client,以及如何进行调优及改进。

key 定位

哈希表

Mc 将数据存储在 Item 中,然后这些 Item 会被 slabclass 的 4 个 LRU 管理。这些 LRU 都是通过双向链表实现数据记录的。双向链表在进行增加、删除、修改位置时都非常高效,但其获取定位 key 的性能非常低下,只能通过链表遍历来实现。因此,Mc 还通过 Hashtable,也就是哈希表,来记录管理这些 Item,通过对 key 进行哈希计算,从而快速定位和读取这些 key/value 所在的 Item,如下图所示。
在这里插入图片描述
哈希表也称散列表,可以通过把 key 映射到哈希表中的一个位置来快速访问记录,定位 key 的时间复杂度只有 O(1)。Mc 的哈希表实际是一个一维指针数组,数组的每个位置称作一个 bucket,即一个桶。性能考虑的需要,Mc 的哈希表的长度设置为 2 的 N 次方。Mc 启动时,默认会构建一个拥有 6.4万 个桶的哈希表,随着新 key 的不断插入,哈希表中的元素超过阀值后,会对哈希表进行扩容,最大可以构建 2 的 32 次方个桶的哈希表,也就是说 Mc 哈希表经过多次扩容后,最多只能有不超过 43亿 个桶。

哈希表设计

对于哈希表设计,有 2 个关键点,一个是哈希算法,一个是哈希冲突解决方案。Mc 使用的哈希算法有 2 种,分别是 Murmur3 Hash 和 Jenkins Hash。Mc 当前版本,默认使用 Murmur3 Hash 算法。不同的 key 通过 Hash 计算,被定位到了相同的桶,这就是哈希冲突。Mc 是通过对每个桶启用一个单向链表,来解决哈希冲突问题的。

定位 key

Memcached 定位 key 时,首先根据 key 采用 Murmur3 或者 Jenkins 算法进行哈希计算,得到一个 32 位的无符号整型输出,存储到变量 hv 中。因为哈希表一般没有 2^32 那么大,所以需要将 key 的哈希值映射到哈希表的范围内。Mc 采用最简单的取模算法作为映射函数,即采用 hv%hashsize 进行计算。由于普通的取模运算比较耗时,所以 Mc 将哈希表的长度设置为 2 的 n 次方,采用位运算进行优化,即采用 hv&hashmask 来计算。hashmask 即 2 的 n 次方 减 1。

定位到 key 所在的桶的位置后,如果是插入一个新数据,则将数据 Item 采用头部插入法插入桶的单向链表中。如果是查找,则轮询对应哈希桶中的那个单向链表,依次比对 key 字符串,key 相同则找到数据 Item。
在这里插入图片描述
如果哈希表桶中元素太多,这个链表轮询耗时会比较长,所以在哈希表中元素达到桶数的 1.5 倍之后,Mc 会对哈希表进行 2 倍扩容。由于哈希表最多只有 43 亿左右个桶,所以性能考虑,单个 Mc 节点最多存储 65亿 个 key/value。如果要存更多 key,则需要修改 Mc 源码,将最大哈希,即 HASHPOWER_MAX, 进行调大设置。

哈希表扩容

当 Mc 的哈希表中,Item 数量大于 1.5 倍的哈希桶数量后,Mc 就对哈希表进行扩容处理。如下图所示,Mc 的哈希扩容是通过哈希维护线程进行处理的。准备开始扩容时,哈希维护线程会首先将所有 IO 工作线程和辅助线程进行暂停,其中辅助线程包括 LRU 维护线程、slab 维护线程、LRU 爬虫线程。待这些线程暂停后,哈希维护线程会将当前的主哈希表设为旧哈希表,然后将新的主哈希表扩容之前的 2 倍容量。然后,工作线程及辅助线程继续工作,同时哈希维护线程开始逐步将 Item 元素从旧哈希表迁移到主哈希表。
在这里插入图片描述
Mc 在启动时,会根据设置的工作线程数,来构建 一个 Item 锁哈希表,线程越多,构建的锁哈希表越大,对于 4 个线程,锁哈希表有 4096 个桶,对于 10 个线程,锁哈希表会有 8192 个桶,Item 锁哈希表最多有 32k 个桶,1k 是 1024,即最多即 32768 个桶。Mc 的锁哈希表中,每个桶对应一个 Item 锁,所以 Mc 最多只有 32768 个 Item 锁。

Mc 哈希表在读取、变更以及扩容迁移过程中,先将 key hash 定位到 Item 锁哈希表的锁桶,然后对 Item 锁进行加锁,然后再进行实际操作。实际上,除了在哈希表,在其他任何时候,只要涉及到在对 Item 的操作,都会根据 Item 中的 key,进行 Item 哈希锁桶加锁,以避免 Item 被同时读写而产生脏数据。Mc 默认有 4096 个锁桶,所以对 key 加锁时,冲突的概率较小,而且 Mc 全部是内存操作,操作速度很快,即便申请时锁被占用,也会很快被释放。

Mc 哈希表在扩容时,哈希表维护线程,每次按 桶链表纬度 迁移,即一次迁移一个桶里单向链表的所有 Item 元素。在扩容过程中,如果要查找或插入 key,会参照迁移位置选择哈希表。如果 key 对应的哈希桶在迁移位置之前,则到新的主哈希表进行查询或插入,否则到旧哈希表进行查询和插入。待全部扩容迁移完毕,所有的处理就会全部在新的主哈希表进行。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UIKit 在 UICollectionView 中拖放交换 Cell 视图的极简实现

概览 UIKit 中的 UICollectionView 视图是我们显示多列集合数据的不二选择,而丰富多彩的交互操作更是我们选择 UICollectionView 视图的另一个重要原因。 如上图所示:我们实现了在 UICollectionView 中拖放交换任意两个 Cell 子视图的功能,这…

YOLOv9来了! 使用可编程梯度信息学习你想学的内容, v7作者新作!【文献速读】

YOLOv9文献速读,本文章使用 GPT 4.0 和 Ai PDF 工具完成。 文章地址:https://arxiv.org/pdf/2402.13616.pdf 文章目录 文章简介有哪些相关研究?如何归类?谁是这一课题在领域内值得关注的研究员?论文试图解决什么问题&a…

实现律所高质量发展-Alpha法律智能操作系统

律师行业本质上属于服务行业,而律师团队作为一个独立的服务单位,应当包含研发、市场、销售、服务等单位发展的基础工作环节。但现实中,很多律师团队其实并没有区分这些工作。鉴于此,上海市锦天城律师事务所医药大健康行业资本市场…

2.22 day3、4 QT

完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示"登录成功”,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密码不匹配&…

MIT-6.824-Lab2,Raft部分笔记|Use Go

文章目录 前记Paper6:RaftLEC5、6:RaftLAB22AtaskHintlockingstructureguide设计与编码 2BtaskHint设计与编码 2CtaskHint question后记 LEC5:GO, Threads, and Raftgo threads技巧raft实验易错点debug技巧 前记 趁着研一考完期末有点点空余…

十四、图像几何形状绘制

项目功能实现&#xff1a;矩形、圆形、椭圆等几何形状绘制&#xff0c;并与原图进行相应比例融合 按照之前的博文结构来&#xff0c;这里就不在赘述了 一、头文件 drawing.h #pragma once#include<opencv2/opencv.hpp>using namespace cv;class DRAWING { public:void…

“最会写”的中文大模型Weaver来了,中文创意写作能力超GPT-4

分享&#xff5c; Weaver ChatGPT等通用大模型支持的功能成百上千&#xff0c;但是对于普通日常用户来说&#xff0c;智能写作一定是最常见的&#xff0c;也是大模型最能真正帮上忙的使用场景之一。尽管大模型经常能写出看起来像模像样的文字&#xff0c;但是大多数情况下内容…

详细·Kubeadm安装

目录 实验前准备部署K8S集群初始化kubeadm&#xff08;只需要master做&#xff09;部署网络插件flannel测试 pod 资源创建 测试访问部署Dashboard&#xff08;master01&#xff09;浏览器访问 实验前准备 master&#xff1a;192.168.188.11 node01&#xff1a;192.168.188.13 …

Code Composer Studio (CCS) - 全局搜索功能

Code Composer Studio [CCS] - 全局搜索功能 1. Ctrl H&#xff0c;全局搜索功能References 1. Ctrl H&#xff0c;全局搜索功能 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

如何用代理IP防止被泄露真实IP地址?

随着互联网的普及&#xff0c;我们的网络行为越来越离不开IP地址。然而&#xff0c;由于一些不法分子利用IP地址进行网络攻击、窃取个人信息等行为&#xff0c;保护我们的真实IP地址变得尤为重要。代理IP地址是一种隐藏真实IP地址的方法&#xff0c;通过使用代理服务器来中转网…

Cartographer 栅格地图更新

栅格地图更新过程 首先来了一帧雷达数据&#xff0c;对应到每一个栅格点&#xff0c;即观测得到该栅格点是occupied或者是Free。 在cartographer中&#xff0c;使用CorrespondenceCostValue&#xff08;整数表示的空闲概率&#xff09;表示栅格状态&#xff0c;所以现在的目的就…

学习鸿蒙背后的价值?星河版开放如何学习?

现在是2024年&#xff0c;华为在1月18开展了鸿蒙千帆起仪式发布会。宣布了鸿蒙星河版&#xff0c;并对开发者开放申请&#xff0c;此次发布会主要是说明了&#xff0c;鸿蒙已经是全栈自研底座&#xff0c;鸿蒙星河版本的编程语言改为ArkTS/仓颉&#xff0c;内核改为鸿蒙原生内核…

5.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-测试需求与需求拆解

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;模拟游戏登陆器启动游戏并且完成注入 首先正常分析软件程序有没有漏洞&#xff0c;需要通过它的操作侵入&#xff0c;比如买东西&#xff0c;就通过买东西的按钮它背后有源代码就看源代码&#xff0c…

开启MySQL远程访问权限,允许远程连接

1、登录mysql数据库 mysql -u root –p 如果端口不是默认的3306&#xff0c;此处端口为3308&#xff0c;使用该指令&#xff1a; mysql –u root –port3308 -p 2、输入密码&#xff1a; 3、使用mysql&#xff0c;查看user表 use mysql; 4、查询user表&#xff0c;root账…

SpringBoot启动报错:Failed to load property source from ‘file:/D:.....

SpringBoot启动报错&#xff1a;Failed to load property source from file:/D:… SpringBoot启动爆如图的错误 2024-02-22 20:57:42.865 ERROR 23024 --- [ restartedMain] o.s.boot.SpringApplication : Application run failedjava.lang.IllegalStateExce…

Centos7环境下安装Docker详细步骤

目录 0.前言 1.卸载旧版 2.配置Docker的yum库 3.安装Docker 4.启动和校验 5.配置镜像加速 5.1.注册阿里云账号 5.2.开通镜像服务 5.3.配置镜像加速 0.前言 环境&#xff1a;Centos7 推荐&#xff1a;买个Centos7阿里或者腾讯云服务&#xff0c;这样就可以不用安装虚…

智慧养老驿站健康监测系统场景需求和技术要求

场景建设需求 1.场景建设核心任务目标 搭建养老驿站的健康检测系统平台&#xff0c;以智慧化手段整合数据、视屏、物联设备&#xff0c;全方位提升对政府、老人、养老机构、服务机构、服务人员等对象的服务支撑能力&#xff0c;赋能居家养老、社区养老、机构养老等多种养老模…

消息中间件之RocketMQ源码分析(十二)

Namesrv启动流程 Broker启动流程 BrokerStartup.java类主要负责为真正的启动过程做准备&#xff0c;解析脚本传过来的参数&#xff0c;初始化Broker配置&#xff0c;创建BrokerController实例等工作。BrokerController.java类是Broker的掌控者&#xff0c;它管理和控制Broker的…

2.21 Qt day2 菜单栏/工具栏/状态栏/浮动窗口、UI界面、信号与槽

思维导图 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;…

【Java 面试题】MySQL与Redis 如何保证双写一致性

目录 方案一:延时双删方案二: 删除缓存重试机制方案三:读取biglog异步删除缓存系列文章版本记录方案一:延时双删 延时双删流程 先删除缓存再更新数据库休眠一会(比如1秒),再次删除缓存。这个休眠一会,一般多久呢?都是1秒? 这个休眠时间 = 读业务逻辑数据